"use client";

import { FormEvent, useMemo, useState } from "react";
import { BedDouble, DoorOpen, History, MoveRight, UserCheck, UserMinus, Wrench } 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 { Textarea } from "@/components/ui/input";
import { Select, type SelectOption } from "@/components/ui/select";
import { Table } from "@/components/ui/table";
import type { ApiResult } from "@/modules/core/server/api";
import type { Admission, BedStatus, FacilityBed, Permission, Room } from "@/modules/core/types";
import type { Elder } from "@/modules/elders/types";
import type { BedOperationalContext, OperationalContextLine } from "@/modules/operations/types";

type BedsWorkspaceProps = {
  bedContexts?: Record<string, BedOperationalContext>;
  initialRooms: Room[];
  initialBeds: FacilityBed[];
  initialAdmissions: Admission[];
  initialElders: Elder[];
  permissions: Permission[];
};

type WorkspaceTab = "overview" | "operations" | "history";

const workspaceTabs: Array<{ value: WorkspaceTab; label: string }> = [
  { value: "overview", label: "概览" },
  { value: "operations", label: "办理" },
  { value: "history", label: "记录" },
];

const bedStatusLabels: Record<BedStatus, string> = {
  available: "空闲",
  occupied: "占用",
  maintenance: "维修",
  disabled: "停用",
};

const admissionStatusLabels: Record<Admission["status"], string> = {
  active: "在住",
  transferred: "已换床",
  discharged: "已退住",
};

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

function bedBadgeVariant(status: BedStatus): "success" | "secondary" | "warning" | "danger" {
  switch (status) {
    case "available":
      return "success";
    case "occupied":
      return "secondary";
    case "maintenance":
      return "warning";
    case "disabled":
      return "danger";
  }
}

function admissionBedLabel(admission: Admission): string {
  return `${admission.roomName}-${admission.bedCode}`;
}

function makeSelectOptions(items: Array<{ id: string; label: string }>, emptyLabel: string): SelectOption[] {
  return [
    { value: "", label: emptyLabel, disabled: true },
    ...items.map((item) => ({ value: item.id, label: item.label })),
  ];
}

