defmodule Berrypod.Setup do
  @moduledoc """
  Aggregates setup status checks for the setup flow and launch checklist.
  """

  alias Berrypod.{Accounts, Mailer, Orders, Products, Settings, Shipping}

  @setup_secret_key :berrypod_setup_secret

  @doc """
  Returns the setup secret for first-run admin creation.

  In prod, gates access to the setup form so only someone with server access
  (log output or SETUP_SECRET env var) can create the admin account.

  Reads from SETUP_SECRET env var first, otherwise auto-generates a random
  token and stores it in :persistent_term for the lifetime of the node.
  """
  def setup_secret do
    case System.get_env("SETUP_SECRET") do
      nil ->
        case :persistent_term.get(@setup_secret_key, nil) do
          nil ->
            secret =
              :crypto.strong_rand_bytes(16)
              |> Base.url_encode64(padding: false)

            :persistent_term.put(@setup_secret_key, secret)
            secret

          secret ->
            secret
        end

      secret ->
        secret
    end
  end

  @doc """
  Returns whether the setup secret gate should be shown.

  True in prod when no admin exists. False in dev/test.
  """
  def require_setup_secret? do
    Application.get_env(:berrypod, :env, :dev) == :prod and not Accounts.has_admin?()
  end

  @doc """
  Returns a map describing the current setup status.

  Used by the setup page, dashboard launch checklist, and ThemeHook gate.

  ## Setup phase (connections)

    * `admin_created` — at least one user exists
    * `provider_connected` — a provider connection with an API key exists
    * `provider_type` — the connected provider's type (e.g. "printify"), or nil
    * `stripe_connected` — Stripe API key is stored
    * `setup_complete` — all three connections made

  ## Launch checklist phase

    * `products_synced` / `product_count` — products imported
    * `has_shipping` — at least one shipping rate exists
    * `theme_customised` — theme settings have been saved at least once
    * `has_orders` — at least one paid order exists
    * `email_configured` — email adapter configured and verified
    * `site_live` — shop is open to the public
    * `can_go_live` — minimum requirements met to go live (includes shipping)
    * `checklist_dismissed` — admin has dismissed the launch checklist
  """
  def setup_status do
    conn = Products.get_first_provider_connection()
    product_count = Products.count_products()

    provider_connected = conn != nil
    products_synced = product_count > 0
    stripe_connected = Settings.has_secret?("stripe_api_key")
    admin_created = Accounts.has_admin?()
    site_live = Settings.site_live?()
    has_shipping = Shipping.has_shipping_rates?()

    %{
      # Setup phase
      admin_created: admin_created,
      provider_connected: provider_connected,
      provider_type: conn && conn.provider_type,
      stripe_connected: stripe_connected,
      setup_complete: admin_created and provider_connected and stripe_connected,

      # Launch checklist
      products_synced: products_synced,
      product_count: product_count,
      has_shipping: has_shipping,
      theme_customised: Settings.get_setting("theme_customised", false) == true,
      has_orders: Orders.has_paid_orders?(),
      email_configured: Mailer.email_configured?(),
      site_live: site_live,
      can_go_live: provider_connected and products_synced and stripe_connected and has_shipping,
      checklist_dismissed: Settings.get_setting("checklist_dismissed", false) == true
    }
  end
end
