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

  import Phoenix.LiveViewTest
  import Berrypod.AccountsFixtures

  alias Berrypod.{Mailer, Settings}

  setup do
    # Ensure mailer starts as test adapter and restore on exit
    original = Application.get_env(:berrypod, Berrypod.Mailer)
    Application.put_env(:berrypod, Berrypod.Mailer, adapter: Swoosh.Adapters.Test)

    on_exit(fn ->
      Application.put_env(:berrypod, Berrypod.Mailer, original)
    end)

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

  describe "authenticated" do
    setup %{conn: conn, user: user} do
      conn = log_in_user(conn, user)
      %{conn: conn}
    end

    test "renders email settings page with provider cards", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/settings/email")

      assert html =~ "Email settings"
      assert html =~ "Email provider"
      # Provider names rendered as radio cards
      assert html =~ "Postmark"
      assert html =~ "Brevo"
      assert html =~ "Mailjet"
      assert html =~ "MailPace"
      assert html =~ "Postal"
    end

    test "shows provider descriptions", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/settings/email")

      assert html =~ "Excellent deliverability tracking"
      assert html =~ "All-in-one platform, GDPR-friendly"
      assert html =~ "EU data processing"
    end

    test "selecting a provider shows its config fields", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/settings/email")

      # Select SMTP via form change (radio inputs fire phx-change)
      html =
        view
        |> form("form[phx-change=\"change_adapter\"]", %{email: %{adapter: "smtp"}})
        |> render_change()

      assert html =~ "Server host"
      assert html =~ "Port"
      assert html =~ "Username"
      assert html =~ "Password"
    end

    test "selecting a different provider shows different fields", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/settings/email")

      # Select Mailgun which needs api_key + domain
      html =
        view
        |> form("form[phx-change=\"change_adapter\"]", %{email: %{adapter: "mailgun"}})
        |> render_change()

      assert html =~ "API key"
      assert html =~ "Domain"
    end

    test "saving config persists settings", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/settings/email")

      # Select Postmark via form change
      view
      |> form("form[phx-change=\"change_adapter\"]", %{email: %{adapter: "postmark"}})
      |> render_change()

      # Submit with an API key
      html =
        view
        |> form("form[phx-submit=\"save\"]", %{
          email: %{adapter: "postmark", api_key: "pm_test_123"}
        })
        |> render_submit()

      assert html =~ "Email settings saved"
      assert Settings.get_setting("email_adapter") == "postmark"
    end

    test "saving without required fields shows error", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/settings/email")

      # Select Postmark
      view
      |> form("form[phx-change=\"change_adapter\"]", %{email: %{adapter: "postmark"}})
      |> render_change()

      # Submit without API key
      html =
        view
        |> form("form[phx-submit=\"save\"]", %{email: %{adapter: "postmark", api_key: ""}})
        |> render_submit()

      assert html =~ "Missing required fields"
    end

    test "disconnect clears email configuration", %{conn: conn} do
      Settings.put_setting("email_adapter", "postmark")
      Settings.put_secret("email_postmark_api_key", "pm_test_abc")

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

      html = render_click(view, "disconnect")

      assert html =~ "Email provider disconnected"
      assert is_nil(Settings.get_setting("email_adapter"))
    end

    test "shows test email section when configured", %{conn: conn} do
      Settings.put_setting("email_adapter", "postmark")
      Settings.put_secret("email_postmark_api_key", "pm_test_abc")

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

      assert html =~ "Test email"
      assert html =~ "Send test email"
    end

    test "hides test email section when not configured", %{conn: conn} do
      # Ensure clean state — no adapter configured
      Settings.delete_setting("email_adapter")
      Application.put_env(:berrypod, Berrypod.Mailer, adapter: Swoosh.Adapters.Local)

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

      refute html =~ "Send test email"
    end

    test "sending test email sets verified flag", %{conn: conn} do
      Settings.put_setting("email_adapter", "postmark")
      Settings.put_secret("email_postmark_api_key", "pm_test_abc")

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

      html = render_click(view, "send_test")

      assert html =~ "Test email sent"
      assert Mailer.email_verified?()
    end

    test "saving config clears verified flag", %{conn: conn} do
      Mailer.mark_email_verified()
      assert Mailer.email_verified?()

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

      view
      |> form("form[phx-change=\"change_adapter\"]", %{email: %{adapter: "postmark"}})
      |> render_change()

      view
      |> form("form[phx-submit=\"save\"]", %{
        email: %{adapter: "postmark", api_key: "pm_new_key"}
      })
      |> render_submit()

      refute Mailer.email_verified?()
    end

    test "disconnecting clears verified flag", %{conn: conn} do
      Settings.put_setting("email_adapter", "postmark")
      Settings.put_secret("email_postmark_api_key", "pm_test_abc")
      Mailer.mark_email_verified()
      assert Mailer.email_verified?()

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

      render_click(view, "disconnect")

      refute Mailer.email_verified?()
    end
  end

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