export function BedsWorkspace({
  bedContexts = {},
  initialRooms,
  initialBeds,
  initialAdmissions,
  initialElders,
  permissions,
}: BedsWorkspaceProps): React.ReactElement {
  const [rooms, setRooms] = useState(initialRooms);
  const [beds, setBeds] = useState(initialBeds);
  const [admissions, setAdmissions] = useState(initialAdmissions);
  const [elders, setElders] = useState(initialElders);
  const [activeTab, setActiveTab] = useState<WorkspaceTab>("overview");
  const [message, setMessage] = useState("");
  const [isPending, setIsPending] = useState(false);
  const [admitElderId, setAdmitElderId] = useState("");
  const [admitBedId, setAdmitBedId] = useState("");
  const [admitNotes, setAdmitNotes] = useState("");
  const [transferAdmissionId, setTransferAdmissionId] = useState("");
  const [transferBedId, setTransferBedId] = useState("");
  const [transferNotes, setTransferNotes] = useState("");
  const [dischargeAdmissionId, setDischargeAdmissionId] = useState("");
  const [dischargeNotes, setDischargeNotes] = useState("");

  const canManageAdmissions = permissions.includes("admission:manage");
  const activeAdmissions = useMemo(() => admissions.filter((admission) => admission.status === "active"), [admissions]);
  const activeElderIds = useMemo(() => new Set(activeAdmissions.map((admission) => admission.elderId)), [activeAdmissions]);
  const availableBeds = useMemo(() => beds.filter((bed) => bed.status === "available"), [beds]);
  const occupiedBeds = beds.filter((bed) => bed.status === "occupied").length;
  const maintenanceBeds = beds.filter((bed) => bed.status === "maintenance").length;
  const occupancyRate = beds.length > 0 ? Math.round((occupiedBeds / beds.length) * 100) : 0;
  const admissionEligibleElders = elders.filter((elder) => !activeElderIds.has(elder.id));

  const elderOptions = makeSelectOptions(
    admissionEligibleElders.map((elder) => ({ id: elder.id, label: `${elder.name} / ${elder.phone}` })),
    "选择老人",
  );
  const bedOptions = makeSelectOptions(
    availableBeds.map((bed) => ({ id: bed.id, label: `${bed.roomName}-${bed.code}` })),
    "选择空闲床位",
  );
  const activeAdmissionOptions = makeSelectOptions(
    activeAdmissions.map((admission) => ({
      id: admission.id,
      label: `${admission.elderName} / ${admissionBedLabel(admission)}`,
    })),
    "选择在住记录",
  );

  async function refreshData(): Promise<void> {
    const [eldersResponse, roomsResponse, bedsResponse, admissionsResponse] = await Promise.all([
      fetch("/api/elders"),
      fetch("/api/facilities/rooms"),
      fetch("/api/facilities/beds"),
      fetch("/api/admissions"),
    ]);
    const [eldersResult, roomsResult, bedsResult, admissionsResult] = (await Promise.all([
      eldersResponse.json(),
      roomsResponse.json(),
      bedsResponse.json(),
      admissionsResponse.json(),
    ])) as [
      ApiResult<{ elders: Elder[] }>,
      ApiResult<{ rooms: Room[] }>,
      ApiResult<{ beds: FacilityBed[] }>,
      ApiResult<{ admissions: Admission[] }>,
    ];

    if (eldersResult.success) {
      setElders(eldersResult.elders);
    }
    if (roomsResult.success) {
      setRooms(roomsResult.rooms);
    }
    if (bedsResult.success) {
      setBeds(bedsResult.beds);
    }
    if (admissionsResult.success) {
      setAdmissions(admissionsResult.admissions);
    }
  }

  async function submitAdmission(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    if (!canManageAdmissions) {
      setMessage("当前角色无权办理入住");
      return;
    }
    if (!admitElderId || !admitBedId) {
      setMessage("请选择老人和空闲床位");
      return;
    }

    setIsPending(true);
    setMessage("");
    const response = await fetch("/api/admissions", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ elderId: admitElderId, bedId: admitBedId, notes: admitNotes }),
    });
    const result = (await response.json()) as ApiResult<{ admission: Admission }>;
    setIsPending(false);

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

    setAdmitElderId("");
    setAdmitBedId("");
    setAdmitNotes("");
    await refreshData();
    setMessage(result.reason);
  }

  async function submitTransfer(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    const admission = activeAdmissions.find((item) => item.id === transferAdmissionId);
    if (!canManageAdmissions) {
      setMessage("当前角色无权办理换床");
      return;
    }
    if (!admission || !transferBedId) {
      setMessage("请选择在住记录和新床位");
      return;
    }

    setIsPending(true);
    setMessage("");
    const response = await fetch("/api/admissions", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ elderId: admission.elderId, bedId: transferBedId, notes: transferNotes || "办理换床" }),
    });
    const result = (await response.json()) as ApiResult<{ admission: Admission }>;
    setIsPending(false);

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

    setTransferAdmissionId("");
    setTransferBedId("");
    setTransferNotes("");
    await refreshData();
    setMessage("换床已办理");
  }

  async function submitDischarge(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    if (!canManageAdmissions) {
      setMessage("当前角色无权办理退住");
      return;
    }
    if (!dischargeAdmissionId) {
      setMessage("请选择在住记录");
      return;
    }

    setIsPending(true);
    setMessage("");
    const response = await fetch(`/api/admissions/${dischargeAdmissionId}`, {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ notes: dischargeNotes }),
    });
    const result = (await response.json()) as ApiResult<{ admission: Admission }>;
    setIsPending(false);

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

    setDischargeAdmissionId("");
    setDischargeNotes("");
    await refreshData();
    setMessage(result.reason);
  }

  return (
    <div className="mx-auto flex w-full max-w-7xl flex-col gap-5">
      <section className="flex border-b pb-4">
        <div className="flex flex-wrap gap-2" role="tablist" aria-label="床位工作区">
          {workspaceTabs.map((tab) => (
            <Button
              aria-selected={activeTab === tab.value}
              key={tab.value}
              onClick={() => setActiveTab(tab.value)}
              role="tab"
              type="button"
              variant={activeTab === tab.value ? "default" : "outline"}
            >
              {tab.label}
            </Button>
          ))}
        </div>
      </section>

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

      {activeTab === "overview" ? (
        <>
          <section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
            <Card>
              <CardHeader className="flex flex-row items-center justify-between space-y-0">
                <div>
                  <CardDescription>房间</CardDescription>
                  <CardTitle className="mt-2 text-3xl">{rooms.length}</CardTitle>
                </div>
                <DoorOpen className="size-5 text-primary" aria-hidden="true" />
              </CardHeader>
            </Card>
            <Card>
              <CardHeader className="flex flex-row items-center justify-between space-y-0">
                <div>
                  <CardDescription>床位</CardDescription>
                  <CardTitle className="mt-2 text-3xl">{beds.length}</CardTitle>
                </div>
                <BedDouble className="size-5 text-primary" aria-hidden="true" />
              </CardHeader>
              <CardContent className="pt-0">
                <p className="text-sm text-muted-foreground">占用率 {occupancyRate}%</p>
              </CardContent>
            </Card>
            <Card className={maintenanceBeds > 0 ? "border-amber-200 bg-amber-50/70" : undefined}>
              <CardHeader className="flex flex-row items-center justify-between space-y-0">
                <div>
                  <CardDescription className={maintenanceBeds > 0 ? "text-amber-700" : undefined}>维修床位</CardDescription>
                  <CardTitle className={maintenanceBeds > 0 ? "mt-2 text-3xl text-amber-700" : "mt-2 text-3xl"}>
                    {maintenanceBeds}
                  </CardTitle>
                </div>
                <Wrench className={maintenanceBeds > 0 ? "size-5 text-amber-700" : "size-5 text-primary"} aria-hidden="true" />
              </CardHeader>
            </Card>
            <Card>
              <CardHeader className="flex flex-row items-center justify-between space-y-0">
                <div>
                  <CardDescription>在住</CardDescription>
                  <CardTitle className="mt-2 text-3xl">{activeAdmissions.length}</CardTitle>
                </div>
                <History className="size-5 text-primary" aria-hidden="true" />
              </CardHeader>
            </Card>
          </section>

          <section className="grid gap-4 xl:grid-cols-[0.9fr_1.1fr]">
            <Card>
              <CardHeader>
                <CardTitle>房间台账</CardTitle>
              </CardHeader>
              <CardContent>
                <div className="overflow-x-auto rounded-md border">
                  <Table className="w-full min-w-[620px] 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.Row>
                    </Table.Header>
                    <Table.Body className="divide-y bg-card">
                      {rooms.map((room) => (
                        <Table.Row key={room.id}>
                          <Table.Cell className="px-4 py-3 font-medium">{room.name}</Table.Cell>
                          <Table.Cell className="px-4 py-3 text-muted-foreground">{room.code}</Table.Cell>
                          <Table.Cell className="px-4 py-3">{room.capacity}</Table.Cell>
                          <Table.Cell className="px-4 py-3">
                            {room.occupiedBedCount}/{room.bedCount}
                          </Table.Cell>
                          <Table.Cell className="px-4 py-3">
                            <Badge variant={room.status === "active" ? "success" : "danger"}>{room.status}</Badge>
                          </Table.Cell>
                        </Table.Row>
                      ))}
                      {rooms.length === 0 ? (
                        <Table.Row>
                          <Table.Cell className="px-4 py-8 text-center text-muted-foreground" colSpan={5}>
                            暂无房间主数据
                          </Table.Cell>
                        </Table.Row>
                      ) : null}
                    </Table.Body>
                  </Table>
                </div>
              </CardContent>
            </Card>

            <Card>
              <CardHeader>
                <CardTitle>床位状态</CardTitle>
              </CardHeader>
              <CardContent>
                <div className="overflow-x-auto rounded-md border">
                  <Table className="w-full min-w-[700px] 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.Row>
                    </Table.Header>
                    <Table.Body className="divide-y bg-card">
                      {beds.map((bed) => {
                        const context = bedContexts[bed.id];
                        return (
                          <Table.Row key={bed.id}>
                            <Table.Cell className="px-4 py-3">{bed.roomName}</Table.Cell>
                            <Table.Cell className="px-4 py-3 font-medium">{bed.code}</Table.Cell>
                            <Table.Cell className="px-4 py-3">
                              <Badge variant={bedBadgeVariant(bed.status)}>{bedStatusLabels[bed.status]}</Badge>
                            </Table.Cell>
                            <Table.Cell className="px-4 py-3">
                              <OccupantSummary context={context} fallbackName={bed.currentElderName} />
                            </Table.Cell>
                            <Table.Cell className="px-4 py-3">
                              <ContextLines lines={context?.lines ?? []} />
                            </Table.Cell>
                            <Table.Cell className="px-4 py-3 text-muted-foreground">{bed.notes || "-"}</Table.Cell>
                          </Table.Row>
                        );
                      })}
                      {beds.length === 0 ? (
                        <Table.Row>
                          <Table.Cell className="px-4 py-8 text-center text-muted-foreground" colSpan={6}>
                            暂无床位主数据
                          </Table.Cell>
                        </Table.Row>
                      ) : null}
                    </Table.Body>
                  </Table>
                </div>
              </CardContent>
            </Card>
          </section>
        </>
      ) : null}

      {activeTab === "operations" ? (
        <section className="grid gap-4 xl:grid-cols-3">
          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <UserCheck className="size-5 text-primary" aria-hidden="true" />
                办理入住
              </CardTitle>
              <CardDescription>选择未在住老人和空闲床位。</CardDescription>
            </CardHeader>
            <CardContent>
              <form className="grid gap-3" onSubmit={(event) => void submitAdmission(event)}>
                <Select
                  aria-label="入住老人"
                  disabled={!canManageAdmissions || isPending}
                  onValueChange={setAdmitElderId}
                  options={elderOptions}
                  value={admitElderId}
                />
                <Select
                  aria-label="入住房间床位"
                  disabled={!canManageAdmissions || isPending}
                  onValueChange={setAdmitBedId}
                  options={bedOptions}
                  value={admitBedId}
                />
                <Textarea
                  aria-label="入住备注"
                  disabled={!canManageAdmissions || isPending}
                  onChange={(event) => setAdmitNotes(event.target.value)}
                  placeholder="备注"
                  value={admitNotes}
                />
                <Button disabled={!canManageAdmissions || isPending} type="submit">
                  <UserCheck className="size-4" aria-hidden="true" />
                  办理入住
                </Button>
              </form>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <MoveRight className="size-5 text-primary" aria-hidden="true" />
                办理换床
              </CardTitle>
              <CardDescription>换床会释放原床位并占用新床位。</CardDescription>
            </CardHeader>
            <CardContent>
              <form className="grid gap-3" onSubmit={(event) => void submitTransfer(event)}>
                <Select
                  aria-label="换床入住记录"
                  disabled={!canManageAdmissions || isPending}
                  onValueChange={setTransferAdmissionId}
                  options={activeAdmissionOptions}
                  value={transferAdmissionId}
                />
                <Select
                  aria-label="换床新床位"
                  disabled={!canManageAdmissions || isPending}
                  onValueChange={setTransferBedId}
                  options={bedOptions}
                  value={transferBedId}
                />
                <Textarea
                  aria-label="换床备注"
                  disabled={!canManageAdmissions || isPending}
                  onChange={(event) => setTransferNotes(event.target.value)}
                  placeholder="备注"
                  value={transferNotes}
                />
                <Button disabled={!canManageAdmissions || isPending} type="submit" variant="outline">
                  <MoveRight className="size-4" aria-hidden="true" />
                  办理换床
                </Button>
              </form>
            </CardContent>
          </Card>

          <Card>
            <CardHeader>
              <CardTitle className="flex items-center gap-2">
                <UserMinus className="size-5 text-primary" aria-hidden="true" />
                办理退住
              </CardTitle>
              <CardDescription>退住会关闭入住记录并释放床位。</CardDescription>
            </CardHeader>
            <CardContent>
              <form className="grid gap-3" onSubmit={(event) => void submitDischarge(event)}>
                <Select
                  aria-label="退住入住记录"
                  disabled={!canManageAdmissions || isPending}
                  onValueChange={setDischargeAdmissionId}
                  options={activeAdmissionOptions}
                  value={dischargeAdmissionId}
                />
                <Textarea
                  aria-label="退住备注"
                  disabled={!canManageAdmissions || isPending}
                  onChange={(event) => setDischargeNotes(event.target.value)}
                  placeholder="备注"
                  value={dischargeNotes}
                />
                <Button disabled={!canManageAdmissions || isPending} type="submit" variant="destructive">
                  <UserMinus className="size-4" aria-hidden="true" />
                  办理退住
                </Button>
              </form>
            </CardContent>
          </Card>
        </section>
      ) : null}

      {activeTab === "history" ? (
        <Card>
          <CardHeader>
            <CardTitle>入住、换床与退住记录</CardTitle>
          </CardHeader>
          <CardContent>
            <div className="overflow-x-auto rounded-md border">
              <Table className="w-full min-w-[820px] 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.Row>
                </Table.Header>
                <Table.Body className="divide-y bg-card">
                  {admissions.map((admission) => (
                    <Table.Row key={admission.id}>
                      <Table.Cell className="px-4 py-3 font-medium">{admission.elderName}</Table.Cell>
                      <Table.Cell className="px-4 py-3">{admissionBedLabel(admission)}</Table.Cell>
                      <Table.Cell className="px-4 py-3">
                        <Badge variant={admission.status === "active" ? "success" : "secondary"}>
                          {admissionStatusLabels[admission.status]}
                        </Badge>
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3 text-muted-foreground">{formatDateTime(admission.admittedAt)}</Table.Cell>
                      <Table.Cell className="px-4 py-3 text-muted-foreground">
                        {admission.dischargedAt ? formatDateTime(admission.dischargedAt) : "-"}
                      </Table.Cell>
                      <Table.Cell className="px-4 py-3 text-muted-foreground">{admission.notes || "-"}</Table.Cell>
                    </Table.Row>
                  ))}
                  {admissions.length === 0 ? (
                    <Table.Row>
                      <Table.Cell className="px-4 py-8 text-center text-muted-foreground" colSpan={6}>
                        暂无入住记录
                      </Table.Cell>
                    </Table.Row>
                  ) : null}
                </Table.Body>
              </Table>
            </div>
          </CardContent>
        </Card>
      ) : null}
    </div>
  );
}

