import type { CommandOption } from "@tui/component/dialog-command"
import type { Setter } from "solid-js"
import { t } from "@/util/i18n"
import open from "open"
import { DialogStatus } from "@tui/component/dialog-status"
import { DialogThemeList } from "@tui/component/dialog-theme-list"
import { DialogHelp } from "@tui/ui/dialog-help"
import * as Log from "@saeeol/core/util/log"

type Dialog = ReturnType<typeof import("@tui/ui/dialog").useDialog>
type KV = ReturnType<typeof import("@tui/context/kv").useKV>
type Renderer = ReturnType<typeof import("@opentui/solid").useRenderer>
type Exit = ReturnType<typeof import("@tui/context/exit").useExit>
type Toast = ReturnType<typeof import("@tui/ui/toast").useToast>
type TuiConfig = ReturnType<typeof import("@tui/context/tui-config").useTuiConfig>
type Sync = ReturnType<typeof import("@tui/context/sync").useSync>

export type SystemCommandDeps = {
  dialog: Dialog
  kv: KV
  renderer: Renderer
  exit: Exit
  toast: Toast
  tuiConfig: TuiConfig
  sync: Sync
  onSnapshot?: () => Promise<string[]>
  mode: () => "dark" | "light"
  setMode: (m: "dark" | "light") => void
  locked: () => boolean
  lock: () => void
  unlock: () => void
  terminalTitleEnabled: () => boolean
  setTerminalTitleEnabled: Setter<boolean>
  pasteSummaryEnabled: () => boolean
  setPasteSummaryEnabled: Setter<boolean>
  docsUrl: string
}

