"use client";

import { FormEvent, useMemo, useState } from "react";
import { Edit3, Filter, Plus, Search, Trash2 } 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 { Permission } from "@/modules/core/types";
import type { CareLevel, Elder, ElderInput, ElderStatus } from "@/modules/elders/types";
import { CARE_LEVEL_LABELS, ELDER_STATUS_LABELS, GENDER_LABELS } from "@/modules/elders/types";

type EldersClientProps = {
  initialElders: Elder[];
  permissions: Permission[];
};

const emptyInput: ElderInput = {
  name: "",
  gender: "male",
  age: 75,
  careLevel: "self-care",
  room: "",
  bed: "",
  status: "active",
  primaryContact: "",
  phone: "",
  medicalNotes: "",
};

const PAGE_SIZE = 8;
const ALL_STATUS = "all";
const ALL_CARE_LEVELS = "all";

function elderToInput(elder: Elder): ElderInput {
  return {
    name: elder.name,
    gender: elder.gender,
    age: elder.age,
    careLevel: elder.careLevel,
    room: elder.room,
    bed: elder.bed,
    status: elder.status,
    primaryContact: elder.primaryContact,
    phone: elder.phone,
    medicalNotes: elder.medicalNotes,
  };
}

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

function formatBedLabel(elder: Pick<Elder, "room" | "bed">): string {
  return elder.room && elder.bed ? `${elder.room}-${elder.bed}` : "-";
}

function getRiskLabel(elder: Elder): { label: string; variant: "danger" | "warning" | "success" } {
  if (elder.careLevel === "intensive") {
    return { label: "红色重点", variant: "danger" };
  }

  if (elder.status === "pending" || elder.careLevel === "assisted") {
    return { label: "黄色关注", variant: "warning" };
  }

  return { label: "绿色稳定", variant: "success" };
}

const statusOptions = [
  { value: ALL_STATUS, label: "全部状态" },
  ...Object.entries(ELDER_STATUS_LABELS).map(([value, label]) => ({ value, label })),
];

const careLevelOptions = [
  { value: ALL_CARE_LEVELS, label: "全部照护" },
  ...Object.entries(CARE_LEVEL_LABELS).map(([value, label]) => ({ value, label })),
];

const genderOptions = Object.entries(GENDER_LABELS).map(([value, label]) => ({ value, label }));
const formCareLevelOptions = Object.entries(CARE_LEVEL_LABELS).map(([value, label]) => ({ value, label }));
const formStatusOptions = Object.entries(ELDER_STATUS_LABELS).map(([value, label]) => ({ value, label }));

function matchesFilters(
  elder: Elder,
  query: string,
  statusFilter: ElderStatus | typeof ALL_STATUS,
  careLevelFilter: CareLevel | typeof ALL_CARE_LEVELS,
): boolean {
  const normalizedQuery = query.trim().toLowerCase();
  const matchesSearch =
    normalizedQuery.length === 0 ||
    [elder.name, elder.room, elder.bed, elder.primaryContact, elder.phone, elder.medicalNotes]
      .join(" ")
      .toLowerCase()
      .includes(normalizedQuery);
  const matchesStatus = statusFilter === ALL_STATUS || elder.status === statusFilter;
  const matchesCareLevel = careLevelFilter === ALL_CARE_LEVELS || elder.careLevel === careLevelFilter;

  return matchesSearch && matchesStatus && matchesCareLevel;
}