function contextToneClass(tone: OperationalContextLine["tone"]): string {
  if (tone === "danger") {
    return "text-destructive";
  }
  if (tone === "warning") {
    return "text-amber-700";
  }
  return "text-muted-foreground";
}

function ContextLines({ lines }: { lines: OperationalContextLine[] }): React.ReactElement {
  if (lines.length === 0) {
    return <span className="text-muted-foreground">-</span>;
  }

  return (
    <div className="grid gap-1">
      {lines.map((line) => (
        <p className={`max-w-[260px] truncate text-xs ${contextToneClass(line.tone)}`} key={`${line.kind}-${line.label}-${line.value}`}>
          <span className="font-medium">{line.label}</span> {line.value}
        </p>
      ))}
    </div>
  );
}

function OccupantSummary({
  context,
  fallbackName,
}: {
  context: BedOperationalContext | undefined;
  fallbackName: string | undefined;
}): React.ReactElement {
  if (!context?.occupant) {
    return <span className="text-muted-foreground">{fallbackName ?? "-"}</span>;
  }

  return (
    <div>
      <p className="font-medium">{context.occupant.elderName}</p>
      <p className="text-xs text-muted-foreground">
        {context.occupant.careLevel} / {context.occupant.status}
      </p>
    </div>
  );
}
