"use client";

import { FormEvent, useMemo, useState } from "react";
import { Radio, Search, ShieldAlert, Siren } from "lucide-react";

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Dialog } from "@/components/ui/dialog";
import { Input, Textarea } from "@/components/ui/input";
import { Select } from "@/components/ui/select";
import { Table } from "@/components/ui/table";
import type { IncidentSeverity } from "@/modules/core/types";
import type { ApiResult } from "@/modules/core/server/api";
import { INCIDENT_SEVERITY_LABELS } from "@/modules/emergency/types";
import type { AlertCenterData, AlertRule, AlertRuleInput, AlertRuleStatus, AlertRuleType, AlertTrigger, AlertTriggerInput, AlertTriggerStatus } from "@/modules/alerts/types";
import { ALERT_RULE_STATUS_LABELS, ALERT_RULE_STATUS_VALUES, ALERT_RULE_TYPE_LABELS, ALERT_RULE_TYPE_VALUES, ALERT_TRIGGER_STATUS_LABELS, ALERT_TRIGGER_STATUS_VALUES } from "@/modules/alerts/types";

type Props = { canManage: boolean; initialData: AlertCenterData };
type DialogState =
  | { kind: "rule"; mode: "create"; value: AlertRuleInput }
  | { kind: "rule"; mode: "edit"; id: string; value: AlertRuleInput }
  | { kind: "trigger"; mode: "create"; value: AlertTriggerInput }
  | { kind: "trigger"; mode: "edit"; id: string; value: AlertTriggerInput };

const severityValues = ["info", "warning", "critical"] as const satisfies readonly IncidentSeverity[];
const emptyRule: AlertRuleInput = { name: "", ruleType: "health", severity: "warning", status: "enabled", conditionSummary: "", suggestion: "" };
const emptyTrigger: AlertTriggerInput = { ruleId: undefined, elderId: undefined, title: "", description: "", status: "open", source: "", handlingNotes: "" };

function formatDateTime(value: string | undefined): string {
  return value ? new Date(value).toLocaleString("zh-CN") : "-";
}

function ruleToInput(rule: AlertRule): AlertRuleInput {
  return { name: rule.name, ruleType: rule.ruleType, severity: rule.severity, status: rule.status, conditionSummary: rule.conditionSummary, suggestion: rule.suggestion };
}

function triggerToInput(trigger: AlertTrigger): AlertTriggerInput {
  return { ruleId: trigger.ruleId, elderId: trigger.elderId, title: trigger.title, description: trigger.description, status: trigger.status, source: trigger.source, handlingNotes: trigger.handlingNotes };
}

function badgeVariant(value: string): "danger" | "secondary" | "success" | "warning" {
  if (value === "critical") return "danger";
  if (value === "enabled" || value === "resolved" || value === "closed") return "success";
  if (value === "open" || value === "acknowledged" || value === "warning") return "warning";
  return "secondary";
}

