"use client";

import { FormEvent, useMemo, useState } from "react";
import { AlertTriangle, CheckCircle2, Search, Wrench, XCircle } 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 { ApiResult } from "@/modules/core/server/api";
import type { DeviceAsset, DeviceAssetInput, DeviceAssetStatus, DeviceOperationsData, MaintenanceTicket, MaintenanceTicketInput, MaintenanceTicketPriority, MaintenanceTicketStatus } from "@/modules/devices/types";
import { DEVICE_ASSET_STATUS_LABELS, DEVICE_ASSET_STATUS_VALUES, MAINTENANCE_TICKET_PRIORITY_LABELS, MAINTENANCE_TICKET_PRIORITY_VALUES, MAINTENANCE_TICKET_STATUS_LABELS, MAINTENANCE_TICKET_STATUS_VALUES } from "@/modules/devices/types";

type DevicesWorkspaceClientProps = {
  canManage: boolean;
  initialData: DeviceOperationsData;
};

type DialogState =
  | { kind: "device"; mode: "create"; value: DeviceAssetInput }
  | { kind: "device"; mode: "edit"; id: string; value: DeviceAssetInput }
  | { kind: "ticket"; mode: "create"; value: MaintenanceTicketInput }
  | { kind: "ticket"; mode: "edit"; id: string; value: MaintenanceTicketInput };

const emptyDevice: DeviceAssetInput = {
  name: "",
  code: "",
  category: "",
  location: "",
  status: "active",
  lastInspectedAt: undefined,
  notes: "",
};

const emptyTicket: MaintenanceTicketInput = {
  deviceId: undefined,
  title: "",
  description: "",
  priority: "normal",
  status: "open",
  assigneeLabel: "",
  resolutionNotes: "",
};

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

function deviceToInput(device: DeviceAsset): DeviceAssetInput {
  return {
    name: device.name,
    code: device.code,
    category: device.category,
    location: device.location,
    status: device.status,
    lastInspectedAt: device.lastInspectedAt,
    notes: device.notes,
  };
}

function ticketToInput(ticket: MaintenanceTicket): MaintenanceTicketInput {
  return {
    deviceId: ticket.deviceId,
    title: ticket.title,
    description: ticket.description,
    priority: ticket.priority,
    status: ticket.status,
    assigneeLabel: ticket.assigneeLabel,
    resolutionNotes: ticket.resolutionNotes,
  };
}

function badgeVariant(status: string): "danger" | "secondary" | "success" | "warning" {
  if (status === "active" || status === "resolved" || status === "closed") {
    return "success";
  }
  if (status === "maintenance" || status === "open" || status === "assigned" || status === "urgent") {
    return "warning";
  }
  if (status === "disabled" || status === "retired" || status === "cancelled") {
    return "danger";
  }
  return "secondary";
}

