/**
 * Saeeol-specific TUI app customizations.
 *
 * Everything in this module is called from the shared upstream `app.tsx`
 * via thin integration points so the upstream diff stays minimal.
 */

import { createEffect, on } from "solid-js"
import { useKeyboard } from "@opentui/solid"
import { TextAttributes } from "@opentui/core"
import * as Clipboard from "@tui/util/clipboard"
import { useCommandDialog } from "@tui/component/dialog-command"
import { useSDK } from "@tui/context/sdk"
import { useSync } from "@tui/context/sync"
import { useDialog } from "@tui/ui/dialog"
import { useToast } from "@tui/ui/toast"
import { useTheme } from "@tui/context/theme"
import { DialogAlert } from "@tui/ui/dialog-alert"
import { DialogSelect } from "@tui/ui/dialog-select"
import { Link } from "@tui/ui/link"
import { isSaeeolError, showSaeeolErrorToast } from "@/saeeol/errors"
import { registerSaeeolCommands } from "@/saeeol/commands-index"
import { initializeTUIDependencies } from "@saeeol/gateway/tui"

// Re-export so upstream can render the route without importing directly
export { SaeeolClawView } from "@/saeeol/claw/view"

// ---------------------------------------------------------------------------
// Constants
// ---------------------------------------------------------------------------

/** Default terminal window title prefix. */
export const APP_TITLE = "새얼"

/** Status icons for terminal title. busy uses spinner frames. */
export const STATUS_ICON: Record<string, string> = {
  idle: "●",
  busy: "◐",
  retry: "↻",
  offline: "✕",
}

/** Spinner frames cycled during busy state. */
export const SPINNER_FRAMES = ["◐", "◓", "◑", "◒"]

/** Interval (ms) between spinner frame updates. */
export const SPINNER_INTERVAL = 200

/** Public docs URL shown in the command palette. */
export const DOCS_URL = "https://saeeol.ai/docs"

/** Human-readable product name used in user-facing messages. */
export const APP_NAME = "SAEEOL"

// ---------------------------------------------------------------------------
// Utilities
// ---------------------------------------------------------------------------

export function isAllowEverything(permission: unknown): boolean {
  if (typeof permission !== "object" || permission === null) return false
  const wildcard = (permission as Record<string, unknown>)["*"]
  if (typeof wildcard === "string") return wildcard === "allow"
  if (typeof wildcard === "object" && wildcard !== null) return (wildcard as Record<string, unknown>)["*"] === "allow"
  return false
}

// ---------------------------------------------------------------------------
// Session effects
// ---------------------------------------------------------------------------

/**
 * Reactive effects for session management:
 * - Notify the server which session the user is viewing (live indicators)
 * - Evict per-session data from the store when navigating away
 *
 * Must be called inside the App component body (needs SolidJS owner).
 */
export function useSessionEffects(deps: {
  route: ReturnType<typeof import("@tui/context/route").useRoute>
  sdk: ReturnType<typeof useSDK>
  sync: ReturnType<typeof useSync>
}) {
  // Notify server which session the user is viewing
  createEffect(() => {
    const sessionID = deps.route.data.type === "session" ? deps.route.data.sessionID : undefined
    deps.sdk.client.session.viewed({ focused: sessionID ? [sessionID] : [] }).catch(() => {})
  })

  // Evict per-session data from store when navigating away
  createEffect(
    on(
      () => (deps.route.data.type === "session" ? deps.route.data.sessionID : undefined),
      (current, prev) => {
        if (prev && prev !== current) deps.sync.session.evict(prev)
      },
    ),
  )
}

// ---------------------------------------------------------------------------
// Terminal title
// ---------------------------------------------------------------------------

/**
 * Returns the terminal title for saeeolclaw routes.
 * Returns undefined for other routes (caller should handle them).
 */
export function getTerminalTitle(
  route: ReturnType<typeof import("@tui/context/route").useRoute>,
  base: string,
): string | undefined {
  if (route.data.type === "saeeolclaw") return `${STATUS_ICON.idle} ${base} | SaeeolClaw`
  return undefined
}

// ---------------------------------------------------------------------------
// Session error handling
// ---------------------------------------------------------------------------

/**
 * Intercepts Saeeol-specific errors and shows a warning toast.
 * Returns `true` if the error was handled, `false` otherwise.
 */
export function handleSessionError(error: unknown, toast: ReturnType<typeof useToast>): boolean {
  if (error && typeof error === "object" && isSaeeolError(error as any)) {
    showSaeeolErrorToast(error as any, toast)
    return true
  }
  return false
}

// ---------------------------------------------------------------------------
// Initialization
// ---------------------------------------------------------------------------

/**
 * One-shot initialiser called from the App component body.
 *
 * - Injects TUI dependencies into saeeol-gateway
 * - Registers Saeeol Gateway commands (profile, teams, saeeolclaw, etc.)
 * - Registers the auto-approve toggle command
 */
export function init() {
  const command = useCommandDialog()
  const sync = useSync()
  const sdk = useSDK()
  const toast = useToast()

  // Inject TUI dependencies for saeeol-gateway
  initializeTUIDependencies({
    useCommandDialog,
    useSync,
    useDialog,
    useToast,
    useTheme,
    useSDK,
    DialogAlert,
    DialogSelect,
    Link,
    Clipboard,
    useKeyboard,
    TextAttributes,
  })

  // Register Saeeol Gateway commands (profile, teams, saeeolclaw, remote, etc.)
  registerSaeeolCommands(useSDK)

  // Register auto-approve toggle
  command.register(() => [
    {
      get title() {
        return isAllowEverything(sync.data.config.permission) ? "Disable auto-approve mode" : "Enable auto-approve mode"
      },
      value: "permission.allow_everything",
      category: "System",
      onSelect: async (dialog) => {
        const enabled = isAllowEverything(sync.data.config.permission)
        const result = await sdk.client.permission.allowEverything({ enable: !enabled })
        if (result.error) {
          toast.show({
            variant: "error",
            message: `Failed to ${!enabled ? "enable" : "disable"} auto-approve mode`,
          })
          return
        }
        dialog.clear()
      },
    },
  ])
}
