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

  import Phoenix.LiveViewTest
  import Berrypod.AccountsFixtures
  import Berrypod.ProductsFixtures
  import Mox

  alias Berrypod.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 a print-on-demand provider"
    end

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

      assert has_element?(view, ~s(a[href="/admin/providers/new?type=printify"]))
      assert has_element?(view, ~s(a[href="/admin/providers/new?type=printful"]))
    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(:berrypod, :provider_modules, %{
        "printify" => MockProvider
      })

      on_exit(fn -> Application.delete_env(:berrypod, :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
      Application.put_env(:berrypod, :provider_modules, %{
        "printify" => MockProvider
      })

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

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

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

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

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

      assert html =~ "Connect to Printful"
      assert html =~ "Printful API key"
      assert html =~ "Log in to Printful"
    end

    test "defaults to Printify when no type param", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/providers/new")

      assert html =~ "Connect to Printify"
    end

    test "saves new connection", %{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")

      # Printify uses 36-character UUID format keys
      valid_uuid_key = "12345678-1234-1234-1234-123456789012"

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

      assert html =~ "Connected to Printify"
    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
