"use client";

import { FormEvent, useMemo, useState } from "react";
import { Edit3, 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 { AiKnowledgeScope, AiKnowledgeStatus, KnowledgeEntry, KnowledgeEntryInput } from "@/modules/ai/types";
import type { ApiResult } from "@/modules/core/server/api";
import type { Permission } from "@/modules/core/types";

type KnowledgeManagementClientProps = {
  initialEntries: KnowledgeEntry[];
  permissions: Permission[];
};

type KnowledgeFormState = {
  scope: AiKnowledgeScope;
  title: string;
  category: string;
  tags: string;
  body: string;
  status: AiKnowledgeStatus;
};

const emptyForm: KnowledgeFormState = {
  scope: "organization",
  title: "",
  category: "",
  tags: "",
  body: "",
  status: "enabled",
};

const scopeOptions = [
  { value: "organization", label: "机构私有" },
  { value: "platform", label: "平台共享" },
];

const statusOptions = [
  { value: "enabled", label: "启用" },
  { value: "disabled", label: "停用" },
];

function entryToForm(entry: KnowledgeEntry): KnowledgeFormState {
  return {
    scope: entry.scope,
    title: entry.title,
    category: entry.category,
    tags: entry.tags,
    body: entry.body,
    status: entry.status,
  };
}

function matchesEntry(entry: KnowledgeEntry, query: string): boolean {
  const normalized = query.trim().toLowerCase();
  if (!normalized) {
    return true;
  }
  return [entry.title, entry.category, entry.tags, entry.body].join(" ").toLowerCase().includes(normalized);
}

function formatKnowledgeFailureReason(reason: string): string {
  if (reason.includes("AI_API_KEY") || reason.includes("向量生成失败")) {
    return `保存知识需要可用的 AI 向量配置：${reason}`;
  }
  return reason;
}

export function KnowledgeManagementClient({ initialEntries, permissions }: KnowledgeManagementClientProps): React.ReactElement {
  const [entries, setEntries] = useState(initialEntries);
  const [query, setQuery] = useState("");
  const [editingId, setEditingId] = useState<string | null>(null);
  const [deleteTarget, setDeleteTarget] = useState<KnowledgeEntry | null>(null);
  const [form, setForm] = useState<KnowledgeFormState>(emptyForm);
  const [isDialogOpen, setIsDialogOpen] = useState(false);
  const [isPending, setIsPending] = useState(false);
  const [message, setMessage] = useState("");

  const canManage = permissions.includes("knowledge:manage");
  const filteredEntries = useMemo(() => entries.filter((entry) => matchesEntry(entry, query)), [entries, query]);
  const isEditing = editingId !== null;

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

  function beginCreate(): void {
    setEditingId(null);
    setForm(emptyForm);
    setMessage("");
    setIsDialogOpen(true);
  }

  function beginEdit(entry: KnowledgeEntry): void {
    setEditingId(entry.id);
    setForm(entryToForm(entry));
    setMessage("");
    setIsDialogOpen(true);
  }

  function closeDialog(): void {
    if (isPending) {
      return;
    }
    setIsDialogOpen(false);
    setEditingId(null);
    setForm(emptyForm);
  }

  async function refreshEntries(): Promise<void> {
    const response = await fetch("/api/ai/knowledge");
    const result = (await response.json()) as ApiResult<{ entries: KnowledgeEntry[] }>;
    if (result.success) {
      setEntries(result.entries);
    }
  }

  async function submit(event: FormEvent<HTMLFormElement>): Promise<void> {
    event.preventDefault();
    if (!canManage) {
      setMessage("当前角色无权维护知识库");
      return;
    }

    setIsPending(true);
    setMessage("");
    const payload: KnowledgeEntryInput = {
      ...form,
    };
    const response = await fetch(isEditing ? `/api/ai/knowledge/${editingId}` : "/api/ai/knowledge", {
      method: isEditing ? "PATCH" : "POST",
      headers: { "content-type": "application/json" },
      body: JSON.stringify(payload),
    });
    const result = (await response.json()) as ApiResult<{ entry: KnowledgeEntry }>;
    setIsPending(false);
    if (!result.success) {
      setMessage(formatKnowledgeFailureReason(result.reason));
      return;
    }

    await refreshEntries();
    closeDialog();
    setMessage(result.reason);
  }

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

    setIsPending(true);
    setMessage("");
    const response = await fetch(`/api/ai/knowledge/${deleteTarget.id}`, { method: "DELETE" });
    const result = (await response.json()) as ApiResult<{ entry: KnowledgeEntry }>;
    setIsPending(false);
    if (!result.success) {
      setMessage(result.reason);
      return;
    }

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

  async function toggleStatus(entry: KnowledgeEntry): Promise<void> {
    const nextStatus: AiKnowledgeStatus = entry.status === "enabled" ? "disabled" : "enabled";
    const response = await fetch(`/api/ai/knowledge/${entry.id}`, {
      method: "PATCH",
      headers: { "content-type": "application/json" },
      body: JSON.stringify({ ...entry, status: nextStatus }),
    });
    const result = (await response.json()) as ApiResult<{ entry: KnowledgeEntry }>;
    if (!result.success) {
      setMessage(formatKnowledgeFailureReason(result.reason));
      return;
    }
    await refreshEntries();
    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>
          <h1 className="text-3xl font-semibold tracking-normal">知识库</h1>
          <p className="mt-2 text-sm text-muted-foreground">维护平台共享和机构私有知识，保存后会重建检索向量。</p>
        </div>
        <Button disabled={!canManage} onClick={beginCreate} type="button">
          <Plus className="size-4" aria-hidden="true" />
          新增知识
        </Button>
      </section>

      <Card>
        <CardHeader className="gap-4">
          <div className="flex flex-col gap-3 md:flex-row md:items-end md:justify-between">
            <div>
              <CardTitle>知识条目</CardTitle>
              <CardDescription>共 {filteredEntries.length} 条匹配记录。</CardDescription>
            </div>
            <label className="relative block w-full md:max-w-sm">
              <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) => setQuery(event.target.value)} placeholder="搜索标题、分类、标签、内容" value={query} />
            </label>
          </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-[860px] 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 text-right font-medium">操作</Table.Head>
                </Table.Row>
              </Table.Header>
              <Table.Body className="divide-y bg-card">
                {filteredEntries.map((entry) => (
                  <Table.Row key={entry.id}>
                    <Table.Cell className="px-4 py-3">
                      <p className="font-medium">{entry.title}</p>
                      <p className="max-w-md truncate text-xs text-muted-foreground">{entry.body}</p>
                    </Table.Cell>
                    <Table.Cell className="px-4 py-3">{entry.scope === "platform" ? "平台共享" : "机构私有"}</Table.Cell>
                    <Table.Cell className="px-4 py-3 text-muted-foreground">{entry.category || "-"}</Table.Cell>
                    <Table.Cell className="px-4 py-3 text-muted-foreground">{entry.tags || "-"}</Table.Cell>
                    <Table.Cell className="px-4 py-3">
                      <Badge variant={entry.status === "enabled" ? "success" : "secondary"}>
                        {entry.status === "enabled" ? "启用" : "停用"}
                      </Badge>
                    </Table.Cell>
                    <Table.Cell className="px-4 py-3">
                      <div className="flex justify-end gap-2">
                        <Button disabled={!canManage} onClick={() => void toggleStatus(entry)} size="sm" type="button" variant="outline">
                          {entry.status === "enabled" ? "停用" : "启用"}
                        </Button>
                        <Button disabled={!canManage} onClick={() => beginEdit(entry)} size="sm" type="button" variant="outline">
                          <Edit3 className="size-4" aria-hidden="true" />
                          编辑
                        </Button>
                        <Button disabled={!canManage} onClick={() => setDeleteTarget(entry)} size="sm" type="button" variant="destructive">
                          <Trash2 className="size-4" aria-hidden="true" />
                          删除
                        </Button>
                      </div>
                    </Table.Cell>
                  </Table.Row>
                ))}
                {filteredEntries.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>

      <Dialog
        description="保存时会写入数据库、重建分块和 embedding。"
        onClose={closeDialog}
        open={isDialogOpen}
        title={isEditing ? "编辑知识" : "新增知识"}
        width="lg"
      >
        <form className="grid gap-3" onSubmit={submit}>
          <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("scope", value as AiKnowledgeScope)}
                options={scopeOptions}
                value={form.scope}
              />
            </div>
            <div className="grid gap-1.5 text-sm font-medium">
              状态
              <Select
                aria-label="知识状态"
                onValueChange={(value) => updateField("status", value as AiKnowledgeStatus)}
                options={statusOptions}
                value={form.status}
              />
            </div>
          </div>
          <label className="grid gap-1.5 text-sm font-medium">
            标题
            <Input onChange={(event) => updateField("title", event.target.value)} required value={form.title} />
          </label>
          <div className="grid gap-3 sm:grid-cols-2">
            <label className="grid gap-1.5 text-sm font-medium">
              分类
              <Input onChange={(event) => updateField("category", event.target.value)} value={form.category} />
            </label>
            <label className="grid gap-1.5 text-sm font-medium">
              标签
              <Input onChange={(event) => updateField("tags", event.target.value)} placeholder="逗号分隔" value={form.tags} />
            </label>
          </div>
          <label className="grid gap-1.5 text-sm font-medium">
            内容
            <Textarea className="min-h-56" onChange={(event) => updateField("body", event.target.value)} required value={form.body} />
          </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={closeDialog} type="button" variant="outline">
              取消
            </Button>
            <Button disabled={isPending || !canManage} type="submit">
              <Plus className="size-4" aria-hidden="true" />
              保存知识
            </Button>
          </div>
        </form>
      </Dialog>

      <Dialog
        description={deleteTarget ? `确认删除「${deleteTarget.title}」？对应分块也会删除。` : undefined}
        onClose={() => setDeleteTarget(null)}
        open={deleteTarget !== null}
        title="删除确认"
        width="sm"
      >
        <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 || !canManage} onClick={() => void remove()} type="button" variant="destructive">
            删除知识
          </Button>
        </div>
      </Dialog>
    </div>
  );
}
