(ns ajet.chat.web.core
  "Web session manager -- http-kit + Hiccup + Datastar SSE.

   Manages the full lifecycle: NATS connection, connection tracker, HTTP server.
   No direct PostgreSQL access -- all data goes through the API via shared api-client.
   System state held in a single atom for REPL-driven development."
  (:refer-clojure :exclude [reset!])
  (:require [clojure.tools.logging :as log]
            [org.httpkit.server :as http-kit]
            [ajet.chat.shared.config :as config]
            [ajet.chat.shared.eventbus :as eventbus]
            [ajet.chat.shared.logging :as logging]
            [ajet.chat.web.routes :as routes]
            [ajet.chat.web.sse :as sse])
  (:gen-class))

(defonce system (atom nil))

;;; ---------------------------------------------------------------------------
;;; Lifecycle
;;; ---------------------------------------------------------------------------

(defn start!
  "Start the Web Session Manager. Connects to NATS and starts HTTP server."
  [& [{:keys [config-overrides]}]]
  (when @system
    (log/warn "System already started -- call (stop!) first")
    (throw (ex-info "System already running" {})))
  (let [cfg        (config/load-config {:resource "web-sm-config.edn"})
        cfg        (if config-overrides (merge cfg config-overrides) cfg)
        _          (log/info "Loaded config:" (config/redact cfg))

        ;; NATS
        nats       (eventbus/connect! (:nats cfg))
        _          (log/info "Connected to NATS")

        ;; Connection tracker -- per-user SSE state
        connections (atom {})

        ;; System map (no DB -- web-sm proxies everything through the API)
        api-url    (get-in cfg [:api :base-url] "http://localhost:3001")
        sys        {:config      cfg
                    :nats        nats
                    :connections connections
                    :api-url     api-url}

        ;; HTTP server
        handler    (routes/app sys)
        port       (get-in cfg [:server :port] 3002)
        host       (get-in cfg [:server :host] "0.0.0.0")
        server     (http-kit/run-server handler {:port port :ip host
                                                  :max-body (* 12 1024 1024)})]
    (clojure.core/reset! system (assoc sys :server server :port port))
    (log/info (str "Web session manager started on port " port))
    @system))

(defn stop!
  "Stop the Web Session Manager. Shuts down HTTP, SSE connections, NATS."
  []
  (when-let [sys @system]
    (log/info "Shutting down Web session manager...")

    ;; Disconnect all SSE clients
    (when-let [connections (:connections sys)]
      (sse/disconnect-all! connections (:nats sys))
      (log/info "All SSE connections closed"))

    ;; Stop HTTP server (wait up to 30s for in-flight requests)
    (when-let [server (:server sys)]
      (server :timeout 30000)
      (log/info "HTTP server stopped"))

    ;; Close NATS
    (when-let [nats (:nats sys)]
      (try
        (eventbus/close! nats)
        (log/info "NATS connection closed")
        (catch Exception e
          (log/error e "Error closing NATS connection"))))

    (clojure.core/reset! system nil)
    (log/info "Web session manager stopped")))

(defn reset!
  "Stop then start the system (REPL convenience)."
  []
  (stop!)
  (start!))

;;; ---------------------------------------------------------------------------
;;; Entry point
;;; ---------------------------------------------------------------------------

(defn -main [& _args]
  (start!)

  ;; Graceful shutdown hook
  (.addShutdownHook
    (Runtime/getRuntime)
    (Thread. ^Runnable (fn []
                         (log/info "Shutdown hook triggered")
                         (stop!))))

  ;; Block main thread
  @(promise))