export function EldersClient({ initialElders, permissions }: EldersClientProps): React.ReactElement {
  const [elders, setElders] = useState(initialElders);
  const [editingId, setEditingId] = useState<string | null>(null);
  const [form, setForm] = useState<ElderInput>(emptyInput);
  const [message, setMessage] = useState("");
  const [isPending, setIsPending] = useState(false);
  const [isFormOpen, setIsFormOpen] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<Elder | null>(null);
  const [query, setQuery] = useState("");
  const [statusFilter, setStatusFilter] = useState<ElderStatus | typeof ALL_STATUS>(ALL_STATUS);
  const [careLevelFilter, setCareLevelFilter] = useState<CareLevel | typeof ALL_CARE_LEVELS>(ALL_CARE_LEVELS);
  const [page, setPage] = useState(1);

  const canCreate = permissions.includes("elder:create");
  const canUpdate = permissions.includes("elder:update");
  const canDelete = permissions.includes("elder:delete");
  const isEditing = editingId !== null;
  const canSubmit = isEditing ? canUpdate : canCreate;

  const metrics = useMemo(() => {
    const activeCount = elders.filter((elder) => elder.status === "active").length;
    const pendingCount = elders.filter((elder) => elder.status === "pending").length;
    const intensiveCount = elders.filter((elder) => elder.careLevel === "intensive").length;
    const warningCount = elders.filter((elder) => getRiskLabel(elder).variant !== "success").length;
    return { activeCount, pendingCount, intensiveCount, warningCount };
  }, [elders]);

  const filteredElders = useMemo(
    () => elders.filter((elder) => matchesFilters(elder, query, statusFilter, careLevelFilter)),
    [careLevelFilter, elders, query, statusFilter],
  );
  const pageCount = Math.max(1, Math.ceil(filteredElders.length / PAGE_SIZE));
  const safePage = Math.min(page, pageCount);
  const pageStart = (safePage - 1) * PAGE_SIZE;
  const visibleElders = filteredElders.slice(pageStart, pageStart + PAGE_SIZE);
  const editingElder = editingId ? elders.find((elder) => elder.id === editingId) : undefined;

  function updateField<K extends keyof ElderInput>(key: K, value: ElderInput[K]): void {
    setForm((current) => ({ ...current, [key]: value }));
  }

  function beginCreate(): void {
    setEditingId(null);
    setForm(emptyInput);
    setMessage("");
    setIsFormOpen(true);
  }

  function beginEdit(elder: Elder): void {
    setEditingId(elder.id);
    setForm(elderToInput(elder));
    setMessage("");
    setIsFormOpen(true);
  }

  function closeForm(): void {
    if (isPending) {
      return;
    }

    setIsFormOpen(false);
    setEditingId(null);
    setForm(emptyInput);
  }

  function updateQuery(value: string): void {
    setQuery(value);
    setPage(1);
  }

  function updateStatusFilter(value: string): void {
    setStatusFilter(value as ElderStatus | typeof ALL_STATUS);
    setPage(1);
  }

  function updateCareLevelFilter(value: string): void {
    setCareLevelFilter(value as CareLevel | typeof ALL_CARE_LEVELS);
    setPage(1);
  }

  async function refreshElders(): Promise<void> {
    const response = await fetch("/api/elders");
    const result = (await response.json()) as ApiResult<{ elders: Elder[] }>;
    if (result.success) {
      setElders(result.elders);
    }
  }

  async function handleSubmit(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    if (!canSubmit) {
      setMessage("当前角色无权保存老人档案");
      return;
    }

    setIsPending(true);
    setMessage("");

    const response = await fetch(isEditing ? `/api/elders/${editingId}` : "/api/elders", {
      method: isEditing ? "PATCH" : "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(form),
    });
    const result = (await response.json()) as ApiResult<{ elder: Elder }>;
    setIsPending(false);

    if (!result.success) {
      setMessage(result.reason);
      return;
    }

    await refreshElders();
    setEditingId(null);
    setForm(emptyInput);
    setIsFormOpen(false);
    setMessage(result.reason);
  }

  async function handleDelete(): Promise<void> {
    if (!deleteTarget) {
      return;
    }

    if (!canDelete) {
      setMessage("当前角色无权删除老人档案");
      return;
    }

    setIsPending(true);
    setMessage("");

    const response = await fetch(`/api/elders/${deleteTarget.id}`, { method: "DELETE" });
    const result = (await response.json()) as ApiResult<{ elder: Elder }>;
    setIsPending(false);

    if (!result.success) {
      setMessage(result.reason);
      return;
    }

    await refreshElders();
    setDeleteTarget(null);
    setMessage(result.reason);
  }

  return (
    <div className="mx-auto flex w-full max-w-7xl flex-col gap-5">
      <section className="flex flex-col gap-4 border-b pb-5 lg:flex-row lg:items-end lg:justify-between">
        <div>
          <Badge variant="success">全栈 CRUD</Badge>
          <h1 className="mt-3 text-3xl font-semibold tracking-normal">老人档案</h1>
          <p className="mt-2 text-sm text-muted-foreground">列表管理、筛选搜索、分页、弹窗维护和审计持久化。</p>
        </div>
        <div className="flex flex-wrap gap-2">
          <Button disabled={!canCreate} onClick={beginCreate} type="button">
            <Plus className="size-4" aria-hidden="true" />
            新增老人
          </Button>
        </div>
      </section>

      <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
        <Card>
          <CardHeader className="p-4">
            <CardDescription>在院老人</CardDescription>
            <CardTitle className="text-3xl">{metrics.activeCount}</CardTitle>
          </CardHeader>
        </Card>
        <Card>
          <CardHeader className="p-4">
            <CardDescription>待入住</CardDescription>
            <CardTitle className="text-3xl">{metrics.pendingCount}</CardTitle>
          </CardHeader>
        </Card>
        <Card className="border-red-200 bg-red-50/70">
          <CardHeader className="p-4">
            <CardDescription className="text-red-700">红色重点</CardDescription>
            <CardTitle className="text-3xl text-red-700">{metrics.intensiveCount}</CardTitle>
          </CardHeader>
        </Card>
        <Card>
          <CardHeader className="p-4">
            <CardDescription>需关注标记</CardDescription>
            <CardTitle className="text-3xl">{metrics.warningCount}</CardTitle>
          </CardHeader>
        </Card>
      </section>

      <Card>
        <CardHeader className="gap-4">
          <div className="flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between">
            <div>
              <CardTitle>档案列表</CardTitle>
              <CardDescription className="mt-1">
                共 {filteredElders.length} 条匹配记录，按状态、照护等级和关键词快速定位。
              </CardDescription>
            </div>
            <div className="grid gap-2 sm:grid-cols-[minmax(220px,1fr)_150px_150px]">
              <label className="relative block">
                <Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
                <Input
                  className="pl-9"
                  onChange={(event) => updateQuery(event.target.value)}
                  placeholder="搜索姓名、床位、联系人"
                  value={query}
                />
              </label>
              <div className="relative block">
                <Filter className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
                <Select
                  aria-label="按老人状态筛选"
                  className="w-full pl-9"
                  onValueChange={updateStatusFilter}
                  options={statusOptions}
                  value={statusFilter}
                />
              </div>
              <Select
                aria-label="按照护等级筛选"
                className="w-full"
                onValueChange={updateCareLevelFilter}
                options={careLevelOptions}
                value={careLevelFilter}
              />
            </div>
          </div>
          {message ? (
            <p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
              {message}
            </p>
          ) : null}
        </CardHeader>
        <CardContent>
          <div className="overflow-x-auto rounded-md border">
            <Table className="w-full min-w-[980px] 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">
                {visibleElders.map((elder) => {
                  const risk = getRiskLabel(elder);

                  return (
                    <Table.Row key={elder.id}>
                      <Table.Cell className="px-4 py-3">
                        <p className="font-medium">{elder.name}</p>
                        <p className="text-xs text-muted-foreground">
                          {GENDER_LABELS[elder.gender]} · {elder.age} 岁
                        </p>
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3">{CARE_LEVEL_LABELS[elder.careLevel]}</Table.Cell>
                      <Table.Cell className="px-4 py-3 text-muted-foreground">{formatBedLabel(elder)}</Table.Cell>
                      <Table.Cell className="px-4 py-3 text-muted-foreground">
                        {elder.primaryContact} / {elder.phone}
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3">
                        <Badge variant={elder.status === "active" ? "success" : "secondary"}>
                          {ELDER_STATUS_LABELS[elder.status]}
                        </Badge>
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3">
                        <Badge variant={risk.variant}>{risk.label}</Badge>
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3">
                        <div className="flex justify-end gap-2">
                          <Button
                            disabled={!canUpdate}
                            onClick={() => beginEdit(elder)}
                            size="sm"
                            type="button"
                            variant="outline"
                          >
                            <Edit3 className="size-4" aria-hidden="true" />
                            编辑
                          </Button>
                          <Button
                            disabled={!canDelete || isPending}
                            onClick={() => setDeleteTarget(elder)}
                            size="sm"
                            type="button"
                            variant="destructive"
                          >
                            <Trash2 className="size-4" aria-hidden="true" />
                            删除
                          </Button>
                        </div>
                      </Table.Cell>
                    </Table.Row>
                  );
                })}
                {visibleElders.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>
          </div>
          <div className="mt-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
            <p className="text-sm text-muted-foreground">
              第 {safePage} / {pageCount} 页
            </p>
            <div className="flex gap-2">
              <Button
                disabled={safePage === 1}
                onClick={() => setPage((current) => Math.max(1, current - 1))}
                size="sm"
                type="button"
                variant="outline"
              >
                上一页
              </Button>
              <Button
                disabled={safePage === pageCount}
                onClick={() => setPage((current) => Math.min(pageCount, current + 1))}
                size="sm"
                type="button"
                variant="outline"
              >
                下一页
              </Button>
            </div>
          </div>
        </CardContent>
      </Card>

      <Dialog
        description="保存后会写入 PostgreSQL，并生成审计记录。"
        onClose={closeForm}
        open={isFormOpen}
        title={isEditing ? "编辑老人档案" : "新增老人档案"}
      >
        <form className="grid gap-3" id="elder-form" onSubmit={handleSubmit}>
          <label className="grid gap-1.5 text-sm font-medium">
            姓名
            <Input value={form.name} onChange={(event) => updateField("name", event.target.value)} />
          </label>
          <div className="grid gap-3 sm:grid-cols-2">
            <div className="grid gap-1.5 text-sm font-medium">
              性别
              <Select
                aria-label="性别"
                onValueChange={(value) => updateField("gender", value as ElderInput["gender"])}
                options={genderOptions}
                value={form.gender}
              />
            </div>
            <label className="grid gap-1.5 text-sm font-medium">
              年龄
              <Input
                max={130}
                min={0}
                onChange={(event) => updateField("age", Number(event.target.value))}
                type="number"
                value={form.age}
              />
            </label>
          </div>
          <div className="grid gap-3 sm:grid-cols-2">
            <div className="grid gap-1.5 text-sm font-medium">
              护理等级
              <Select
                aria-label="护理等级"
                onValueChange={(value) => updateField("careLevel", value as ElderInput["careLevel"])}
                options={formCareLevelOptions}
                value={form.careLevel}
              />
            </div>
            <div className="grid gap-1.5 text-sm font-medium">
              状态
              <Select
                aria-label="状态"
                onValueChange={(value) => updateField("status", value as ElderInput["status"])}
                options={formStatusOptions}
                value={form.status}
              />
            </div>
          </div>
          {isEditing ? (
            <div className="rounded-md border bg-secondary/30 px-3 py-2 text-sm">
              当前床位：{editingElder ? formatBedLabel(editingElder) : "-"}
            </div>
          ) : null}
          <label className="grid gap-1.5 text-sm font-medium">
            联系人
            <Input value={form.primaryContact} onChange={(event) => updateField("primaryContact", event.target.value)} />
          </label>
          <label className="grid gap-1.5 text-sm font-medium">
            联系电话
            <Input value={form.phone} onChange={(event) => updateField("phone", event.target.value)} />
          </label>
          <label className="grid gap-1.5 text-sm font-medium">
            健康备注
            <Textarea
              className="min-h-24"
              onChange={(event) => updateField("medicalNotes", event.target.value)}
              value={form.medicalNotes}
            />
          </label>
          {message ? (
            <p className="rounded-md bg-secondary px-3 py-2 text-sm text-secondary-foreground" role="status">
              {message}
            </p>
          ) : null}
          <div className="flex flex-col-reverse gap-2 pt-2 sm:flex-row sm:justify-end">
            <Button disabled={isPending} onClick={closeForm} type="button" variant="outline">
              取消
            </Button>
            <Button disabled={isPending || !canSubmit} type="submit">
              <Plus className="size-4" aria-hidden="true" />
              {isEditing ? "保存修改" : "新增老人"}
            </Button>
          </div>
        </form>
      </Dialog>

      <Dialog
        className="max-w-md"
        description={deleteTarget ? `确认删除 ${deleteTarget.name} 的档案？该操作会写入审计日志。` : undefined}
        onClose={() => setDeleteTarget(null)}
        open={deleteTarget !== null}
        title="删除确认"
      >
        <div className="flex flex-col gap-4">
          {deleteTarget ? (
            <div className="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-700">
              {deleteTarget.name}，{formatBedLabel(deleteTarget)}，最近更新：
              {formatDateTime(deleteTarget.updatedAt)}
            </div>
          ) : null}
          <div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
            <Button disabled={isPending} onClick={() => setDeleteTarget(null)} type="button" variant="outline">
              取消
            </Button>
            <Button disabled={isPending || !canDelete} onClick={() => void handleDelete()} type="button" variant="destructive">
              删除档案
            </Button>
          </div>
        </div>
      </Dialog>
    </div>
  );
}
