import { useCallback, useEffect, useMemo, useRef, useState } from "react"
import type {
  AutomationTask,
  AutomationTaskRun,
  AutomationTaskSchedule,
  ProjectSummary,
  UpdateAutomationTaskInput
} from "@qjclaw/shared-types"
import { Button } from "../../components/ui/Button"
import { Panel } from "../../components/ui/Panel"
import { ScrollArea } from "../../components/ui/ScrollArea"
import { StatusChip } from "../../components/ui/StatusChip"
import { EditIcon, PlusIcon, RefreshIcon, TrashIcon } from "../../components/icons/AppIcons"
import { desktopApi } from "../../lib/desktop-api"
import { HOME_CHAT_PROJECT_ID } from "../../lib/constants"
import { renderChatMessageContent } from "../chat/renderChatMessageContent"

type FilterMode = "all" | "enabled" | "disabled"
type FormScheduleKind = AutomationTaskSchedule["kind"]

interface AutomationTasksViewProps {
  projects: ProjectSummary[]
}

interface AutomationTaskFormState {
  id?: string
  title: string
  prompt: string
  expertId: string
  enabled: boolean
  scheduleKind: FormScheduleKind
  runAt: string
  time: string
  weekdays: number[]
}

const weekdayLabels = ["日", "一", "二", "三", "四", "五", "六"]
const activeRunStatuses = new Set<AutomationTaskRun["status"]>(["queued", "running"])

function toDateTimeLocalValue(date: Date) {
  const year = date.getFullYear()
  const month = String(date.getMonth() + 1).padStart(2, "0")
  const day = String(date.getDate()).padStart(2, "0")
  const hour = String(date.getHours()).padStart(2, "0")
  const minute = String(date.getMinutes()).padStart(2, "0")
  return `${year}-${month}-${day}T${hour}:${minute}`
}

function createDefaultForm(projects: ProjectSummary[]): AutomationTaskFormState {
  const nextHour = new Date(Date.now() + 60 * 60 * 1000)
  return {
    title: "",
    prompt: "",
    expertId: projects[0]?.id ?? "",
    enabled: true,
    scheduleKind: "daily",
    runAt: toDateTimeLocalValue(nextHour),
    time: "09:00",
    weekdays: [new Date().getDay()]
  }
}

function formFromTask(task: AutomationTask): AutomationTaskFormState {
  const base = createDefaultForm([])
  const schedule = task.schedule
  return {
    id: task.id,
    title: task.title,
    prompt: task.prompt,
    expertId: task.expertId ?? "",
    enabled: task.enabled,
    scheduleKind: schedule.kind,
    runAt: schedule.kind === "once" ? toDateTimeLocalValue(new Date(schedule.runAt)) : base.runAt,
    time: schedule.kind === "once" ? base.time : schedule.time,
    weekdays: schedule.kind === "weekly" ? schedule.weekdays : base.weekdays
  }
}

function scheduleFromForm(form: AutomationTaskFormState): AutomationTaskSchedule {
  if (form.scheduleKind === "once") {
    return {
      kind: "once",
      runAt: new Date(form.runAt).toISOString()
    }
  }
  if (form.scheduleKind === "weekly") {
    return {
      kind: "weekly",
      time: form.time,
      weekdays: form.weekdays.length ? form.weekdays : [new Date().getDay()]
    }
  }
  return {
    kind: "daily",
    time: form.time
  }
}

function formatDateTime(value?: string) {
  if (!value) {
    return "未安排"
  }
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) {
    return value
  }
  return date.toLocaleString("zh-CN", {
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit"
  })
}

function formatSchedule(schedule: AutomationTaskSchedule) {
  if (schedule.kind === "once") {
    return `一次性 ${formatDateTime(schedule.runAt)}`
  }
  if (schedule.kind === "daily") {
    return `每天 ${schedule.time}`
  }
  return `每周${schedule.weekdays.map((day) => weekdayLabels[day]).join("、")} ${schedule.time}`
}

