#!/usr/bin/env bb

(ns iamwaiting.core
  (:require [babashka.http-client :as http]
            [babashka.fs :as fs]
            [babashka.process :as process]
            [cheshire.core :as json]
            [clojure.string :as str]))

(def config-file (str (System/getenv "HOME") "/.iamwaiting/config.edn"))

(defn load-config []
  "Load configuration from config file or environment variables"
  (let [config (when (fs/exists? config-file)
                 (read-string (slurp config-file)))
        webhook-url (or (:webhook-url config)
                       (System/getenv "IAMWAITING_WEBHOOK_URL"))
        user-id (or (:user-id config)
                   (System/getenv "IAMWAITING_USER_ID"))
        spiceflow-url (or (:spiceflow-url config)
                         (System/getenv "IAMWAITING_SPICEFLOW_URL"))
        toggles (or (:toggles config)
                   {:idle-prompt true
                    :permission-prompt true
                    :permission-prompt-ping true})]
    {:webhook-url webhook-url
     :user-id user-id
     :spiceflow-url spiceflow-url
     :toggles toggles}))

(defn send-discord-webhook [webhook-url message]
  "Send a message to Discord via webhook"
  (try
    (let [payload {:content message
                   :username "Claude Code"
                   :avatar_url "https://www.anthropic.com/images/icons/apple-touch-icon.png"}
          response (http/post webhook-url
                             {:headers {"Content-Type" "application/json"}
                              :body (json/generate-string payload)})]
      (if (< (:status response) 300)
        {:success true}
        {:success false :error (str "HTTP " (:status response))}))
    (catch Exception e
      {:success false :error (.getMessage e)})))

(defn get-tmux-session []
  "Get the current tmux session name if running inside tmux"
  (when (System/getenv "TMUX")
    (try
      (let [result (process/shell {:out :string :err :string}
                                  "tmux" "display-message" "-p" "#S")]
        (when (zero? (:exit result))
          (str/trim (:out result))))
      (catch Exception _ nil))))

(defn format-waiting-message [event-data user-id toggles spiceflow-url]
  "Format a message for Claude waiting event"
  (let [cwd (or (:cwd event-data) (System/getProperty "user.dir"))
        tmux-session (get-tmux-session)
        project-name (fs/file-name cwd)
        timestamp (java.time.LocalDateTime/now)
        formatted-time (.format timestamp
                               (java.time.format.DateTimeFormatter/ofPattern "HH:mm:ss"))
        session-id (:session_id event-data)
        notification-type (:notification_type event-data)
        permission-mode (:permission_mode event-data)
        hook-message (:message event-data)
        transcript-path (:transcript_path event-data)
        transcript-file (when transcript-path (fs/file-name transcript-path))
        ;; Check if this is a permission prompt
        is-permission-prompt? (or (= notification-type "permission_prompt")
                                 (some? permission-mode))
        ;; Ping user if configured, it's a permission prompt, and ping toggle is enabled
        ping-enabled? (get toggles :permission-prompt-ping true)
        user-ping (when (and user-id is-permission-prompt? ping-enabled?)
                   (str "<@" user-id "> "))
        ;; Build Spiceflow session link if both URL and tmux session are available
        spiceflow-link (when (and spiceflow-url tmux-session)
                        (str spiceflow-url "/session/" tmux-session))]
    (str user-ping
         "⏳ **Claude is waiting** in `" project-name "`\n"
         "📁 Path: `" cwd "`\n"
         (when tmux-session (str "🖥️ Tmux: `" tmux-session "`\n"))
         (when spiceflow-link (str "🔗 **[Open in Spiceflow](" spiceflow-link ")**\n"))
         "🕐 Time: " formatted-time "\n"
         (when session-id (str "🔑 Session: `" session-id "`\n"))
         (when notification-type (str "📢 Type: `" notification-type "`\n"))
         (when permission-mode (str "🔐 Mode: `" permission-mode "`\n"))
         (when transcript-file (str "📝 Transcript: `" transcript-file "`\n"))
         (when hook-message (str "\n> " hook-message)))))

