defmodule ToweropsWeb.AccountLive.TotpEnrollment do
  @moduledoc """
  LiveView for mandatory TOTP enrollment during user registration.

  New users must enroll a TOTP device before accessing the application.
  """
  use ToweropsWeb, :live_view

  alias Towerops.Accounts

  @impl true
  def mount(_params, _session, socket) do
    require Logger

    user = socket.assigns.current_scope.user

    # If user already has TOTP enabled, redirect them
    if Accounts.totp_enabled?(user) do
      {:ok, redirect(socket, to: ~p"/devices")}
    else
      # Only generate secret when socket is connected
      # On initial render (disconnected), use temporary placeholder
      if connected?(socket) do
        # Generate secret once per LiveView process
        # IMPORTANT: If you refresh this page, you'll get a NEW secret
        # You must scan the CURRENT QR code that's displayed
        secret = Accounts.generate_totp_secret()
        uri = Accounts.generate_totp_uri(user, secret)
        qr_code = Accounts.generate_totp_qr_code(user, secret)

        # Base32 encode secret for storage in socket assigns
        # This prevents corruption during LiveView serialization
        secret_base32 = Base.encode32(secret, padding: false)

        Logger.info("TOTP enrollment started",
          user_email: user.email,
          secret_length: byte_size(secret),
          secret_base32: secret_base32,
          secret_hex: Base.encode16(secret),
          uri: uri
        )

        socket =
          socket
          |> assign(:page_title, "Set Up Two-Factor Authentication")
          |> assign(:secret_base32, secret_base32)
          |> assign(:qr_code, qr_code)
          |> assign(:code, "")
          |> assign(:error, nil)
          |> assign(:enrollment_complete, false)
          |> assign(:recovery_codes, [])
          |> assign(:show_recovery_codes, false)

        {:ok, socket}
      else
        # Initial disconnected render - use placeholder
        # Real secret will be generated when socket connects
        socket =
          socket
          |> assign(:page_title, "Set Up Two-Factor Authentication")
          |> assign(:secret_base32, nil)
          |> assign(:qr_code, nil)
          |> assign(:code, "")
          |> assign(:error, nil)
          |> assign(:enrollment_complete, false)
          |> assign(:recovery_codes, [])
          |> assign(:show_recovery_codes, false)

        {:ok, socket}
      end
    end
  end

  @impl true
  def handle_event("verify_code", %{"code" => code}, socket) do
    require Logger

    user = socket.assigns.current_scope.user
    secret_base32 = socket.assigns.secret_base32

    # Decode base32 secret back to binary
    secret = Base.decode32!(secret_base32, padding: false, case: :upper)

    Logger.info("TOTP enrollment verification attempt",
      user_email: user.email,
      provided_code: code,
      secret_length: byte_size(secret),
      secret_base32_from_assigns: secret_base32,
      secret_binary_hex: Base.encode16(secret)
    )

    if Accounts.verify_totp(secret, code) do
      Logger.info("TOTP enrollment successful", user_email: user.email)
      handle_valid_code(socket, user, secret)
    else
      Logger.warning("TOTP enrollment verification failed", user_email: user.email)
      {:noreply, assign(socket, :error, "Invalid code. Please try again.")}
    end
  end

  @impl true
  def handle_event("confirm_recovery_codes_saved", _params, socket) do
    user = socket.assigns.current_scope.user
    redirect_path = get_post_enrollment_path(user)

    {:noreply,
     socket
     |> put_flash(:info, "Two-factor authentication enabled successfully!")
     |> redirect(to: redirect_path)}
  end

  defp handle_valid_code(socket, user, secret) do
    # Create first TOTP device (new multi-device system)
    case Accounts.create_totp_device(user.id, "Primary Device", secret) do
      {:ok, _device, _secret} ->
        # Generate recovery codes for the user
        {:ok, codes} = Accounts.generate_recovery_codes(user.id)

        # Show recovery codes to user - they can only be displayed once
        {:noreply,
         socket
         |> assign(:enrollment_complete, true)
         |> assign(:recovery_codes, codes)
         |> assign(:show_recovery_codes, true)}

      {:error, _changeset} ->
        {:noreply, assign(socket, :error, "Failed to enable two-factor authentication. Please try again.")}
    end
  end

  defp get_post_enrollment_path(user) do
    case Towerops.Organizations.list_user_organizations(user.id) do
      [_first_org | _] -> ~p"/devices"
      [] -> ~p"/orgs"
    end
  end

  @impl true
  def render(assigns) do
    ~H"""
    <Layouts.authenticated flash={@flash} current_scope={@current_scope}>
      <div class="mx-auto max-w-2xl px-4 py-12">
        <div class="bg-white dark:bg-gray-900 rounded-lg shadow-lg p-8">
          <%= if @show_recovery_codes do %>
            <!-- Recovery Codes Display -->
            <div class="text-center mb-8">
              <.icon
                name="hero-shield-check"
                class="w-16 h-16 mx-auto mb-4 text-green-600 dark:text-green-400"
              />
              <h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
                Save Your Recovery Codes
              </h1>
              <p class="text-gray-600 dark:text-gray-400">
                Two-factor authentication has been enabled successfully!
              </p>
            </div>

            <div class="space-y-6">
              <!-- Warning -->
              <div class="rounded-md bg-yellow-50 dark:bg-yellow-900/20 p-4 border border-yellow-200 dark:border-yellow-800">
                <div class="flex">
                  <.icon
                    name="hero-exclamation-triangle"
                    class="h-5 w-5 text-yellow-400 mt-0.5"
                  />
                  <div class="ml-3">
                    <h3 class="text-sm font-medium text-yellow-800 dark:text-yellow-200">
                      Important: Save these recovery codes now
                    </h3>
                    <div class="mt-2 text-sm text-yellow-700 dark:text-yellow-300">
                      <ul class="list-disc pl-5 space-y-1">
                        <li>These codes will only be shown once and cannot be retrieved later</li>
                        <li>Store them in a secure location like a password manager</li>
                        <li>Each code can only be used once</li>
                        <li>Use these codes if you lose access to your authenticator app</li>
                      </ul>
                    </div>
                  </div>
                </div>
              </div>
              <!-- Recovery Codes -->
              <div class="border border-gray-200 dark:border-gray-700 rounded-lg p-6">
                <h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-4 text-center">
                  Your Recovery Codes
                </h2>
                <div class="grid grid-cols-2 gap-3 max-w-md mx-auto">
                  <%= for code <- @recovery_codes do %>
                    <div class="bg-gray-50 dark:bg-gray-800 rounded-md p-3 text-center">
                      <code class="text-lg font-mono text-gray-900 dark:text-white font-semibold">
                        {code}
                      </code>
                    </div>
                  <% end %>
                </div>

                <div class="mt-6 flex gap-3 justify-center">
                  <button
                    type="button"
                    phx-click={JS.dispatch("phx:copy", to: "#recovery-codes-text")}
                    class="inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 shadow-sm text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
                  >
                    <.icon name="hero-clipboard-document" class="w-5 h-5 mr-2" /> Copy All
                  </button>

                  <a
                    href={"data:text/plain;charset=utf-8," <> URI.encode(Enum.join(@recovery_codes, "\n"))}
                    download="towerops-recovery-codes.txt"
                    class="inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 shadow-sm text-sm font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
                  >
                    <.icon name="hero-arrow-down-tray" class="w-5 h-5 mr-2" /> Download
                  </a>
                </div>
                
    <!-- Hidden textarea for copy functionality -->
                <textarea
                  id="recovery-codes-text"
                  class="sr-only"
                  readonly
                >{Enum.join(@recovery_codes, "\n")}</textarea>
              </div>
              
    <!-- Continue Button -->
              <div class="flex justify-center pt-4">
                <button
                  type="button"
                  phx-click="confirm_recovery_codes_saved"
                  class="inline-flex items-center px-6 py-3 border border-transparent text-base font-medium rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
                >
                  I've Saved My Recovery Codes <.icon name="hero-arrow-right" class="w-5 h-5 ml-2" />
                </button>
              </div>
            </div>
          <% else %>
            <!-- Enrollment Form -->
            <div class="text-center mb-8">
              <.icon
                name="hero-shield-check"
                class="w-16 h-16 mx-auto mb-4 text-blue-600 dark:text-blue-400"
              />
              <h1 class="text-3xl font-bold text-gray-900 dark:text-white mb-2">
                Set Up Two-Factor Authentication
              </h1>
              <p class="text-gray-600 dark:text-gray-400">
                To keep your account secure, two-factor authentication is required for all users.
              </p>
            </div>

            <div class="space-y-6">
              <!-- Step 1: Scan QR Code -->
              <div class="border-t border-gray-200 dark:border-gray-700 pt-6">
                <h2 class="text-xl font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
                  <span class="flex items-center justify-center w-8 h-8 bg-blue-600 text-white rounded-full mr-3 text-sm">
                    1
                  </span>
                  Install an Authenticator App
                </h2>
                <p class="text-gray-600 dark:text-gray-400 ml-11 mb-4">
                  Download an authenticator app on your phone if you haven't already:
                </p>
                <ul class="ml-11 space-y-2 text-gray-700 dark:text-gray-300">
                  <li class="flex items-center">
                    <.icon
                      name="hero-check-circle"
                      class="w-5 h-5 mr-2 text-green-600 dark:text-green-400"
                    /> Google Authenticator (iOS, Android)
                  </li>
                  <li class="flex items-center">
                    <.icon
                      name="hero-check-circle"
                      class="w-5 h-5 mr-2 text-green-600 dark:text-green-400"
                    /> Authy (iOS, Android, Desktop)
                  </li>
                  <li class="flex items-center">
                    <.icon
                      name="hero-check-circle"
                      class="w-5 h-5 mr-2 text-green-600 dark:text-green-400"
                    /> 1Password, Bitwarden (with TOTP support)
                  </li>
                </ul>
              </div>
              
    <!-- Step 2: Scan QR Code -->
              <div class="border-t border-gray-200 dark:border-gray-700 pt-6">
                <h2 class="text-xl font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
                  <span class="flex items-center justify-center w-8 h-8 bg-blue-600 text-white rounded-full mr-3 text-sm">
                    2
                  </span>
                  Scan the QR Code
                </h2>
                <p class="text-gray-600 dark:text-gray-400 ml-11 mb-4">
                  Open your authenticator app and scan this QR code:
                </p>
                <%= if @qr_code do %>
                  <div class="ml-11 flex justify-center">
                    <div class="bg-white p-4 rounded-lg border-2 border-gray-200">
                      <img src={@qr_code} alt="TOTP QR Code" class="w-64 h-64" />
                    </div>
                  </div>
                <% else %>
                  <div class="ml-11 flex justify-center">
                    <div class="bg-gray-100 dark:bg-gray-800 p-4 rounded-lg border-2 border-gray-200 dark:border-gray-700 w-72 h-72 flex items-center justify-center">
                      <p class="text-gray-500 dark:text-gray-400">Loading QR code...</p>
                    </div>
                  </div>
                <% end %>
              </div>
              
    <!-- Step 3: Enter Code -->
              <div class="border-t border-gray-200 dark:border-gray-700 pt-6">
                <h2 class="text-xl font-semibold text-gray-900 dark:text-white mb-4 flex items-center">
                  <span class="flex items-center justify-center w-8 h-8 bg-blue-600 text-white rounded-full mr-3 text-sm">
                    3
                  </span>
                  Enter the Code from Your App
                </h2>
                <.form
                  for={%{}}
                  as={:form}
                  phx-submit="verify_code"
                  class="ml-11 flex flex-col items-center"
                >
                  <div class="space-y-4 w-full max-w-xs">
                    <div>
                      <label
                        for="code"
                        class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2 text-center"
                      >
                        6-digit code
                      </label>
                      <input
                        type="text"
                        name="code"
                        id="code"
                        inputmode="numeric"
                        pattern="[0-9]{6}"
                        maxlength="6"
                        placeholder="000000"
                        required
                        autocomplete="off"
                        class="block w-full rounded-md border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white shadow-sm focus:border-blue-500 focus:ring-blue-500 text-2xl text-center tracking-widest font-mono"
                        phx-mounted={JS.focus()}
                      />
                    </div>

                    <%= if @error do %>
                      <div class="rounded-md bg-red-50 dark:bg-red-900/30 p-4">
                        <div class="flex">
                          <.icon name="hero-exclamation-circle" class="h-5 w-5 text-red-400" />
                          <div class="ml-3">
                            <p class="text-sm text-red-800 dark:text-red-200">
                              {@error}
                            </p>
                          </div>
                        </div>
                      </div>
                    <% end %>

                    <div>
                      <.button type="submit" variant="primary" class="w-full">
                        <.icon name="hero-shield-check" class="w-5 h-5 mr-2" /> Verify and Enable
                      </.button>
                    </div>
                  </div>
                </.form>
              </div>
            </div>

            <div class="mt-8 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800">
              <div class="flex">
                <.icon
                  name="hero-information-circle"
                  class="h-5 w-5 text-blue-600 dark:text-blue-400 mt-0.5"
                />
                <div class="ml-3">
                  <p class="text-sm text-blue-900 dark:text-blue-100">
                    <strong>Keep your device safe:</strong>
                    You'll need to enter a code from your authenticator app each time you log in.
                    Make sure to keep your phone secure and backed up.
                  </p>
                </div>
              </div>
            </div>
          <% end %>
        </div>
      </div>
    </Layouts.authenticated>
    """
  end
end
