defmodule SimpleshopThemeWeb.Admin.ProvidersTest do
  use SimpleshopThemeWeb.ConnCase, async: false

  import Phoenix.LiveViewTest
  import SimpleshopTheme.AccountsFixtures
  import SimpleshopTheme.ProductsFixtures
  import Mox

  alias SimpleshopTheme.Providers.MockProvider

  setup :verify_on_exit!

  setup do
    user = user_fixture()
    %{user: user}
  end

  # -- Index page --

  describe "index - unauthenticated" do
    test "redirects to login", %{conn: conn} do
      {:error, redirect} = live(conn, ~p"/admin/providers")
      assert {:redirect, %{to: path}} = redirect
      assert path == ~p"/users/log-in"
    end
  end

  describe "index - empty state" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "shows empty state when no connections exist", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/providers")

      assert html =~ "Connect your Printify account"
    end

    test "shows connect button", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/providers")

      assert has_element?(view, ~s(a[href="/admin/providers/new"]))
    end
  end

  describe "index - with connection" do
    setup %{conn: conn, user: user} do
      connection =
        provider_connection_fixture(%{
          provider_type: "printify",
          name: "My Printify Shop"
        })

      %{conn: log_in_user(conn, user), connection: connection}
    end

    test "lists provider connections", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/providers")

      assert html =~ "Printify"
      assert html =~ "My Printify Shop"
    end

    test "shows edit link", %{conn: conn, connection: connection} do
      {:ok, view, _html} = live(conn, ~p"/admin/providers")

      assert has_element?(view, ~s(a[href="/admin/providers/#{connection.id}/edit"]))
    end

    test "shows product count", %{conn: conn, connection: connection} do
      product_fixture(%{provider_connection: connection})

      {:ok, _view, html} = live(conn, ~p"/admin/providers")

      assert html =~ "1 product"
    end

    test "shows never synced warning", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/providers")

      assert html =~ "Never synced"
    end
  end

  describe "index - delete" do
    setup %{conn: conn, user: user} do
      connection =
        provider_connection_fixture(%{
          provider_type: "printify",
          name: "Delete Me Shop"
        })

      %{conn: log_in_user(conn, user), connection: connection}
    end

    test "deletes connection and shows flash", %{conn: conn, connection: connection} do
      {:ok, view, _html} = live(conn, ~p"/admin/providers")

      html = render_click(view, "delete", %{"id" => to_string(connection.id)})

      assert html =~ "Provider connection deleted"
      refute html =~ "Delete Me Shop"
    end
  end

  describe "index - sync" do
    setup %{conn: conn, user: user} do
      Application.put_env(:simpleshop_theme, :provider_modules, %{
        "printify" => MockProvider
      })

      on_exit(fn -> Application.delete_env(:simpleshop_theme, :provider_modules) end)

      connection =
        provider_connection_fixture(%{
          provider_type: "printify",
          name: "Sync Test Shop"
        })

      %{conn: log_in_user(conn, user), connection: connection}
    end

    test "starts sync and shows flash", %{conn: conn, connection: connection} do
      stub(MockProvider, :fetch_products, fn _conn -> {:ok, []} end)

      {:ok, view, _html} = live(conn, ~p"/admin/providers")

      html = render_click(view, "sync", %{"id" => to_string(connection.id)})

      assert html =~ "Sync started"
    end
  end

  # -- Form page --

  describe "form - new" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "renders new form", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/providers/new")

      assert html =~ "Connect to Printify"
      assert html =~ "connection key"
      assert html =~ "Log in to Printify"
    end

    test "test connection shows error when no api key", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/providers/new")

      html = render_click(view, "test_connection")

      assert html =~ "Please enter your connection key"
    end

    test "saves new connection", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/providers/new")

      {:ok, _view, html} =
        view
        |> form("#provider-form", %{
          "provider_connection" => %{
            "api_key" => "test_key_123"
          }
        })
        |> render_submit()
        |> follow_redirect(conn, ~p"/admin/settings")

      assert html =~ "Connected to Printify"
    end
  end

  describe "form - test connection" do
    setup %{conn: conn, user: user} do
      Application.put_env(:simpleshop_theme, :provider_modules, %{
        "printify" => MockProvider
      })

      on_exit(fn -> Application.delete_env(:simpleshop_theme, :provider_modules) end)

      %{conn: log_in_user(conn, user)}
    end

    test "shows success when connection is valid", %{conn: conn} do
      expect(MockProvider, :test_connection, fn _conn ->
        {:ok, %{shop_name: "My Printify Shop", shop_id: 12345}}
      end)

      {:ok, view, _html} = live(conn, ~p"/admin/providers/new")

      # Validate first to set pending_api_key
      view
      |> form("#provider-form", %{
        "provider_connection" => %{"api_key" => "valid_key_123"}
      })
      |> render_change()

      html = render_click(view, "test_connection")

      assert html =~ "Connected to My Printify Shop"
    end

    test "shows error when connection fails", %{conn: conn} do
      expect(MockProvider, :test_connection, fn _conn ->
        {:error, :unauthorized}
      end)

      {:ok, view, _html} = live(conn, ~p"/admin/providers/new")

      view
      |> form("#provider-form", %{
        "provider_connection" => %{"api_key" => "bad_key"}
      })
      |> render_change()

      html = render_click(view, "test_connection")

      assert html =~ "doesn&#39;t seem to be valid"
    end
  end

  describe "form - edit" do
    setup %{conn: conn, user: user} do
      connection =
        provider_connection_fixture(%{
          provider_type: "printify",
          name: "Edit Me Shop"
        })

      %{conn: log_in_user(conn, user), connection: connection}
    end

    test "renders edit form", %{conn: conn, connection: connection} do
      {:ok, _view, html} = live(conn, ~p"/admin/providers/#{connection.id}/edit")

      assert html =~ "Printify settings"
      assert html =~ "Connection enabled"
      assert html =~ "Save changes"
    end

    test "saves changes", %{conn: conn, connection: connection} do
      {:ok, view, _html} = live(conn, ~p"/admin/providers/#{connection.id}/edit")

      {:ok, _view, html} =
        view
        |> form("#provider-form", %{
          "provider_connection" => %{"enabled" => "true"}
        })
        |> render_submit()
        |> follow_redirect(conn, ~p"/admin/settings")

      assert html =~ "Settings saved"
    end
  end
end