(defn setup-config []
  "Interactive setup for webhook configuration"
  (println "iamwaiting setup")
  (println "================\n")
  (println "Enter your Discord webhook URL:")
  (println "(Get this from Discord: Server Settings > Integrations > Webhooks)\n")
  (print "> ")
  (flush)
  (let [webhook-url (str/trim (read-line))]
    (when (str/blank? webhook-url)
      (println "Error: webhook URL cannot be empty")
      (System/exit 1))

    (println "\nEnter your Discord user ID (optional, for @mentions on permission prompts):")
    (println "(Get this from Discord: User Settings > Advanced > Developer Mode, then right-click your name)\n")
    (print "> ")
    (flush)
    (let [user-id-input (str/trim (read-line))
          user-id (when-not (str/blank? user-id-input) user-id-input)]

      (println "\nEnter your Spiceflow URL (optional, for session links in notifications):")
      (println "(e.g., https://framework-desktop:5173)\n")
      (print "> ")
      (flush)
      (let [spiceflow-url-input (str/trim (read-line))
            spiceflow-url (when-not (str/blank? spiceflow-url-input)
                           ;; Remove trailing slash if present
                           (str/replace spiceflow-url-input #"/$" ""))]

      ;; Toggle prompts
      (println "\n📬 Notification Preferences")
      (print "Enable notifications for idle prompts? (y/n, default: y): ")
      (flush)
      (let [idle-response (str/lower-case (str/trim (read-line)))
            idle-enabled? (not= idle-response "n")]

        (print "Enable notifications for permission prompts? (y/n, default: y): ")
        (flush)
        (let [perm-response (str/lower-case (str/trim (read-line)))
              perm-enabled? (not= perm-response "n")

              ;; Ask about ping preference if user ID provided
              ping-enabled? (if user-id
                             (do
                               (print "@mention you on permission prompts? (y/n, default: y): ")
                               (flush)
                               (let [ping-response (str/lower-case (str/trim (read-line)))]
                                 (not= ping-response "n")))
                             true)

              ;; Build config with toggles
              config (cond-> {:webhook-url webhook-url
                             :toggles {:idle-prompt idle-enabled?
                                      :permission-prompt perm-enabled?
                                      :permission-prompt-ping ping-enabled?}}
                       user-id (assoc :user-id user-id)
                       spiceflow-url (assoc :spiceflow-url spiceflow-url))]

          ;; Create config directory
          (fs/create-dirs (fs/parent config-file))

          ;; Write config
          (spit config-file (pr-str config))
          (println "\n✓ Configuration saved to" config-file)
          (when user-id
            (println (str "✓ User ID configured - you will be @mentioned on permission prompts: "
                         (if ping-enabled? "enabled" "disabled"))))
          (when spiceflow-url
            (println (str "✓ Spiceflow URL: " spiceflow-url)))
          (println (str "✓ Idle prompts: " (if idle-enabled? "enabled" "disabled")))
          (println (str "✓ Permission prompts: " (if perm-enabled? "enabled" "disabled")))
          (println "\nTest the webhook with: ./iamwaiting test")))))))

(defn test-webhook []
  "Test the webhook configuration"
  (let [config (load-config)]
    (if-not (:webhook-url config)
      (do
        (println "Error: No webhook URL configured")
        (println "Run: ./iamwaiting setup")
        (System/exit 1))
      (do
        (println "Sending test message...")
        (let [result (send-discord-webhook
                      (:webhook-url config)
                      "🧪 **Test message from iamwaiting**\n\nIf you see this, your webhook is configured correctly!")]
          (if (:success result)
            (println "✓ Test message sent successfully!")
            (do
              (println "✗ Failed to send message:" (:error result))
              (System/exit 1))))))))

(defn read-hook-data []
  "Read hook data from stdin (JSON format)"
  (try
    (let [stdin (slurp *in*)]
      (when-not (str/blank? stdin)
        (json/parse-string stdin true)))
    (catch Exception e
      (binding [*out* *err*]
        (println "Warning: Failed to parse stdin JSON:" (.getMessage e)))
      {})))

(defn send-waiting-notification [& event-data-args]
  "Send a waiting notification to Discord"
  (let [config (load-config)]
    (if-not (:webhook-url config)
      (do
        (println "Error: No webhook URL configured")
        (println "Run: ./iamwaiting setup")
        (System/exit 1))
      (let [;; Read from stdin first (hook data), fallback to command-line args
            event-data (or (read-hook-data)
                          (when (seq event-data-args)
                            (try
                              (json/parse-string (first event-data-args) true)
                              (catch Exception _ {})))
                          {})
            ;; Determine notification type
            notification-type (:notification_type event-data)
            permission-mode (:permission_mode event-data)
            is-permission-prompt? (or (= notification-type "permission_prompt")
                                     (some? permission-mode))
            ;; Determine which toggle to check
            toggle-key (if is-permission-prompt? :permission-prompt :idle-prompt)
            enabled? (get-in config [:toggles toggle-key] true)]

        ;; Exit early if notification type is disabled
        (if-not enabled?
          (when (System/getenv "DEBUG")
            (println (str "Notification disabled for " toggle-key)))

          ;; Original notification logic
          (let [message (format-waiting-message event-data (:user-id config) (:toggles config) (:spiceflow-url config))
                result (send-discord-webhook (:webhook-url config) message)]
            (if (:success result)
              (println "✓ Notification sent")
              (do
                (println "✗ Failed to send notification:" (:error result))
                (System/exit 1)))))))))

(defn toggle-feature [feature action]
  "Toggle a notification feature on or off"
  (let [config (load-config)
        feature-key (case feature
                     "idle-prompt" :idle-prompt
                     "permission-prompt" :permission-prompt
                     "permission-prompt-ping" :permission-prompt-ping
                     nil)
        action-bool (case action
                     "on" true
                     "off" false
                     nil)]

    (cond
      (nil? feature-key)
      (do
        (println "❌ Invalid feature. Use: idle-prompt | permission-prompt | permission-prompt-ping")
        (System/exit 1))

      (nil? action-bool)
      (do
        (println "❌ Invalid action. Use: on | off")
        (System/exit 1))

      :else
      (let [updated-config (assoc-in config [:toggles feature-key] action-bool)]
        (fs/create-dirs (fs/parent config-file))
        (spit config-file (pr-str updated-config))
        (println (str "✅ " feature " notifications: " action))))))

(defn show-toggle-status []
  "Display current toggle status"
  (let [config (load-config)
        toggles (or (:toggles config)
                   {:idle-prompt true
                    :permission-prompt true
                    :permission-prompt-ping true})]
    (println "📊 Toggle Status\n")
    (println (str "Idle prompts:        " (if (:idle-prompt toggles) "✅ enabled" "❌ disabled")))
    (println (str "Permission prompts:  " (if (:permission-prompt toggles) "✅ enabled" "❌ disabled")))
    (println (str "Permission ping:     " (if (:permission-prompt-ping toggles) "✅ enabled" "❌ disabled")))))

(defn show-config []
  "Display current configuration"
  (let [config (load-config)
        toggles (or (:toggles config)
                   {:idle-prompt true
                    :permission-prompt true
                    :permission-prompt-ping true})
        user-id (:user-id config)
        spiceflow-url (:spiceflow-url config)]
    (println "⚙️  Configuration\n")
    (println (str "Webhook URL:         " (if (:webhook-url config) "✅ configured" "❌ not configured")))
    (println (str "User ID:             " (or user-id "not configured")))
    (println (str "Spiceflow URL:       " (or spiceflow-url "not configured")))
    (println "\n📊 Toggles\n")
    (println (str "Idle prompts:        " (if (:idle-prompt toggles) "✅ enabled" "❌ disabled")))
    (println (str "Permission prompts:  " (if (:permission-prompt toggles) "✅ enabled" "❌ disabled")))
    (println (str "Permission ping:     " (if (:permission-prompt-ping toggles) "✅ enabled" "❌ disabled")))))

(defn show-help []
  (println "iamwaiting - Send Discord notifications when Claude is waiting")
  (println "")
  (println "Usage:")
  (println "  iamwaiting setup                                   Set up Discord webhook configuration")
  (println "  iamwaiting test                                    Test webhook configuration")
  (println "  iamwaiting status                                  Show current configuration")
  (println "  iamwaiting toggle status                           Show current toggle status")
  (println "  iamwaiting toggle idle-prompt <on|off>             Toggle idle prompt notifications")
  (println "  iamwaiting toggle permission-prompt <on|off>       Toggle permission prompt notifications")
  (println "  iamwaiting toggle permission-prompt-ping <on|off>  Toggle @mentions on permission prompts")
  (println "  iamwaiting [event-data-json]                       Send waiting notification")
  (println "")
  (println "Configuration:")
  (println "  Config file: ~/.iamwaiting/config.edn")
  (println "  Environment: IAMWAITING_WEBHOOK_URL")
  (println "")
  (println "Hook Integration:")
  (println "  Add to ~/.claude/hooks.edn:")
  (println "  {:agent-waiting-for-user {:command [\"iamwaiting\"]}}")
  (System/exit 0))

;; CLI entry point
(defn -main [& args]
  (if (empty? args)
    (send-waiting-notification)
    (let [command (first args)
          rest-args (rest args)]
      (case command
        "setup" (setup-config)
        "test" (test-webhook)
        "status" (show-config)
        "toggle" (let [subcommand (second args)]
                  (case subcommand
                    "status" (show-toggle-status)
                    "idle-prompt" (toggle-feature "idle-prompt" (nth args 2 nil))
                    "permission-prompt" (toggle-feature "permission-prompt" (nth args 2 nil))
                    "permission-prompt-ping" (toggle-feature "permission-prompt-ping" (nth args 2 nil))
                    (do
                      (println "Usage: iamwaiting toggle <status|idle-prompt|permission-prompt|permission-prompt-ping> [on|off]")
                      (System/exit 1))))
        "help" (show-help)
        "--help" (show-help)
        "-h" (show-help)
        ;; Default: treat first arg as event data JSON
        (apply send-waiting-notification args)))))

(when (= *file* (System/getProperty "babashka.file"))
  (apply -main *command-line-args*))