export function AlertsWorkspaceClient({ canManage, initialData }: Props): React.ReactElement {
  const [data, setData] = useState(initialData);
  const [query, setQuery] = useState("");
  const [triggerStatus, setTriggerStatus] = useState<"all" | AlertTriggerStatus>("all");
  const [dialog, setDialog] = useState<DialogState | undefined>();
  const [message, setMessage] = useState("");
  const [isPending, setIsPending] = useState(false);
  const normalizedQuery = query.trim().toLowerCase();
  const filteredRules = useMemo(() => data.rules.filter((rule) => !normalizedQuery || [rule.name, rule.conditionSummary, rule.suggestion].join(" ").toLowerCase().includes(normalizedQuery)), [data.rules, normalizedQuery]);
  const filteredTriggers = useMemo(
    () =>
      data.triggers.filter((trigger) => {
        const matchesQuery = !normalizedQuery || [trigger.title, trigger.description, trigger.ruleName, trigger.elderName, trigger.source].join(" ").toLowerCase().includes(normalizedQuery);
        return matchesQuery && (triggerStatus === "all" || trigger.status === triggerStatus);
      }),
    [data.triggers, normalizedQuery, triggerStatus],
  );

  async function refreshData(): Promise<void> {
    const response = await fetch("/api/alerts/rules");
    const result = (await response.json()) as ApiResult<{ data: AlertCenterData }>;
    if (result.success) setData(result.data);
  }

  async function submitDialog(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    if (!dialog || !canManage) {
      setMessage("当前角色无权维护规则预警");
      return;
    }
    const isCreate = dialog.mode === "create";
    const path = dialog.kind === "rule" ? (isCreate ? "/api/alerts/rules" : `/api/alerts/rules/${dialog.id}`) : isCreate ? "/api/alerts/triggers" : `/api/alerts/triggers/${dialog.id}`;
    setIsPending(true);
    const response = await fetch(path, { method: isCreate ? "POST" : "PATCH", headers: { "content-type": "application/json" }, body: JSON.stringify(dialog.value) });
    const result = (await response.json()) as ApiResult<Record<string, unknown>>;
    setIsPending(false);
    setMessage(result.reason);
    if (result.success) {
      setDialog(undefined);
      await refreshData();
    }
  }

  async function remove(kind: "rule" | "trigger", id: string): Promise<void> {
    if (!canManage) {
      setMessage("当前角色无权删除规则预警记录");
      return;
    }
    setIsPending(true);
    const response = await fetch(kind === "rule" ? `/api/alerts/rules/${id}` : `/api/alerts/triggers/${id}`, { method: "DELETE" });
    const result = (await response.json()) as ApiResult<Record<string, unknown>>;
    setIsPending(false);
    setMessage(result.reason);
    if (result.success) await refreshData();
  }

  return (
    <div className="mx-auto flex w-full max-w-7xl flex-col gap-5">
      <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <MetricCard icon={Radio} label="启用规则" value={data.metrics.enabledRules} />
        <MetricCard icon={ShieldAlert} label="待处理触发" value={data.metrics.openTriggers} />
        <MetricCard icon={Siren} label="紧急触发" value={data.metrics.criticalTriggers} />
        <MetricCard icon={Radio} label="已处理触发" value={data.metrics.resolvedTriggers} />
      </section>
      <section className="flex flex-col gap-3 border-b pb-4 xl:flex-row xl:items-center xl:justify-between">
        <div><h1 className="text-3xl font-semibold tracking-normal">规则预警</h1><p className="mt-2 text-sm text-muted-foreground">维护规则并处理预警触发记录。</p></div>
        <div className="grid gap-2 sm:grid-cols-2 xl:flex xl:items-center">
          <label className="relative block sm:col-span-2 xl:col-span-1"><Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" /><Input className="w-full pl-9 xl:w-72" onChange={(event) => setQuery(event.target.value)} placeholder="搜索规则或触发记录" value={query} /></label>
          <Select aria-label="触发状态" onValueChange={(value) => setTriggerStatus(value as "all" | AlertTriggerStatus)} options={[{ value: "all", label: "全部触发状态" }, ...ALERT_TRIGGER_STATUS_VALUES.map((value) => ({ value, label: ALERT_TRIGGER_STATUS_LABELS[value] }))]} value={triggerStatus} />
          <Button disabled={!canManage} onClick={() => setDialog({ kind: "rule", mode: "create", value: emptyRule })} type="button">新增规则</Button>
          <Button disabled={!canManage} onClick={() => setDialog({ kind: "trigger", mode: "create", value: emptyTrigger })} type="button" variant="outline">新增触发</Button>
        </div>
      </section>
      {message ? <p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">{message}</p> : null}
      <DataTable title="预警规则" empty="暂无预警规则" colSpan={6} heads={["规则", "类型", "级别", "状态", "更新时间", "操作"]}>
        {filteredRules.map((rule) => (
          <Table.Row key={rule.id}>
            <Table.Cell className="px-4 py-3"><p className="font-medium">{rule.name}</p><p className="text-xs text-muted-foreground">{rule.conditionSummary || "-"}</p></Table.Cell>
            <Table.Cell className="px-4 py-3 text-muted-foreground">{ALERT_RULE_TYPE_LABELS[rule.ruleType]}</Table.Cell>
            <Table.Cell className="px-4 py-3"><Badge variant={badgeVariant(rule.severity)}>{INCIDENT_SEVERITY_LABELS[rule.severity]}</Badge></Table.Cell>
            <Table.Cell className="px-4 py-3"><Badge variant={badgeVariant(rule.status)}>{ALERT_RULE_STATUS_LABELS[rule.status]}</Badge></Table.Cell>
            <Table.Cell className="px-4 py-3 text-muted-foreground">{formatDateTime(rule.updatedAt)}</Table.Cell>
            <Table.Cell className="px-4 py-3"><RowActions disabled={!canManage || isPending} onDelete={() => remove("rule", rule.id)} onEdit={() => setDialog({ kind: "rule", mode: "edit", id: rule.id, value: ruleToInput(rule) })} /></Table.Cell>
          </Table.Row>
        ))}
        {filteredRules.length === 0 ? <EmptyRow colSpan={6} text="暂无预警规则" /> : null}
      </DataTable>
      <DataTable title="触发记录" empty="暂无触发记录" colSpan={7} heads={["记录", "规则", "老人", "状态", "来源", "更新时间", "操作"]}>
        {filteredTriggers.map((trigger) => (
          <Table.Row key={trigger.id}>
            <Table.Cell className="px-4 py-3"><p className="font-medium">{trigger.title}</p><p className="text-xs text-muted-foreground">{trigger.description || trigger.handlingNotes || "-"}</p></Table.Cell>
            <Table.Cell className="px-4 py-3 text-muted-foreground">{trigger.ruleName || "-"}</Table.Cell>
            <Table.Cell className="px-4 py-3 text-muted-foreground">{trigger.elderName || "-"}</Table.Cell>
            <Table.Cell className="px-4 py-3"><Badge variant={badgeVariant(trigger.status)}>{ALERT_TRIGGER_STATUS_LABELS[trigger.status]}</Badge></Table.Cell>
            <Table.Cell className="px-4 py-3 text-muted-foreground">{trigger.source || "-"}</Table.Cell>
            <Table.Cell className="px-4 py-3 text-muted-foreground">{formatDateTime(trigger.updatedAt)}</Table.Cell>
            <Table.Cell className="px-4 py-3"><RowActions disabled={!canManage || isPending} onDelete={() => remove("trigger", trigger.id)} onEdit={() => setDialog({ kind: "trigger", mode: "edit", id: trigger.id, value: triggerToInput(trigger) })} /></Table.Cell>
          </Table.Row>
        ))}
        {filteredTriggers.length === 0 ? <EmptyRow colSpan={7} text="暂无触发记录" /> : null}
      </DataTable>
      <Dialog onClose={() => setDialog(undefined)} open={dialog !== undefined} title={dialog?.kind === "rule" ? "预警规则" : "触发记录"} width="lg">
        {dialog ? <form className="grid gap-3" onSubmit={submitDialog}>{dialog.kind === "rule" ? <RuleForm dialog={dialog} setDialog={setDialog} /> : <TriggerForm dialog={dialog} rules={data.rules} setDialog={setDialog} />}<div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"><Button disabled={isPending} onClick={() => setDialog(undefined)} type="button" variant="outline">取消</Button><Button disabled={isPending || !canManage} type="submit">保存</Button></div></form> : null}
      </Dialog>
    </div>
  );
}

function RuleForm({ dialog, setDialog }: { dialog: Extract<DialogState, { kind: "rule" }>; setDialog: (dialog: DialogState) => void }): React.ReactElement {
  const value = dialog.value;
  const update = (next: Partial<AlertRuleInput>) => setDialog({ ...dialog, value: { ...value, ...next } });
  return <><Input label="规则名称" onChange={(event) => update({ name: event.target.value })} required value={value.name} /><Select aria-label="规则类型" onValueChange={(ruleType) => update({ ruleType: ruleType as AlertRuleType })} options={ALERT_RULE_TYPE_VALUES.map((item) => ({ value: item, label: ALERT_RULE_TYPE_LABELS[item] }))} value={value.ruleType} /><Select aria-label="级别" onValueChange={(severity) => update({ severity: severity as IncidentSeverity })} options={severityValues.map((item) => ({ value: item, label: INCIDENT_SEVERITY_LABELS[item] }))} value={value.severity} /><Select aria-label="状态" onValueChange={(status) => update({ status: status as AlertRuleStatus })} options={ALERT_RULE_STATUS_VALUES.map((item) => ({ value: item, label: ALERT_RULE_STATUS_LABELS[item] }))} value={value.status} /><Textarea label="条件摘要" onChange={(event) => update({ conditionSummary: event.target.value })} value={value.conditionSummary} /><Textarea label="处理建议" onChange={(event) => update({ suggestion: event.target.value })} value={value.suggestion} /></>;
}

function TriggerForm({ dialog, rules, setDialog }: { dialog: Extract<DialogState, { kind: "trigger" }>; rules: AlertRule[]; setDialog: (dialog: DialogState) => void }): React.ReactElement {
  const value = dialog.value;
  const update = (next: Partial<AlertTriggerInput>) => setDialog({ ...dialog, value: { ...value, ...next } });
  return <><Select aria-label="关联规则" onValueChange={(ruleId) => update({ ruleId: ruleId || undefined })} options={[{ value: "", label: "不关联规则" }, ...rules.map((rule) => ({ value: rule.id, label: rule.name }))]} value={value.ruleId ?? ""} /><Input label="标题" onChange={(event) => update({ title: event.target.value })} required value={value.title} /><Textarea label="描述" onChange={(event) => update({ description: event.target.value })} value={value.description} /><Select aria-label="状态" onValueChange={(status) => update({ status: status as AlertTriggerStatus })} options={ALERT_TRIGGER_STATUS_VALUES.map((item) => ({ value: item, label: ALERT_TRIGGER_STATUS_LABELS[item] }))} value={value.status} /><Input label="来源" onChange={(event) => update({ source: event.target.value })} value={value.source} /><Textarea label="处理记录" onChange={(event) => update({ handlingNotes: event.target.value })} value={value.handlingNotes} /></>;
}

function MetricCard({ icon: Icon, label, value }: { icon: React.ComponentType<{ "aria-hidden"?: boolean; className?: string }>; label: string; value: number }): React.ReactElement {
  return <Card><CardHeader className="flex flex-row items-center justify-between p-4"><div><p className="text-sm text-muted-foreground">{label}</p><CardTitle className="mt-2 text-3xl">{value}</CardTitle></div><Icon className="size-5 text-primary" aria-hidden={true} /></CardHeader></Card>;
}

function DataTable({ children, heads, title }: { children: React.ReactNode; colSpan: number; empty: string; heads: string[]; title: string }): React.ReactElement {
  return <Card><CardHeader><CardTitle>{title}</CardTitle></CardHeader><CardContent className="overflow-x-auto"><Table className="w-full min-w-[980px] text-sm"><Table.Header className="bg-secondary text-left text-xs text-muted-foreground"><Table.Row>{heads.map((head) => <Table.Head className={head === "操作" ? "px-4 py-3 text-right" : "px-4 py-3"} key={head}>{head}</Table.Head>)}</Table.Row></Table.Header><Table.Body className="divide-y bg-card">{children}</Table.Body></Table></CardContent></Card>;
}

function EmptyRow({ colSpan, text }: { colSpan: number; text: string }): React.ReactElement {
  return <Table.Row><Table.Cell className="px-4 py-8 text-center text-muted-foreground" colSpan={colSpan}>{text}</Table.Cell></Table.Row>;
}

function RowActions({ disabled, onDelete, onEdit }: { disabled: boolean; onDelete: () => void; onEdit: () => void }): React.ReactElement {
  return <div className="flex justify-end gap-2"><Button disabled={disabled} onClick={onEdit} size="sm" type="button" variant="outline">编辑</Button><Button disabled={disabled} onClick={onDelete} size="sm" type="button" variant="outline">删除</Button></div>;
}
