"use client";

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

import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, 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 { ApiResult } from "@/modules/core/server/api";
import type { IncidentSeverity, IncidentStatus } from "@/modules/core/types";
import type { EmergencyIncident, EmergencyIncidentData } from "@/modules/emergency/types";
import { INCIDENT_SEVERITY_LABELS, INCIDENT_STATUS_LABELS } from "@/modules/emergency/types";

type EmergencyWorkspaceClientProps = {
  canManage: boolean;
  initialData: EmergencyIncidentData;
};

const emptyCreateForm = {
  severity: "warning" as IncidentSeverity,
  title: "",
  description: "",
  source: "人工上报",
};

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

function severityVariant(severity: IncidentSeverity): "danger" | "secondary" | "warning" {
  if (severity === "critical") {
    return "danger";
  }

  return severity === "warning" ? "warning" : "secondary";
}

function statusVariant(status: IncidentStatus): "success" | "secondary" | "warning" {
  if (status === "open") {
    return "warning";
  }

  return status === "resolved" || status === "closed" ? "success" : "secondary";
}

export function EmergencyWorkspaceClient({ canManage, initialData }: EmergencyWorkspaceClientProps): React.ReactElement {
  const [data, setData] = useState(initialData);
  const [query, setQuery] = useState("");
  const [statusFilter, setStatusFilter] = useState<"all" | IncidentStatus>("all");
  const [severityFilter, setSeverityFilter] = useState<"all" | IncidentSeverity>("all");
  const [message, setMessage] = useState("");
  const [isPending, setIsPending] = useState(false);
  const [isCreateOpen, setIsCreateOpen] = useState(false);
  const [createForm, setCreateForm] = useState(emptyCreateForm);

  const normalizedQuery = query.trim().toLowerCase();
  const filteredIncidents = useMemo(
    () =>
      data.incidents.filter((incident) => {
        const matchesQuery =
          !normalizedQuery ||
          [incident.title, incident.description, incident.source].join(" ").toLowerCase().includes(normalizedQuery);
        const matchesStatus = statusFilter === "all" || incident.status === statusFilter;
        const matchesSeverity = severityFilter === "all" || incident.severity === severityFilter;
        return matchesQuery && matchesStatus && matchesSeverity;
      }),
    [data.incidents, normalizedQuery, severityFilter, statusFilter],
  );

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

  async function createIncident(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    if (!canManage) {
      setMessage("当前角色无权创建应急事件");
      return;
    }

    setIsPending(true);
    setMessage("");
    const response = await fetch("/api/emergency/incidents", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(createForm),
    });
    const result = (await response.json()) as ApiResult<{ incident: EmergencyIncident }>;
    setIsPending(false);
    setMessage(result.reason);

    if (result.success) {
      setIsCreateOpen(false);
      setCreateForm(emptyCreateForm);
      await refreshData();
    }
  }

  async function updateStatus(incident: EmergencyIncident, status: IncidentStatus): Promise<void> {
    if (!canManage) {
      setMessage("当前角色无权处理应急事件");
      return;
    }

    setIsPending(true);
    setMessage("");
    const response = await fetch(`/api/emergency/incidents/${incident.id}`, {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ status }),
    });
    const result = (await response.json()) as ApiResult<{ incident: EmergencyIncident }>;
    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={CircleAlert} label="待处理" value={data.metrics.open} />
        <MetricCard icon={ShieldAlert} label="已确认" value={data.metrics.acknowledged} />
        <MetricCard icon={Siren} label="紧急事件" value={data.metrics.critical} />
        <MetricCard icon={CheckCircle2} label="今日解决" value={data.metrics.resolvedToday} />
      </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) => setStatusFilter(value as "all" | IncidentStatus)}
            options={[
              { value: "all", label: "全部状态" },
              ...Object.entries(INCIDENT_STATUS_LABELS).map(([value, label]) => ({ value, label })),
            ]}
            value={statusFilter}
          />
          <Select
            aria-label="事件级别"
            onValueChange={(value) => setSeverityFilter(value as "all" | IncidentSeverity)}
            options={[
              { value: "all", label: "全部级别" },
              ...Object.entries(INCIDENT_SEVERITY_LABELS).map(([value, label]) => ({ value, label })),
            ]}
            value={severityFilter}
          />
          <Button disabled={!canManage} onClick={() => setIsCreateOpen(true)} type="button">
            新建事件
          </Button>
        </div>
      </section>

      {message ? (
        <p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
          {message}
        </p>
      ) : null}

      <Card>
        <CardHeader>
          <CardTitle>应急事件</CardTitle>
          <CardDescription>状态处理会记录确认人、解决人和审计日志。</CardDescription>
        </CardHeader>
        <CardContent className="overflow-x-auto">
          <Table className="w-full min-w-[960px] text-sm">
            <Table.Header className="bg-secondary text-left text-xs text-muted-foreground">
              <Table.Row>
                <Table.Head className="px-4 py-3 font-medium">事件</Table.Head>
                <Table.Head className="px-4 py-3 font-medium">级别</Table.Head>
                <Table.Head className="px-4 py-3 font-medium">状态</Table.Head>
                <Table.Head className="px-4 py-3 font-medium">来源</Table.Head>
                <Table.Head className="px-4 py-3 font-medium">确认/解决</Table.Head>
                <Table.Head className="px-4 py-3 font-medium">更新时间</Table.Head>
                <Table.Head className="px-4 py-3 text-right font-medium">操作</Table.Head>
              </Table.Row>
            </Table.Header>
            <Table.Body className="divide-y bg-card">
              {filteredIncidents.map((incident) => (
                <Table.Row key={incident.id}>
                  <Table.Cell className="px-4 py-3">
                    <p className="font-medium">{incident.title}</p>
                    <p className="text-xs text-muted-foreground">{incident.description}</p>
                  </Table.Cell>
                  <Table.Cell className="px-4 py-3">
                    <Badge variant={severityVariant(incident.severity)}>{INCIDENT_SEVERITY_LABELS[incident.severity]}</Badge>
                  </Table.Cell>
                  <Table.Cell className="px-4 py-3">
                    <Badge variant={statusVariant(incident.status)}>{INCIDENT_STATUS_LABELS[incident.status]}</Badge>
                  </Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">{incident.source}</Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">
                    {incident.resolvedByName ?? incident.acknowledgedByName ?? "-"}
                  </Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">{formatDateTime(incident.updatedAt)}</Table.Cell>
                  <Table.Cell className="px-4 py-3">
                    <div className="flex justify-end gap-2">
                      {incident.status === "open" ? (
                        <Button disabled={!canManage || isPending} onClick={() => updateStatus(incident, "acknowledged")} size="sm" type="button" variant="outline">
                          确认
                        </Button>
                      ) : null}
                      {incident.status === "open" || incident.status === "acknowledged" ? (
                        <Button disabled={!canManage || isPending} onClick={() => updateStatus(incident, "resolved")} size="sm" type="button">
                          解决
                        </Button>
                      ) : null}
                      {incident.status === "resolved" ? (
                        <Button disabled={!canManage || isPending} onClick={() => updateStatus(incident, "closed")} size="sm" type="button" variant="outline">
                          关闭
                        </Button>
                      ) : null}
                    </div>
                  </Table.Cell>
                </Table.Row>
              ))}
              {filteredIncidents.length === 0 ? (
                <Table.Row>
                  <Table.Cell className="px-4 py-8 text-center text-muted-foreground" colSpan={7}>
                    暂无应急事件
                  </Table.Cell>
                </Table.Row>
              ) : null}
            </Table.Body>
          </Table>
        </CardContent>
      </Card>

      <Dialog className="max-w-xl" description="手工登记安全、应急或巡检异常事件。" onClose={() => setIsCreateOpen(false)} open={isCreateOpen} title="新建应急事件">
        <form className="grid gap-3" onSubmit={createIncident}>
          <Input label="事件标题" onChange={(event) => setCreateForm((current) => ({ ...current, title: event.target.value }))} required value={createForm.title} />
          <Select
            label="事件级别"
            onValueChange={(value) => setCreateForm((current) => ({ ...current, severity: value as IncidentSeverity }))}
            options={Object.entries(INCIDENT_SEVERITY_LABELS).map(([value, label]) => ({ value, label }))}
            value={createForm.severity}
          />
          <Input label="来源" onChange={(event) => setCreateForm((current) => ({ ...current, source: event.target.value }))} value={createForm.source} />
          <Textarea
            label="事件描述"
            onChange={(event) => setCreateForm((current) => ({ ...current, description: event.target.value }))}
            required
            value={createForm.description}
          />
          <div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
            <Button disabled={isPending} onClick={() => setIsCreateOpen(false)} type="button" variant="outline">
              取消
            </Button>
            <Button disabled={isPending} type="submit">
              创建事件
            </Button>
          </div>
        </form>
      </Dialog>
    </div>
  );
}

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>
          <CardDescription>{label}</CardDescription>
          <CardTitle className="mt-2 text-3xl">{value}</CardTitle>
        </div>
        <Icon className="size-5 text-primary" aria-hidden={true} />
      </CardHeader>
    </Card>
  );
}