export function registerSystemCommands(deps: SystemCommandDeps): CommandOption[] {
  const {
    dialog,
    kv,
    renderer,
    exit,
    toast,
    tuiConfig,
    sync,
    onSnapshot,
    mode,
    setMode,
    locked,
    lock,
    unlock,
    terminalTitleEnabled,
    setTerminalTitleEnabled,
    pasteSummaryEnabled,
    setPasteSummaryEnabled,
    docsUrl,
  } = deps
  return [
    {
      title: t("cmd.system.status"),
      keybind: "status_view",
      value: "saeeol.status",
      slash: {
        name: "status",
      },
      onSelect: () => {
        dialog.replace(() => <DialogStatus />)
      },
      category: t("cmd.cat.system"),
    },
    {
      title: t("cmd.system.theme_switch"),
      value: "theme.switch",
      keybind: "theme_list",
      slash: {
        name: "themes",
      },
      onSelect: () => {
        dialog.replace(() => <DialogThemeList />)
      },
      category: t("cmd.cat.system"),
    },
    {
      title: mode() === "dark" ? t("cmd.system.theme_light") : t("cmd.system.theme_dark"),
      value: "theme.switch_mode",
      onSelect: (dialog) => {
        setMode(mode() === "dark" ? "light" : "dark")
        dialog.clear()
      },
      category: t("cmd.cat.system"),
    },
    {
      title: locked() ? t("cmd.system.theme_unlock") : t("cmd.system.theme_lock"),
      value: "theme.mode.lock",
      onSelect: (dialog) => {
        if (locked()) unlock()
        else lock()
        dialog.clear()
      },
      category: t("cmd.cat.system"),
    },
    {
      title: t("cmd.system.help"),
      value: "help.show",
      slash: {
        name: "help",
      },
      onSelect: () => {
        dialog.replace(() => <DialogHelp />)
      },
      category: t("cmd.cat.system"),
    },
    {
      title: "Open Log File",
      value: "app.logs",
      slash: {
        name: "logs",
      },
      onSelect: () => {
        const logPath = Log.file()
        if (logPath) {
          open(logPath).catch(() => {
            toast.show({ variant: "error", message: logPath, duration: 10000 })
          })
        } else {
          toast.show({ variant: "error", message: "No log file available", duration: 3000 })
        }
        dialog.clear()
      },
      category: t("cmd.cat.system"),
    },
    {
      title: t("cmd.system.docs"),
      value: "docs.open",
      onSelect: () => {
        open(docsUrl).catch(() => {})
        dialog.clear()
      },
      category: t("cmd.cat.system"),
    },
    {
      title: t("cmd.system.exit"),
      value: "app.exit",
      slash: {
        name: "exit",
        aliases: ["quit", "q"],
      },
      onSelect: () => exit(),
      category: t("cmd.cat.system"),
    },
    {
      title: t("cmd.system.restart"),
      value: "app.restart",
      slash: {
        name: "restart",
        aliases: ["rs"],
      },
      onSelect: () => exit.restart(),
      category: t("cmd.cat.system"),
    },
    {
      title: t("cmd.system.debug"),
      category: t("cmd.cat.system"),
      value: "app.debug",
      onSelect: (dialog) => {
        renderer.toggleDebugOverlay()
        dialog.clear()
      },
    },
    {
      title: t("cmd.system.console"),
      category: t("cmd.cat.system"),
      value: "app.console",
      onSelect: (dialog) => {
        renderer.console.toggle()
        dialog.clear()
      },
    },
    {
      title: t("cmd.system.heap_snapshot"),
      category: t("cmd.cat.system"),
      value: "app.heap_snapshot",
      onSelect: async (dialog) => {
        const files = await onSnapshot?.()
        toast.show({
          variant: "info",
          message: `Heap snapshot written to ${files?.join(", ")}`,
          duration: 5000,
        })
        dialog.clear()
      },
    },
    {
      title: t("cmd.system.suspend"),
      value: "terminal.suspend",
      keybind: "terminal_suspend",
      category: t("cmd.cat.system"),
      hidden: true,
      enabled: tuiConfig.keybinds?.terminal_suspend !== "none",
      onSelect: () => {
        process.once("SIGCONT", () => {
          renderer.resume()
        })
        renderer.suspend()
        process.kill(0, "SIGTSTP")
      },
    },
    {
      title: terminalTitleEnabled() ? t("cmd.system.terminal_title_disable") : t("cmd.system.terminal_title_enable"),
      value: "terminal.title.toggle",
      keybind: "terminal_title_toggle",
      category: t("cmd.cat.system"),
      onSelect: (dialog) => {
        setTerminalTitleEnabled((prev) => {
          const next = !prev
          kv.set("terminal_title_enabled", next)
          if (!next) renderer.setTerminalTitle("")
          return next
        })
        dialog.clear()
      },
    },
    {
      title: kv.get("bell_enabled", true) ? t("cmd.system.notifications_disable") : t("cmd.system.notifications_enable"),
      value: "app.toggle.notifications",
      category: t("cmd.cat.system"),
      onSelect: (dialog) => {
        kv.set("bell_enabled", !kv.get("bell_enabled", true))
        dialog.clear()
      },
    },
    {
      title: kv.get("animations_enabled", true) ? t("cmd.system.animations_disable") : t("cmd.system.animations_enable"),
      value: "app.toggle.animations",
      category: t("cmd.cat.system"),
      onSelect: (dialog) => {
        kv.set("animations_enabled", !kv.get("animations_enabled", true))
        dialog.clear()
      },
    },
    {
      title: kv.get("file_context_enabled", true) ? t("cmd.system.file_context_disable") : t("cmd.system.file_context_enable"),
      value: "app.toggle.file_context",
      category: t("cmd.cat.system"),
      onSelect: (dialog) => {
        kv.set("file_context_enabled", !kv.get("file_context_enabled", true))
        dialog.clear()
      },
    },
    {
      title: pasteSummaryEnabled() ? t("cmd.system.paste_summary_disable") : t("cmd.system.paste_summary_enable"),
      value: "app.toggle.paste_summary",
      category: t("cmd.cat.system"),
      onSelect: (dialog) => {
        setPasteSummaryEnabled((prev) => {
          const next = !prev
          kv.set("paste_summary_enabled", next)
          return next
        })
        dialog.clear()
      },
    },
    {
      title: kv.get("session_directory_filter_enabled", true)
        ? t("cmd.system.session_dir_filter_disable")
        : t("cmd.system.session_dir_filter_enable"),
      value: "app.toggle.session_directory_filter",
      category: t("cmd.cat.system"),
      onSelect: async (dialog) => {
        kv.set("session_directory_filter_enabled", !kv.get("session_directory_filter_enabled", true))
        await sync.session.refresh()
        dialog.clear()
      },
    },
    {
      title: kv.get("diff_wrap_mode", "word") === "word" ? t("cmd.system.diffwrap_disable") : t("cmd.system.diffwrap_enable"),
      value: "app.toggle.diffwrap",
      category: t("cmd.cat.system"),
      onSelect: (dialog) => {
        const current = kv.get("diff_wrap_mode", "word")
        kv.set("diff_wrap_mode", current === "word" ? "none" : "word")
        dialog.clear()
      },
    },
  ]
}
