defmodule SimpleshopThemeWeb.AdminLive.Settings do
  use SimpleshopThemeWeb, :live_view

  alias SimpleshopTheme.Settings
  alias SimpleshopTheme.Stripe.Setup, as: StripeSetup

  @impl true
  def mount(_params, _session, socket) do
    {:ok, socket |> assign(:page_title, "Credentials") |> assign_stripe_state()}
  end

  defp assign_stripe_state(socket) do
    has_key = Settings.has_secret?("stripe_api_key")
    has_signing = Settings.has_secret?("stripe_signing_secret")

    status =
      cond do
        !has_key -> :not_configured
        has_key && StripeSetup.localhost?() -> :connected_localhost
        true -> :connected
      end

    socket
    |> assign(:stripe_status, status)
    |> assign(:stripe_api_key_hint, Settings.secret_hint("stripe_api_key"))
    |> assign(:stripe_signing_secret_hint, Settings.secret_hint("stripe_signing_secret"))
    |> assign(:stripe_webhook_url, StripeSetup.webhook_url())
    |> assign(:stripe_has_signing_secret, has_signing)
    |> assign(:connect_form, to_form(%{"api_key" => ""}, as: :stripe))
    |> assign(:secret_form, to_form(%{"signing_secret" => ""}, as: :webhook))
    |> assign(:advanced_open, false)
    |> assign(:connecting, false)
  end

  @impl true
  def handle_event("connect_stripe", %{"stripe" => %{"api_key" => api_key}}, socket) do
    if api_key == "" do
      {:noreply, put_flash(socket, :error, "Please enter your Stripe secret key")}
    else
      socket = assign(socket, :connecting, true)

      case StripeSetup.connect(api_key) do
        {:ok, :webhook_created} ->
          socket =
            socket
            |> assign_stripe_state()
            |> put_flash(:info, "Stripe connected and webhook endpoint created")

          {:noreply, socket}

        {:ok, :localhost} ->
          socket =
            socket
            |> assign_stripe_state()
            |> put_flash(
              :info,
              "API key saved. Enter a webhook signing secret below for local testing."
            )

          {:noreply, socket}

        {:error, message} ->
          socket =
            socket
            |> assign(:connecting, false)
            |> put_flash(:error, "Stripe connection failed: #{message}")

          {:noreply, socket}
      end
    end
  end

  def handle_event("disconnect_stripe", _params, socket) do
    StripeSetup.disconnect()

    socket =
      socket
      |> assign_stripe_state()
      |> put_flash(:info, "Stripe disconnected")

    {:noreply, socket}
  end

  def handle_event("save_signing_secret", %{"webhook" => %{"signing_secret" => secret}}, socket) do
    if secret == "" do
      {:noreply, put_flash(socket, :error, "Please enter a signing secret")}
    else
      StripeSetup.save_signing_secret(secret)

      socket =
        socket
        |> assign_stripe_state()
        |> put_flash(:info, "Webhook signing secret saved")

      {:noreply, socket}
    end
  end

  def handle_event("toggle_advanced", _params, socket) do
    {:noreply, assign(socket, :advanced_open, !socket.assigns.advanced_open)}
  end

  @impl true
  def render(assigns) do
    ~H"""
    <Layouts.app flash={@flash} current_scope={@current_scope}>
      <div class="max-w-2xl">
        <.header>
          Credentials
          <:subtitle>Connect payment providers and manage API keys</:subtitle>
        </.header>

        <section class="mt-10">
          <div class="flex items-center gap-3">
            <h2 class="text-lg font-semibold">Stripe</h2>
            <%= case @stripe_status do %>
              <% :connected -> %>
                <span class="inline-flex items-center gap-1 rounded-full bg-green-50 px-2 py-1 text-xs font-medium text-green-700 ring-1 ring-green-600/20 ring-inset">
                  <.icon name="hero-check-circle-mini" class="size-3" /> Connected
                </span>
              <% :connected_localhost -> %>
                <span class="inline-flex items-center gap-1 rounded-full bg-amber-50 px-2 py-1 text-xs font-medium text-amber-700 ring-1 ring-amber-600/20 ring-inset">
                  <.icon name="hero-exclamation-triangle-mini" class="size-3" /> Dev mode
                </span>
              <% :not_configured -> %>
                <span class="inline-flex items-center gap-1 rounded-full bg-zinc-50 px-2 py-1 text-xs font-medium text-zinc-600 ring-1 ring-zinc-500/10 ring-inset">
                  Not connected
                </span>
            <% end %>
          </div>

          <%= if @stripe_status == :not_configured do %>
            <.stripe_setup_form connect_form={@connect_form} connecting={@connecting} />
          <% else %>
            <.stripe_connected_view
              stripe_status={@stripe_status}
              stripe_api_key_hint={@stripe_api_key_hint}
              stripe_webhook_url={@stripe_webhook_url}
              stripe_signing_secret_hint={@stripe_signing_secret_hint}
              stripe_has_signing_secret={@stripe_has_signing_secret}
              secret_form={@secret_form}
              advanced_open={@advanced_open}
            />
          <% end %>
        </section>
      </div>
    </Layouts.app>
    """
  end

  defp stripe_setup_form(assigns) do
    ~H"""
    <div class="mt-4">
      <p class="text-sm text-zinc-600">
        To accept payments, connect your Stripe account by entering your secret key.
        You can find it in your
        <a
          href="https://dashboard.stripe.com/apikeys"
          target="_blank"
          rel="noopener"
          class="text-zinc-900 underline"
        >
          Stripe dashboard
        </a>
        under Developers &rarr; API keys.
      </p>

      <.form for={@connect_form} phx-submit="connect_stripe" class="mt-6">
        <.input
          field={@connect_form[:api_key]}
          type="password"
          label="Secret key"
          autocomplete="off"
          placeholder="sk_test_... or sk_live_..."
        />
        <p class="text-xs text-zinc-500 mt-1">
          Starts with <code>sk_test_</code> (test mode) or <code>sk_live_</code> (live mode).
          This key is encrypted at rest in the database.
        </p>
        <div class="mt-4">
          <.button phx-disable-with="Connecting...">
            Connect Stripe
          </.button>
        </div>
      </.form>
    </div>
    """
  end

  defp stripe_connected_view(assigns) do
    ~H"""
    <div class="mt-4 space-y-4">
      <dl class="text-sm">
        <div class="flex gap-2 py-1">
          <dt class="text-zinc-500 w-28 shrink-0">API key</dt>
          <dd><code class="text-zinc-700">{@stripe_api_key_hint}</code></dd>
        </div>
        <div class="flex gap-2 py-1">
          <dt class="text-zinc-500 w-28 shrink-0">Webhook URL</dt>
          <dd><code class="text-zinc-700 text-xs break-all">{@stripe_webhook_url}</code></dd>
        </div>
        <div class="flex gap-2 py-1">
          <dt class="text-zinc-500 w-28 shrink-0">Webhook secret</dt>
          <dd>
            <%= if @stripe_has_signing_secret do %>
              <code class="text-zinc-700">{@stripe_signing_secret_hint}</code>
            <% else %>
              <span class="text-amber-600">Not set</span>
            <% end %>
          </dd>
        </div>
      </dl>

      <%= if @stripe_status == :connected_localhost do %>
        <div class="rounded-md bg-amber-50 p-4 ring-1 ring-amber-600/10 ring-inset">
          <p class="text-sm text-amber-800">
            Stripe can't reach localhost for webhooks. For local testing, run the Stripe CLI:
          </p>
          <pre class="mt-2 rounded bg-amber-100 p-2 text-xs text-amber-900 overflow-x-auto">stripe listen --forward-to localhost:4000/webhooks/stripe</pre>
          <p class="mt-2 text-xs text-amber-700">
            The CLI will output a signing secret starting with <code>whsec_</code>. Enter it below.
          </p>
        </div>

        <.form for={@secret_form} phx-submit="save_signing_secret" class="mt-2">
          <.input
            field={@secret_form[:signing_secret]}
            type="password"
            label="Webhook signing secret"
            autocomplete="off"
            placeholder="whsec_..."
          />
          <div class="mt-3">
            <.button phx-disable-with="Saving...">Save signing secret</.button>
          </div>
        </.form>
      <% else %>
        <div class="border-t border-zinc-200 pt-3">
          <button
            phx-click="toggle_advanced"
            class="flex items-center gap-1 text-sm text-zinc-500 hover:text-zinc-700"
          >
            <.icon
              name={if @advanced_open, do: "hero-chevron-down-mini", else: "hero-chevron-right-mini"}
              class="size-4"
            /> Advanced
          </button>

          <%= if @advanced_open do %>
            <div class="mt-3">
              <p class="text-xs text-zinc-500 mb-3">
                Override the webhook signing secret if you need to use a custom endpoint or the Stripe CLI.
              </p>
              <.form for={@secret_form} phx-submit="save_signing_secret">
                <.input
                  field={@secret_form[:signing_secret]}
                  type="password"
                  label="Webhook signing secret"
                  autocomplete="off"
                  placeholder="whsec_..."
                />
                <div class="mt-3">
                  <.button phx-disable-with="Saving...">Save signing secret</.button>
                </div>
              </.form>
            </div>
          <% end %>
        </div>
      <% end %>

      <div class="border-t border-zinc-200 pt-4">
        <button
          phx-click="disconnect_stripe"
          data-confirm="This will remove your Stripe API key and delete the webhook endpoint. Are you sure?"
          class="text-sm text-red-600 hover:text-red-800"
        >
          Disconnect Stripe
        </button>
      </div>
    </div>
    """
  end
end