function getRunStatusLabel(status?: AutomationTaskRun["status"]) {
  switch (status) {
    case "completed":
      return "已完成"
    case "running":
      return "执行中"
    case "failed":
      return "失败"
    case "missed":
      return "已错过"
    case "queued":
      return "排队中"
    default:
      return "未运行"
  }
}

function getStatusTone(status?: AutomationTaskRun["status"]) {
  if (status === "completed") {
    return "positive" as const
  }
  if (status === "running" || status === "queued") {
    return "info" as const
  }
  if (status === "failed" || status === "missed") {
    return "warning" as const
  }
  return "info" as const
}

function getTaskLifecycleLabel(task: AutomationTask) {
  if (task.enabled) {
    return "启用"
  }
  if (task.schedule.kind === "once" && task.lastRunStatus === "completed") {
    return "已完成，已停用"
  }
  if (task.schedule.kind === "once" && task.lastRunStatus === "missed") {
    return "已错过，已停用"
  }
  return "已停用"
}

function getTaskNextRunLabel(task: AutomationTask) {
  return task.enabled ? formatDateTime(task.nextRunAt) : getTaskLifecycleLabel(task)
}

function truncateText(text: string, maxLength: number) {
  return text.length > maxLength ? `${text.slice(0, maxLength)}...` : text
}