export function DevicesWorkspaceClient({ canManage, initialData }: DevicesWorkspaceClientProps): React.ReactElement {
  const [data, setData] = useState(initialData);
  const [query, setQuery] = useState("");
  const [deviceStatus, setDeviceStatus] = useState<"all" | DeviceAssetStatus>("all");
  const [ticketStatus, setTicketStatus] = useState<"all" | MaintenanceTicketStatus>("all");
  const [dialog, setDialog] = useState<DialogState | undefined>();
  const [message, setMessage] = useState("");
  const [isPending, setIsPending] = useState(false);
  const normalizedQuery = query.trim().toLowerCase();

  const filteredDevices = useMemo(
    () =>
      data.devices.filter((device) => {
        const matchesQuery = !normalizedQuery || [device.name, device.code, device.category, device.location, device.notes].join(" ").toLowerCase().includes(normalizedQuery);
        const matchesStatus = deviceStatus === "all" || device.status === deviceStatus;
        return matchesQuery && matchesStatus;
      }),
    [data.devices, deviceStatus, normalizedQuery],
  );
  const filteredTickets = useMemo(
    () =>
      data.tickets.filter((ticket) => {
        const matchesQuery = !normalizedQuery || [ticket.title, ticket.description, ticket.deviceName, ticket.assigneeLabel].join(" ").toLowerCase().includes(normalizedQuery);
        const matchesStatus = ticketStatus === "all" || ticket.status === ticketStatus;
        return matchesQuery && matchesStatus;
      }),
    [data.tickets, normalizedQuery, ticketStatus],
  );

  async function refreshData(): Promise<void> {
    const response = await fetch("/api/devices/assets");
    const result = (await response.json()) as ApiResult<{ data: DeviceOperationsData }>;
    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 === "device"
        ? isCreate
          ? "/api/devices/assets"
          : `/api/devices/assets/${dialog.id}`
        : isCreate
          ? "/api/devices/tickets"
          : `/api/devices/tickets/${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: "device" | "ticket", id: string): Promise<void> {
    if (!canManage) {
      setMessage("当前角色无权删除设备运维记录");
      return;
    }
    const path = kind === "device" ? `/api/devices/assets/${id}` : `/api/devices/tickets/${id}`;
    setIsPending(true);
    const response = await fetch(path, { 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={CheckCircle2} label="运行设备" value={data.metrics.activeDevices} />
        <MetricCard icon={Wrench} label="维护中设备" value={data.metrics.maintenanceDevices} />
        <MetricCard icon={AlertTriangle} label="待处理工单" value={data.metrics.openTickets} />
        <MetricCard icon={XCircle} label="紧急工单" value={data.metrics.urgentTickets} />
      </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) => setDeviceStatus(value as "all" | DeviceAssetStatus)} options={[{ value: "all", label: "全部设备状态" }, ...DEVICE_ASSET_STATUS_VALUES.map((value) => ({ value, label: DEVICE_ASSET_STATUS_LABELS[value] }))]} value={deviceStatus} />
          <Select aria-label="工单状态" onValueChange={(value) => setTicketStatus(value as "all" | MaintenanceTicketStatus)} options={[{ value: "all", label: "全部工单状态" }, ...MAINTENANCE_TICKET_STATUS_VALUES.map((value) => ({ value, label: MAINTENANCE_TICKET_STATUS_LABELS[value] }))]} value={ticketStatus} />
          <Button disabled={!canManage} onClick={() => setDialog({ kind: "device", mode: "create", value: emptyDevice })} type="button">新增设备</Button>
          <Button disabled={!canManage} onClick={() => setDialog({ kind: "ticket", mode: "create", value: emptyTicket })} 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}

      <Card>
        <CardHeader><CardTitle>设备台账</CardTitle></CardHeader>
        <CardContent className="overflow-x-auto">
          <Table className="w-full min-w-[900px] text-sm">
            <Table.Header className="bg-secondary text-left text-xs text-muted-foreground">
              <Table.Row>
                <Table.Head className="px-4 py-3">设备</Table.Head>
                <Table.Head className="px-4 py-3">分类</Table.Head>
                <Table.Head className="px-4 py-3">位置</Table.Head>
                <Table.Head className="px-4 py-3">状态</Table.Head>
                <Table.Head className="px-4 py-3">最近巡检</Table.Head>
                <Table.Head className="px-4 py-3 text-right">操作</Table.Head>
              </Table.Row>
            </Table.Header>
            <Table.Body className="divide-y bg-card">
              {filteredDevices.map((device) => (
                <Table.Row key={device.id}>
                  <Table.Cell className="px-4 py-3"><p className="font-medium">{device.name}</p><p className="text-xs text-muted-foreground">{device.code} / {device.notes || "-"}</p></Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">{device.category || "-"}</Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">{device.location || "-"}</Table.Cell>
                  <Table.Cell className="px-4 py-3"><Badge variant={badgeVariant(device.status)}>{DEVICE_ASSET_STATUS_LABELS[device.status]}</Badge></Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">{formatDateTime(device.lastInspectedAt)}</Table.Cell>
                  <Table.Cell className="px-4 py-3"><div className="flex justify-end gap-2"><Button disabled={!canManage || isPending} onClick={() => setDialog({ kind: "device", mode: "edit", id: device.id, value: deviceToInput(device) })} size="sm" type="button" variant="outline">编辑</Button><Button disabled={!canManage || isPending} onClick={() => remove("device", device.id)} size="sm" type="button" variant="outline">删除</Button></div></Table.Cell>
                </Table.Row>
              ))}
              {filteredDevices.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>
        </CardContent>
      </Card>

      <Card>
        <CardHeader><CardTitle>维修工单</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>
                <Table.Head className="px-4 py-3">工单</Table.Head>
                <Table.Head className="px-4 py-3">设备</Table.Head>
                <Table.Head className="px-4 py-3">优先级</Table.Head>
                <Table.Head className="px-4 py-3">状态</Table.Head>
                <Table.Head className="px-4 py-3">负责人</Table.Head>
                <Table.Head className="px-4 py-3">更新时间</Table.Head>
                <Table.Head className="px-4 py-3 text-right">操作</Table.Head>
              </Table.Row>
            </Table.Header>
            <Table.Body className="divide-y bg-card">
              {filteredTickets.map((ticket) => (
                <Table.Row key={ticket.id}>
                  <Table.Cell className="px-4 py-3"><p className="font-medium">{ticket.title}</p><p className="text-xs text-muted-foreground">{ticket.description || ticket.resolutionNotes || "-"}</p></Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">{ticket.deviceName || "-"}</Table.Cell>
                  <Table.Cell className="px-4 py-3"><Badge variant={badgeVariant(ticket.priority)}>{MAINTENANCE_TICKET_PRIORITY_LABELS[ticket.priority]}</Badge></Table.Cell>
                  <Table.Cell className="px-4 py-3"><Badge variant={badgeVariant(ticket.status)}>{MAINTENANCE_TICKET_STATUS_LABELS[ticket.status]}</Badge></Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">{ticket.assigneeLabel || "-"}</Table.Cell>
                  <Table.Cell className="px-4 py-3 text-muted-foreground">{formatDateTime(ticket.updatedAt)}</Table.Cell>
                  <Table.Cell className="px-4 py-3"><div className="flex justify-end gap-2"><Button disabled={!canManage || isPending} onClick={() => setDialog({ kind: "ticket", mode: "edit", id: ticket.id, value: ticketToInput(ticket) })} size="sm" type="button" variant="outline">编辑</Button><Button disabled={!canManage || isPending} onClick={() => remove("ticket", ticket.id)} size="sm" type="button" variant="outline">删除</Button></div></Table.Cell>
                </Table.Row>
              ))}
              {filteredTickets.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 onClose={() => setDialog(undefined)} open={dialog !== undefined} title={dialog?.kind === "device" ? "设备台账" : "维修工单"} width="lg">
        {dialog ? (
          <form className="grid gap-3" onSubmit={submitDialog}>
            {dialog.kind === "device" ? <DeviceForm dialog={dialog} setDialog={setDialog} /> : <TicketForm devices={data.devices} dialog={dialog} 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 DeviceForm({ dialog, setDialog }: { dialog: Extract<DialogState, { kind: "device" }>; setDialog: (dialog: DialogState) => void }): React.ReactElement {
  const value = dialog.value;
  function update(next: Partial<DeviceAssetInput>): void {
    setDialog({ ...dialog, value: { ...value, ...next } });
  }
  return (
    <>
      <Input label="设备名称" onChange={(event) => update({ name: event.target.value })} required value={value.name} />
      <Input label="设备编号" onChange={(event) => update({ code: event.target.value })} required value={value.code} />
      <Input label="分类" onChange={(event) => update({ category: event.target.value })} value={value.category} />
      <Input label="位置" onChange={(event) => update({ location: event.target.value })} value={value.location} />
      <Select aria-label="设备状态" onValueChange={(status) => update({ status: status as DeviceAssetStatus })} options={DEVICE_ASSET_STATUS_VALUES.map((status) => ({ value: status, label: DEVICE_ASSET_STATUS_LABELS[status] }))} value={value.status} />
      <Input label="最近巡检时间" onChange={(event) => update({ lastInspectedAt: event.target.value || undefined })} type="datetime-local" value={value.lastInspectedAt ? value.lastInspectedAt.slice(0, 16) : ""} />
      <Textarea label="备注" onChange={(event) => update({ notes: event.target.value })} value={value.notes} />
    </>
  );
}

function TicketForm({ devices, dialog, setDialog }: { devices: DeviceAsset[]; dialog: Extract<DialogState, { kind: "ticket" }>; setDialog: (dialog: DialogState) => void }): React.ReactElement {
  const value = dialog.value;
  function update(next: Partial<MaintenanceTicketInput>): void {
    setDialog({ ...dialog, value: { ...value, ...next } });
  }
  return (
    <>
      <Select aria-label="关联设备" onValueChange={(deviceId) => update({ deviceId: deviceId || undefined })} options={[{ value: "", label: "不关联设备" }, ...devices.map((device) => ({ value: device.id, label: `${device.name} / ${device.code}` }))]} value={value.deviceId ?? ""} />
      <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={(priority) => update({ priority: priority as MaintenanceTicketPriority })} options={MAINTENANCE_TICKET_PRIORITY_VALUES.map((priority) => ({ value: priority, label: MAINTENANCE_TICKET_PRIORITY_LABELS[priority] }))} value={value.priority} />
      <Select aria-label="工单状态" onValueChange={(status) => update({ status: status as MaintenanceTicketStatus })} options={MAINTENANCE_TICKET_STATUS_VALUES.map((status) => ({ value: status, label: MAINTENANCE_TICKET_STATUS_LABELS[status] }))} value={value.status} />
      <Input label="负责人" onChange={(event) => update({ assigneeLabel: event.target.value })} value={value.assigneeLabel} />
      <Textarea label="处理记录" onChange={(event) => update({ resolutionNotes: event.target.value })} value={value.resolutionNotes} />
    </>
  );
}

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>
  );
}
