(ns ajet.chat.auth-gw.pages
  "HTML pages rendered by the Auth Gateway using Hiccup.

   Renders login, error, invite landing, and setup wizard pages.
   Uses Tailwind CSS via CDN for styling."
  (:require [hiccup2.core :as h]
            [hiccup.util :as hu]))

;;; ---------------------------------------------------------------------------
;;; Layout
;;; ---------------------------------------------------------------------------

(defn- page-shell
  "Base HTML shell with Tailwind CDN and dark theme."
  [title & body]
  (str
   "<!DOCTYPE html>"
   (h/html
    [:html {:lang "en" :class "dark"}
     [:head
      [:meta {:charset "UTF-8"}]
      [:meta {:name "viewport" :content "width=device-width, initial-scale=1.0"}]
      [:title (str title " - ajet chat")]
      [:script {:src "https://cdn.tailwindcss.com"}]
      [:script
       (h/raw "tailwindcss.config = {
          darkMode: 'class',
          theme: {
            extend: {
              colors: {
                brand: { 50: '#eef2ff', 100: '#e0e7ff', 200: '#c7d2fe', 500: '#6366f1', 600: '#4f46e5', 700: '#4338ca', 800: '#3730a3', 900: '#312e81' }
              }
            }
          }
        }")]]
     [:body {:class "bg-gray-950 text-gray-100 min-h-screen flex items-center justify-center antialiased"}
      [:div {:class "w-full max-w-md mx-auto px-4"}
       body]]])))

(defn- provider-button
  "Render an OAuth provider login button."
  [slug label icon-svg]
  [:a {:href  (str "/auth/login?provider=" slug)
       :class "flex items-center justify-center gap-3 w-full px-4 py-3 rounded-lg bg-gray-800 hover:bg-gray-700 border border-gray-700 hover:border-gray-600 text-gray-100 font-medium transition-colors duration-150 no-underline"}
   (h/raw icon-svg)
   [:span (str "Continue with " label)]])

(def ^:private provider-icons
  {"github" "<svg class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z\"/></svg>"
   "gitea"  "<svg class=\"w-5 h-5\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 6.407.140 7.954.140 7.954c.224.594.47.972.736 1.249-.192.294-.39.633-.543 1.049-.265.723-.264 1.528.007 2.238.271.71.755 1.295 1.379 1.695-.177.556-.193 1.173-.044 1.742.198.755.672 1.39 1.311 1.773.16.096.331.177.509.244-.077.394-.07.808.022 1.207.135.585.426 1.112.834 1.525.407.413.928.705 1.506.844.354.086.714.124 1.074.112a3.77 3.77 0 0 0 1.18-.262c.387.35.851.593 1.35.715.499.122 1.02.107 1.512-.044.397-.122.765-.327 1.073-.602.195.06.396.098.601.112.609.042 1.218-.109 1.728-.43.51-.32.905-.78 1.132-1.325a3.09 3.09 0 0 0 .226-1.195c.503-.21.95-.533 1.302-.946.352-.413.597-.907.711-1.433.115-.526.095-1.072-.057-1.587a3.19 3.19 0 0 0-.794-1.303 3.17 3.17 0 0 0 .382-1.665 3.19 3.19 0 0 0-.677-1.764 3.23 3.23 0 0 0-1.458-1.043 3.25 3.25 0 0 0-1.8-.138c-.39-.535-.903-.95-1.487-1.21a3.36 3.36 0 0 0-1.818-.279c-.594.073-1.154.318-1.618.696a3.22 3.22 0 0 0-1.028-.63 3.29 3.29 0 0 0-1.202-.168 3.27 3.27 0 0 0-1.558.519 3.24 3.24 0 0 0-1.074 1.263c-.203-.064-.412-.1-.622-.112zM12 6.5a5.5 5.5 0 1 1 0 11 5.5 5.5 0 0 1 0-11z\"/></svg>"
   "oidc"   "<svg class=\"w-5 h-5\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z\"/></svg>"})

(defn- icon-for-provider-type [provider-type]
  (get provider-icons provider-type (get provider-icons "oidc")))

;;; ---------------------------------------------------------------------------
;;; Common UI components
;;; ---------------------------------------------------------------------------

(defn- error-banner [error]
  (when error
    [:div {:class "rounded-lg bg-red-900/40 border border-red-800 px-4 py-3 text-red-300 text-sm"}
     error]))

(defn- text-input [{:keys [name type placeholder value required autocomplete]}]
  [:input {:type (or type "text") :name name :required required
           :placeholder placeholder :value (or value "")
           :autocomplete (or autocomplete "off")
           :class "w-full px-3 py-2 rounded-lg bg-gray-800 border border-gray-700 text-gray-100 placeholder-gray-500 focus:outline-none focus:border-brand-500"}])

(defn- submit-button [label]
  [:button {:type "submit"
            :class "flex items-center justify-center w-full px-4 py-3 rounded-lg bg-brand-600 hover:bg-brand-700 text-white font-medium transition-colors"}
   label])

(defn- step-indicator
  "Render a step progress indicator. current is 1-based."
  [current total]
  [:div {:class "flex items-center justify-center gap-2 mb-6"}
   (for [i (range 1 (inc total))]
     [:div {:class (str "w-2.5 h-2.5 rounded-full "
                        (if (= i current)
                          "bg-brand-500"
                          (if (< i current)
                            "bg-brand-700"
                            "bg-gray-700")))}])])

;;; ---------------------------------------------------------------------------
;;; Login Page
;;; ---------------------------------------------------------------------------

(defn login-page
  "Render the login page with dynamic OAuth provider buttons and optional password form.

   opts:
     :providers    - vector of provider maps from DB [{:slug :display-name :provider-type ...}]
     :error        - optional error message string
     :invite-info  - optional map {:community-name \"...\"} for invite flow
     :first-user?  - true if no users exist yet (bootstrap mode)"
  [{:keys [providers error invite-info first-user?]}]
  (page-shell "Sign In"
    [:div {:class "text-center space-y-8 py-12"}
     ;; Logo / branding
     [:div {:class "space-y-2"}
      [:h1 {:class "text-3xl font-bold tracking-tight text-brand-200"} "ajet chat"]
      [:p {:class "text-gray-400 text-sm"}
       (if first-user?
         "Welcome! Sign in to set up your community."
         "Sign in to continue")]]

     ;; Error message
     (error-banner error)

     ;; OAuth provider buttons (dynamic from DB)
     (when (seq providers)
       [:div {:class "space-y-3"}
        (for [{:keys [slug display-name provider-type]} providers]
          (provider-button slug display-name (icon-for-provider-type provider-type)))])

     ;; Invite info
     (when invite-info
       [:div {:class "border-t border-gray-800 pt-4 space-y-2"}
        [:p {:class "text-gray-500 text-xs uppercase tracking-wider"} "Accepting invite"]
        [:p {:class "text-gray-300 font-medium"}
         (str "Joining: " (:community-name invite-info))]])

     ;; First user hint
     (when first-user?
       [:div {:class "border-t border-gray-800 pt-4"}
        [:p {:class "text-gray-500 text-sm"}
         "You'll be the first user and community owner."]])]))

;;; ---------------------------------------------------------------------------
;;; Error Page
;;; ---------------------------------------------------------------------------

(defn error-page
  "Render a generic error page.

   opts:
     :status  - HTTP status code (401, 403, 404, 429, 502, 503)
     :title   - error title
     :message - error description
     :retry-after - optional seconds for 429 responses"
  [{:keys [status title message retry-after]}]
  (let [status-text (case status
                      401 "Unauthorized"
                      403 "Forbidden"
                      404 "Not Found"
                      429 "Too Many Requests"
                      502 "Bad Gateway"
                      503 "Service Unavailable"
                      "Error")
        display-title (or title status-text)]
    (page-shell display-title
      [:div {:class "text-center space-y-6 py-16"}
       [:div {:class "space-y-2"}
        [:p {:class "text-6xl font-bold text-gray-700"} (str status)]
        [:h1 {:class "text-xl font-semibold text-gray-300"} display-title]]
       [:p {:class "text-gray-500 text-sm max-w-sm mx-auto"}
        (or message "Something went wrong. Please try again.")]
       (when retry-after
         [:div {:class "space-y-2"}
          [:p {:class "text-gray-500 text-sm"}
           (str "Please wait " retry-after " seconds before retrying.")]
          [:div {:class "w-full bg-gray-800 rounded-full h-1.5"}
           [:div {:class "bg-brand-500 h-1.5 rounded-full transition-all duration-1000"
                  :style "width: 0%"
                  :id    "retry-bar"}]]
          [:script
           (h/raw (format "(() => { let s=%d, el=document.getElementById('retry-bar'), iv=setInterval(() => { s--; el.style.width=(((%d-s)/%d)*100)+'%%'; if(s<=0){clearInterval(iv);location.reload();}},1000);})()"
                          retry-after retry-after retry-after))]])
       [:div {:class "pt-4 space-x-4"}
        [:a {:href  "/"
             :class "inline-block px-4 py-2 rounded-lg bg-brand-600 hover:bg-brand-700 text-white text-sm font-medium transition-colors no-underline"}
         "Go Home"]
        (when (#{401 403} status)
          [:a {:href  "/auth/login"
               :class "inline-block px-4 py-2 rounded-lg bg-gray-800 hover:bg-gray-700 border border-gray-700 text-gray-300 text-sm font-medium transition-colors no-underline"}
           "Sign In"])]])))

;;; ---------------------------------------------------------------------------
;;; Invite Landing Page
;;; ---------------------------------------------------------------------------

(defn invite-page
  "Render the invite landing page.

   opts:
     :community-name - name of the community being joined
     :invite-code    - the invite code
     :error          - optional error message"
  [{:keys [community-name invite-code error]}]
  (page-shell "Join Community"
    [:div {:class "text-center space-y-8 py-12"}
     ;; Logo
     [:div {:class "space-y-2"}
      [:h1 {:class "text-3xl font-bold tracking-tight text-brand-200"} "ajet chat"]]

     ;; Error
     (error-banner error)

     ;; Invite info
     [:div {:class "space-y-4"}
      [:div {:class "rounded-lg bg-gray-900 border border-gray-800 p-6 space-y-3"}
       [:p {:class "text-gray-400 text-sm"} "You've been invited to join"]
       [:p {:class "text-2xl font-bold text-gray-100"} community-name]]

      [:a {:href  (str "/auth/login?invite=" (hu/url-encode invite-code))
           :class "inline-block w-full px-4 py-3 rounded-lg bg-brand-600 hover:bg-brand-700 text-white font-medium transition-colors text-center no-underline"}
       "Accept Invite & Sign In"]]]))

;;; ---------------------------------------------------------------------------
;;; Setup Wizard Pages
;;; ---------------------------------------------------------------------------


(defn setup-configure-providers-page
  "Render the OAuth provider configuration form (wizard step 2).
   Shows existing providers with delete buttons and a form to add new ones.
   Providers require: type, display name, slug, client ID/secret, and
   type-specific URLs (base-url for Gitea, issuer-url for OIDC).

   opts:
     :providers - vector of existing provider rows from DB
     :error     - optional validation error message"
  [{:keys [providers error]}]
  (page-shell "Setup - OAuth Providers"
    [:div {:class "space-y-8 py-12"}
     [:div {:class "text-center space-y-2"}
      [:h1 {:class "text-3xl font-bold tracking-tight text-brand-200"} "ajet chat"]
      [:p {:class "text-gray-400 text-sm"} "Configure at least one OAuth login provider to get started."]]

     (step-indicator 1 2)

     (error-banner error)

     ;; Existing providers
     (when (seq providers)
       [:div {:class "space-y-2"}
        [:h2 {:class "text-sm font-medium text-gray-400 uppercase tracking-wider"} "Configured Providers"]
        (for [{:keys [id display-name provider-type slug]} providers]
          [:div {:class "flex items-center justify-between bg-gray-900 border border-gray-800 rounded-lg p-3"}
           [:div {:class "flex items-center gap-3"}
            [:span {:class "text-xs font-mono text-gray-500 uppercase"} provider-type]
            [:span {:class "text-gray-100 font-medium"} display-name]
            [:span {:class "text-gray-500 text-xs"} (str "(" slug ")")]]
           [:form {:method "post" :action (str "/setup/providers/" id "/delete")}
            [:button {:type "submit"
                      :class "text-red-400 hover:text-red-300 text-sm px-2 py-1 rounded hover:bg-red-900/30 transition-colors"}
             "Remove"]]])])

     ;; Add provider form
     [:div {:class "space-y-3 text-left"}
      [:h2 {:class "text-sm font-medium text-gray-400 uppercase tracking-wider"} "Add Provider"]
      [:form {:method "post" :action "/setup/providers" :class "space-y-3"}
       [:div
        [:label {:class "block text-sm text-gray-400 mb-1"} "Provider Type"]
        [:select {:name "provider-type"
                  :class "w-full px-3 py-2 rounded-lg bg-gray-800 border border-gray-700 text-gray-100 focus:outline-none focus:border-brand-500"}
         [:option {:value "github"} "GitHub"]
         [:option {:value "gitea"} "Gitea"]
         [:option {:value "oidc"} "OIDC (OpenID Connect)"]]]

       [:label {:class "block text-sm text-gray-400"} "Display Name"]
       (text-input {:name "display-name" :placeholder "e.g. GitHub"})

       [:label {:class "block text-sm text-gray-400"} "Slug (URL-safe identifier)"]
       (text-input {:name "slug" :placeholder "e.g. github"})

       [:label {:class "block text-sm text-gray-400"} "Client ID"]
       (text-input {:name "client-id" :placeholder "OAuth client ID"})

       [:label {:class "block text-sm text-gray-400"} "Client Secret"]
       (text-input {:name "client-secret" :type "password" :placeholder "OAuth client secret"})

       [:label {:class "block text-sm text-gray-400"} "Base URL (Gitea only)"]
       (text-input {:name "base-url" :placeholder "e.g. https://gitea.example.com"})

       [:label {:class "block text-sm text-gray-400"} "Issuer URL (OIDC only)"]
       (text-input {:name "issuer-url" :placeholder "e.g. https://auth.example.com"})

       (submit-button "Add Provider")]]

     ;; Navigation — require at least one provider before proceeding
     (when (seq providers)
       [:div {:class "pt-4"}
        [:a {:href "/auth/login"
             :class "flex items-center justify-center w-full px-4 py-3 rounded-lg bg-brand-600 hover:bg-brand-700 text-white font-medium transition-colors no-underline"}
         "Continue — Sign in with your provider"]])]))

(defn setup-create-community-page
  "Render the community creation form (wizard step 3).
   Collects community name and slug. Slug must be lowercase alphanumeric
   with hyphens (min 2 chars). On success, completes the setup wizard.

   opts:
     :error - optional validation/API error message
     :name  - prefill community name on re-render after error
     :slug  - prefill community slug on re-render after error"
  [{:keys [error name slug]}]
  (page-shell "Setup - Create Community"
    [:div {:class "text-center space-y-8 py-12"}
     [:div {:class "space-y-2"}
      [:h1 {:class "text-3xl font-bold tracking-tight text-brand-200"} "ajet chat"]
      [:p {:class "text-gray-400 text-sm"} "Create your first community."]]

     (step-indicator 2 2)

     (error-banner error)

     [:form {:method "post" :action "/setup/create-community" :class "space-y-3 text-left"}
      [:label {:class "block text-sm text-gray-400"} "Community Name"]
      (text-input {:name "name" :placeholder "My Team" :value name :required true})

      [:label {:class "block text-sm text-gray-400 pt-2"} "Slug"]
      (text-input {:name "slug" :placeholder "my-team" :value slug :required true})
      [:p {:class "text-gray-500 text-xs"} "Lowercase letters, digits, and hyphens only."]

      [:div {:class "pt-2"}
       (submit-button "Create Community & Finish Setup")]]]))