export function AutomationTasksView({ projects }: AutomationTasksViewProps) {
  const [tasks, setTasks] = useState<AutomationTask[]>([])
  const [runs, setRuns] = useState<AutomationTaskRun[]>([])
  const [selectedTaskId, setSelectedTaskId] = useState("")
  const [filterMode, setFilterMode] = useState<FilterMode>("all")
  const [form, setForm] = useState<AutomationTaskFormState | null>(null)
  const [loading, setLoading] = useState(true)
  const [saving, setSaving] = useState(false)
  const [errorText, setErrorText] = useState("")
  const [optimisticRunningTaskIds, setOptimisticRunningTaskIds] = useState<Set<string>>(() => new Set())
  const selectedTaskIdRef = useRef("")

  const expertOptions = useMemo(() => [
    { id: "", label: "通用助手" },
    ...projects.filter((project) => project.id !== HOME_CHAT_PROJECT_ID).map((project) => ({
      id: project.id,
      label: project.displayName || project.name || project.id
    }))
  ], [projects])

  const selectedTask = useMemo(
    () => tasks.find((task) => task.id === selectedTaskId) ?? tasks[0],
    [selectedTaskId, tasks]
  )
  const filteredTasks = useMemo(() => tasks.filter((task) => {
    if (filterMode === "enabled") {
      return task.enabled
    }
    if (filterMode === "disabled") {
      return !task.enabled
    }
    return true
  }), [filterMode, tasks])

  useEffect(() => {
    selectedTaskIdRef.current = selectedTask?.id ?? ""
  }, [selectedTask?.id])

  const loadTasks = useCallback(async () => {
    setLoading(true)
    setErrorText("")
    try {
      const nextTasks = await desktopApi.automationTasks.list()
      setTasks(nextTasks)
      setSelectedTaskId((current) => current && nextTasks.some((task) => task.id === current) ? current : nextTasks[0]?.id ?? "")
    } catch (error) {
      setErrorText(error instanceof Error ? error.message : "自动化任务加载失败")
    } finally {
      setLoading(false)
    }
  }, [])

  const loadSelectedTaskRuns = useCallback(async () => {
    const taskId = selectedTask?.id
    if (!taskId) {
      setRuns([])
      return []
    }
    try {
      const nextRuns = await desktopApi.automationTasks.listRuns(taskId)
      if (selectedTaskIdRef.current === taskId) {
        setRuns(nextRuns)
      }
      return nextRuns
    } catch (error) {
      setErrorText(error instanceof Error ? error.message : "运行记录加载失败")
      return []
    }
  }, [selectedTask?.id])

  useEffect(() => {
    void loadTasks()
  }, [loadTasks])

  useEffect(() => {
    void loadSelectedTaskRuns()
  }, [loadSelectedTaskRuns])

  const startCreate = () => {
    setForm(createDefaultForm(projects))
  }

  const startEdit = (task: AutomationTask) => {
    setForm(formFromTask(task))
  }

  const submitForm = async () => {
    if (!form) {
      return
    }
    const title = form.title.trim()
    const prompt = form.prompt.trim()
    if (!title || !prompt) {
      setErrorText("请填写标题和任务内容")
      return
    }

    setSaving(true)
    setErrorText("")
    try {
      const selectedExpert = expertOptions.find((option) => option.id === form.expertId)
      const expertId = form.expertId || (form.id ? null : undefined)
      const expertName = form.expertId ? selectedExpert?.label : (form.id ? null : undefined)
      const input = {
        title,
        prompt,
        expertId,
        expertName,
        enabled: form.enabled,
        schedule: scheduleFromForm(form)
      }
      const saved = form.id
        ? await desktopApi.automationTasks.update(form.id, input satisfies UpdateAutomationTaskInput)
        : await desktopApi.automationTasks.create({
            title,
            prompt,
            expertId: form.expertId || undefined,
            expertName: form.expertId ? selectedExpert?.label : undefined,
            enabled: form.enabled,
            schedule: scheduleFromForm(form)
          })
      if (saved) {
        setSelectedTaskId(saved.id)
      }
      setForm(null)
      await loadTasks()
    } catch (error) {
      setErrorText(error instanceof Error ? error.message : "自动化任务保存失败")
    } finally {
      setSaving(false)
    }
  }

  const deleteTask = async (taskId: string) => {
    const task = tasks.find((candidate) => candidate.id === taskId)
    const confirmed = window.confirm(`确认删除自动化任务「${task?.title ?? "未命名任务"}」？`)
    if (!confirmed) {
      return
    }

    setSaving(true)
    setErrorText("")
    try {
      await desktopApi.automationTasks.delete(taskId)
      setForm(null)
      await loadTasks()
    } catch (error) {
      setErrorText(error instanceof Error ? error.message : "自动化任务删除失败")
    } finally {
      setSaving(false)
    }
  }

  const runTaskNow = async (taskId: string) => {
    setOptimisticRunningTaskIds((current) => new Set(current).add(taskId))
    setSaving(true)
    setErrorText("")
    try {
      const run = await desktopApi.automationTasks.runNow(taskId)
      if (selectedTaskIdRef.current === taskId) {
        setRuns((current) => [run, ...current.filter((item) => item.id !== run.id)])
      }
      await loadTasks()
    } catch (error) {
      setErrorText(error instanceof Error ? error.message : "立即执行失败")
    } finally {
      setOptimisticRunningTaskIds((current) => {
        const next = new Set(current)
        next.delete(taskId)
        return next
      })
      setSaving(false)
    }
  }

  const copyRunMarkdownCode = async (_token: string, text: string) => {
    await navigator.clipboard?.writeText(text)
  }

  const hasActiveSelectedRun = runs.some((run) => run.taskId === selectedTask?.id && activeRunStatuses.has(run.status))
  const hasOptimisticSelectedRun = optimisticRunningTaskIds.has(selectedTask?.id ?? "")
  const isRunningSelectedTask = hasActiveSelectedRun || hasOptimisticSelectedRun
  const shouldPollSelectedRuns = hasActiveSelectedRun || hasOptimisticSelectedRun

  useEffect(() => {
    if (!shouldPollSelectedRuns) {
      return
    }
    const pollTimer = window.setInterval(() => {
      void loadSelectedTaskRuns()
      void loadTasks()
    }, 2000)
    return () => {
      window.clearInterval(pollTimer)
    }
  }, [shouldPollSelectedRuns, loadSelectedTaskRuns, loadTasks])

  return (
    <div className="automation-page-stack">
      <Panel
        className="automation-page"
        bodyClassName="automation-page-body"
        header={(
          <div className="automation-header">
            <div>
              <h1>自动化任务</h1>
            </div>
            <div className="automation-header-actions">
              <Button variant="secondary" size="sm" className="automation-action-button automation-button-secondary" onClick={() => void loadTasks()} disabled={loading || saving}>
                <RefreshIcon />
                <span>刷新</span>
              </Button>
              <Button size="sm" className="automation-action-button automation-button-primary" onClick={startCreate}>
                <PlusIcon />
                <span>新建任务</span>
              </Button>
            </div>
          </div>
        )}
      >
        {errorText ? <div className="notice error" role="alert">{errorText}</div> : null}
        <div className="automation-layout">
          <aside className="automation-list-pane" aria-label="自动化任务列表">
            <div className="automation-filter-row">
              {([
                ["all", "全部"],
                ["enabled", "启用"],
                ["disabled", "停用"]
              ] as const).map(([key, label]) => (
                <button
                  key={key}
                  type="button"
                  className={filterMode === key ? "active" : ""}
                  onClick={() => setFilterMode(key)}
                >
                  {label}
                </button>
              ))}
            </div>
            <ScrollArea className="automation-list-scroll">
              <div className="automation-task-list">
                {loading ? (
                  <div className="automation-empty">正在加载</div>
                ) : filteredTasks.length ? filteredTasks.map((task) => (
                  <article
                    key={task.id}
                    className={"automation-task-row" + (selectedTask?.id === task.id ? " active" : "")}
                  >
                    <button
                      type="button"
                      className="automation-task-select"
                      onClick={() => setSelectedTaskId(task.id)}
                    >
                      <strong>{truncateText(task.title, 20)}</strong>
                      <small>{truncateText(task.prompt, 20)}</small>
                    </button>
                  </article>
                )) : (
                  <div className="automation-empty">暂无任务</div>
                )}
              </div>
            </ScrollArea>
          </aside>
          <section className="automation-detail-pane" aria-label="自动化任务详情">
            {form ? (
              <div className="automation-form">
                <div className="automation-form-grid">
                  <label>
                    <span>标题</span>
                    <input value={form.title} onChange={(event) => setForm({ ...form, title: event.target.value })} />
                  </label>
                  <label>
                    <span>执行专家</span>
                    <select value={form.expertId} onChange={(event) => setForm({ ...form, expertId: event.target.value })}>
                      {expertOptions.map((option) => (
                        <option key={option.id || "home"} value={option.id}>{option.label}</option>
                      ))}
                    </select>
                  </label>
                  <label className="automation-form-full">
                    <span>任务内容</span>
                    <textarea rows={5} value={form.prompt} onChange={(event) => setForm({ ...form, prompt: event.target.value })} />
                  </label>
                  <label>
                    <span>规则</span>
                    <select value={form.scheduleKind} onChange={(event) => setForm({ ...form, scheduleKind: event.target.value as FormScheduleKind })}>
                      <option value="once">一次性</option>
                      <option value="daily">每天</option>
                      <option value="weekly">每周</option>
                    </select>
                  </label>
                  {form.scheduleKind === "once" ? (
                    <label>
                      <span>执行时间</span>
                      <input type="datetime-local" value={form.runAt} onChange={(event) => setForm({ ...form, runAt: event.target.value })} />
                    </label>
                  ) : (
                    <label>
                      <span>具体时间</span>
                      <input type="time" value={form.time} onChange={(event) => setForm({ ...form, time: event.target.value })} />
                    </label>
                  )}
                  {form.scheduleKind === "weekly" ? (
                    <div className="automation-weekdays automation-form-full">
                      {weekdayLabels.map((label, day) => (
                        <label key={day}>
                          <input
                            type="checkbox"
                            checked={form.weekdays.includes(day)}
                            onChange={(event) => setForm({
                              ...form,
                              weekdays: event.target.checked
                                ? [...form.weekdays, day].sort((left, right) => left - right)
                                : form.weekdays.filter((value) => value !== day)
                            })}
                          />
                          <span>{label}</span>
                        </label>
                      ))}
                    </div>
                  ) : null}
                  <label className="automation-enabled-toggle">
                    <input type="checkbox" checked={form.enabled} onChange={(event) => setForm({ ...form, enabled: event.target.checked })} />
                    <span>启用任务</span>
                  </label>
                </div>
                <div className="automation-form-actions">
                  <Button variant="secondary" size="sm" className="automation-form-button-secondary" onClick={() => setForm(null)} disabled={saving}>取消</Button>
                  <Button size="sm" className="automation-form-button-primary" onClick={() => void submitForm()} disabled={saving}>{saving ? "保存中" : "保存"}</Button>
                </div>
              </div>
            ) : selectedTask ? (
              <>
                <div className="automation-detail-head">
                  <div>
                    <span className="automation-kicker">{selectedTask.expertName || "通用助手"}</span>
                    <h2>{selectedTask.title}</h2>
                    <p className="automation-detail-prompt">{truncateText(selectedTask.prompt, 30)}</p>
                  </div>
                  <div className="automation-detail-actions">
                    <Button variant="secondary" size="sm" className="automation-action-button automation-button-secondary" onClick={() => startEdit(selectedTask)} disabled={saving}>
                      <EditIcon />
                      <span>编辑</span>
                    </Button>
                    <Button size="sm" className="automation-action-button automation-button-accent" onClick={() => void runTaskNow(selectedTask.id)} disabled={saving || isRunningSelectedTask}>
                      {isRunningSelectedTask ? (
                        <>
                          <span className="automation-button-spinner" aria-hidden="true" />
                          <span>执行中</span>
                        </>
                      ) : <span>立即执行</span>}
                    </Button>
                    <button
                      type="button"
                      className="button button-sm automation-action-button automation-delete-button"
                      onClick={() => void deleteTask(selectedTask.id)}
                      disabled={saving}
                    >
                      <TrashIcon />
                      <span>删除</span>
                    </button>
                  </div>
                </div>
                <div className="automation-meta-grid">
                  <div>
                    <span>定时规则</span>
                    <strong>{formatSchedule(selectedTask.schedule)}</strong>
                  </div>
                  <div>
                    <span>下次执行</span>
                    <strong>{getTaskNextRunLabel(selectedTask)}</strong>
                  </div>
                  <div>
                    <span>最近状态</span>
                    <strong>{getTaskLifecycleLabel(selectedTask)}</strong>
                  </div>
                </div>
                <div className="automation-runs">
                  <h3>运行记录</h3>
                  <div className="automation-run-list">
                    {runs.length ? runs.map((run) => (
                      <article key={run.id} className="automation-run-item">
                        <div className="automation-run-meta">
                          <StatusChip tone={getStatusTone(run.status)}>{getRunStatusLabel(run.status)}</StatusChip>
                          <span>{formatDateTime(run.completedAt ?? run.startedAt ?? run.scheduledFor)}</span>
                        </div>
                        {run.replyText ? (
                          <div className="markdown-body automation-run-markdown">
                            {renderChatMessageContent(run.replyText, {
                              messageId: `automation-run-${run.id}`,
                              copiedToken: "",
                              onCopy: copyRunMarkdownCode
                            })}
                          </div>
                        ) : null}
                        {run.error ? <p className="automation-run-error">{run.error}</p> : null}
                      </article>
                    )) : (
                      <div className="automation-empty">暂无运行记录</div>
                    )}
                  </div>
                </div>
              </>
            ) : (
              <div className="automation-empty">暂无任务</div>
            )}
          </section>
        </div>
      </Panel>
    </div>
  )
}
