import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import type React from "react";
import { Link, useParams } from "react-router";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
  getProject,
  getStructure,
  listLanguages,
  type Project,
  type ProjectStructure,
  getLanguageTranslations,
  upsertStructure,
  deleteEntryFromAllLanguages,
  renameEntryInAllLanguages,
} from "@/lib/db";
import { ArrowLeft } from "lucide-react";
import { useTranslationInlineEdit } from "@/hooks/biz/use-translation-inline-edit";
import { flattenEntries, type FlatEntry, insertEntrySibling, removeEntryAtPath, renameEntryAtPath } from "@/lib/i18n-structure";
import { ImportLanguageModal } from "@/components/biz/import-language-modal";
import { ExportLanguageModal } from "@/components/biz/export-language-modal";
import { EntryNameModal } from "@/components/biz/entry-name-modal";
import { TableVirtuoso, type TableVirtuosoHandle } from "react-virtuoso";
import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
} from "@/components/ui/dropdown-menu";

export default function Editor() {
  const { id: projectId } = useParams();
  const [project, setProject] = useState<Project | null>(null);
  const [structure, setStructure] = useState<ProjectStructure | null>(null);
  const [languages, setLanguages] = useState<string[]>([]);
  const [loading, setLoading] = useState(true);
  const [pageError, setPageError] = useState<string | null>(null);
  const [importOpen, setImportOpen] = useState(false);
  const [exportOpen, setExportOpen] = useState(false);
  const [addModal, setAddModal] = useState<{ open: boolean; path: string; position: "above" | "below" } | null>(null);
  const [renameModal, setRenameModal] = useState<{ open: boolean; path: string } | null>(null);
  const virtuosoRef = useRef<TableVirtuosoHandle | null>(null);
  const scrollerRootRef = useRef<HTMLElement | Window | null>(null);
  const [query, setQuery] = useState("");
  const [caseSensitive, setCaseSensitive] = useState(false);
  const [fullMatch, setFullMatch] = useState(false);

  function highlightRow(index: number) {
    const tryFindAndAnimate = (attempt = 0) => {
      const root = scrollerRootRef.current as HTMLElement | null;
      if (!root) return;
      const row = root.querySelector(`tr[data-item-index="${index}"]`) as HTMLTableRowElement | null;
      if (row) {
        row.animate(
          [
            { backgroundColor: "rgba(250, 204, 21, 0.6)" },
            { backgroundColor: "transparent" },
            { backgroundColor: "rgba(250, 204, 21, 0.6)" },
            { backgroundColor: "transparent" },
          ],
          { duration: 1200, easing: "ease-in-out" }
        );
        return;
      }
      if (attempt < 10) {
        setTimeout(() => tryFindAndAnimate(attempt + 1), 50);
      }
    };
    // 等一帧，确保滚动定位后的 DOM 稳定
    requestAnimationFrame(() => tryFindAndAnimate(0));
  }

  function scrollToQuery() {
    if (!query) return;
    const idx = entries.findIndex((e) => {
      const hay = caseSensitive ? e.path : e.path.toLowerCase();
      const needle = caseSensitive ? query : query.toLowerCase();
      return fullMatch ? hay === needle : hay.includes(needle);
    });
    if (idx >= 0) {
      virtuosoRef.current?.scrollIntoView({ index: idx, align: "center", done: () => highlightRow(idx) });
    }
  }

  async function refresh() {
    if (!projectId) return;
    setLoading(true);
    setPageError(null);
    try {
      const p = await getProject(projectId);
      if (!p) throw new Error("项目不存在");
      setProject(p);
      const s = await getStructure(projectId);
      if (s) setStructure(s);
      const langs = await listLanguages(projectId);
      setLanguages(langs);
    } catch (e) {
      setPageError((e as Error)?.message ?? "加载失败");
    } finally {
      setLoading(false);
    }
  }

  useEffect(() => {
    void refresh();
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [projectId]);

  const entries: FlatEntry[] = useMemo(() => {
    if (!structure) return [];
    return flattenEntries(structure.root);
  }, [structure]);

  const [valuesByLang, setValuesByLang] = useState<Record<string, Record<string, string>>>({});
  const inline = useTranslationInlineEdit({
    projectId,
    valuesByLang,
    setValuesByLang,
    onError: (m) => setPageError(m),
  });

  const colWidth = useMemo(() => `${100 / (languages.length + 2)}%`, [languages.length]);

  const virtuosoComponents = useMemo(() => ({
    Table: (props: React.TableHTMLAttributes<HTMLTableElement>) => <table className="min-w-full text-sm table-fixed" {...props} />,
    TableHead: (props: React.HTMLAttributes<HTMLTableSectionElement>) => <thead className="bg-muted" {...props} />,
    TableRow: (props: React.HTMLAttributes<HTMLTableRowElement>) => <tr className="border-t" {...props} />,
    TableBody: (props: React.HTMLAttributes<HTMLTableSectionElement>) => <tbody {...props} />,
    TableFoot: (props: React.HTMLAttributes<HTMLTableSectionElement>) => <tfoot {...props} />,
  }), []);

  const headerContent = useCallback(() => (
    <tr>
      <th style={{ width: colWidth }} className="text-left px-3 py-2">翻译条目名称</th>
      {languages.map((lang) => (
        <th key={lang} style={{ width: colWidth }} className="text-left px-3 py-2 whitespace-nowrap">{lang}</th>
      ))}
      <th style={{ width: "5em" }} className="text-left px-3 py-2">操作</th>
    </tr>
  ), [languages, colWidth]);

  const renderItemContent = useCallback((_idx: number, entry: FlatEntry) => {
    return (
      <>
        <td style={{ width: colWidth }} className="px-3 py-2 font-mono whitespace-nowrap">{entry.path}</td>
        {languages.map((lang) => {
          const isEditing = inline.isEditingCell(entry.path, lang);
          const isSaving = inline.isSavingCell(entry.path, lang);
          const displayValue = inline.getDisplayValue(entry.path, lang);
          return (
            <td key={`${entry.path}:${lang}`} style={{ width: colWidth }} className="px-3 py-2 text-foreground/90 align-top">
              {isEditing ? (
                <Input
                  ref={inline.inputRef}
                  value={inline.editingValue}
                  onChange={(e) => inline.setEditingValue(e.target.value)}
                  onBlur={inline.saveEdit}
                  onKeyDown={inline.handleKeyDown}
                  disabled={isSaving}
                  className="h-8"
                />
              ) : (
                <button
                  type="button"
                  className="w-full text-left min-h-8 leading-8 px-2 rounded hover:bg-accent"
                  onClick={() => inline.startEdit(entry.path, lang)}
                  title="点击编辑"
                >
                  {displayValue || <span className="text-muted-foreground">点击编辑</span>}
                </button>
              )}
            </td>
          );
        })}
        <td style={{ width: "5em" }} className="px-3 py-2 align-top">
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button size="sm" variant="outline">操作</Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="w-44">
              <DropdownMenuItem onClick={() => setAddModal({ open: true, path: entry.path, position: "below" })}>
                在下面新增
              </DropdownMenuItem>
              <DropdownMenuItem onClick={() => setAddModal({ open: true, path: entry.path, position: "above" })}>
                在上面新增
              </DropdownMenuItem>
              <DropdownMenuSeparator />
              <DropdownMenuItem
                onClick={async () => {
                  if (!projectId || !structure) return;
                  if (!confirm("确认删除该条目？此操作会移除所有语言下的该键")) return;
                  try {
                    const nextRoot = removeEntryAtPath(structure.root, entry.path);
                    await upsertStructure({ projectId, root: nextRoot });
                    await deleteEntryFromAllLanguages(projectId, entry.path);
                    setStructure({ projectId, root: nextRoot });
                    setValuesByLang((old) => {
                      const copy: typeof old = {};
                      for (const [langKey, vals] of Object.entries(old)) {
                        const rest = { ...vals } as Record<string, string>;
                        delete rest[entry.path];
                        copy[langKey] = rest;
                      }
                      return copy;
                    });
                  } catch (e) {
                    setPageError((e as Error)?.message ?? "删除失败");
                  }
                }}
              >
                删除
              </DropdownMenuItem>
              <DropdownMenuItem onClick={() => setRenameModal({ open: true, path: entry.path })}>
                重命名
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </td>
      </>
    );
  }, [languages, colWidth, inline, projectId, structure, setStructure, setValuesByLang]);

  useEffect(() => {
    if (!projectId || languages.length === 0) return;
    let cancelled = false;
    (async () => {
      const all: Record<string, Record<string, string>> = {};
      for (const lang of languages) {
        const rec = await getLanguageTranslations(projectId, lang);
        all[lang] = rec?.values ?? {};
      }
      if (!cancelled) setValuesByLang(all);
    })();
    return () => {
      cancelled = true;
    };
  }, [projectId, languages]);

  return (
    <div className="h-screen flex flex-col">
      <header className="h-14 border-b px-2 md:px-4">
        <div className="grid grid-cols-3 h-full items-center">
          <div className="flex items-center gap-2">
            <Button asChild size="icon" variant="ghost" aria-label="返回">
              <Link to="/">
                <ArrowLeft className="size-5" />
              </Link>
            </Button>
          </div>
          <div className="text-center font-medium truncate">
            {project?.name ?? "编辑器"}
          </div>
          <div className="flex items-center justify-end gap-2">
            {!structure ? (
              <Button onClick={() => { setImportOpen(true); }}>构建翻译结构</Button>
            ) : (
              <Button variant="outline" onClick={() => { setImportOpen(true); }}>导入语言 JSON</Button>
            )}
            {languages.length > 0 && (
              <Button variant="outline" onClick={() => setExportOpen(true)}>导出 JSON</Button>
            )}
          </div>
        </div>
      </header>

      <main className="flex-1 overflow-auto p-4 md:p-6">
        {pageError && (
          <div className="mb-4 text-sm text-red-600" role="alert">{pageError}</div>
        )}

        {loading ? (
          <div className="text-sm text-muted-foreground">加载中...</div>
        ) : !structure ? (
          <div className="rounded-md border border-dashed p-6">
            <div className="text-sm text-muted-foreground">
              该项目还没有翻译结构。请导入一份 JSON 文件来构建结构，并同时录入该语言的翻译内容。
            </div>
            <div className="mt-3">
              <Button onClick={() => { setImportOpen(true); }}>构建翻译结构</Button>
            </div>
          </div>
        ) : (
          <div>
            <div className="mb-3 flex items-center gap-2">
              <Input placeholder="搜索翻译条目名称" value={query} onChange={(e) => setQuery(e.target.value)} />
              <Button
                variant={fullMatch ? "default" : "outline"}
                onClick={() => setFullMatch((v) => !v)}
                title="切换全量匹配/模糊匹配"
              >
                {fullMatch ? "全量匹配" : "模糊匹配"}
              </Button>
              <Button
                variant={caseSensitive ? "default" : "outline"}
                onClick={() => setCaseSensitive((v) => !v)}
                title="切换大小写敏感"
              >
                {caseSensitive ? "区分大小写" : "忽略大小写"}
              </Button>
              <Button variant="outline" onClick={scrollToQuery}>定位</Button>
            </div>
            <div className="border rounded-md">
              <TableVirtuoso
                ref={virtuosoRef}
                data={entries}
                style={{ height: "60vh" }}
                fixedHeaderContent={headerContent}
                itemContent={renderItemContent}
                components={virtuosoComponents}
                computeItemKey={(_index, entry) => entry.path}
                scrollerRef={(el) => { scrollerRootRef.current = el; }}
              />
            </div>
          </div>
        )}
      </main>

      <ImportLanguageModal
        open={importOpen}
        onOpenChange={setImportOpen}
        projectId={projectId ?? ""}
        hasStructure={!!structure}
        onImported={refresh}
      />
      <ExportLanguageModal
        open={exportOpen}
        onOpenChange={setExportOpen}
        languages={languages}
        valuesByLang={valuesByLang}
        orderedPaths={entries.map((e) => e.path)}
      />

      <EntryNameModal
        open={!!addModal?.open}
        onOpenChange={(v) => setAddModal((cur) => (cur ? { ...cur, open: v } : cur))}
        title={addModal?.position === "above" ? "在上方新增条目" : "在下方新增条目"}
        placeholder="请输入条目名称（不含点）"
        onConfirm={async (name) => {
          if (!projectId || !structure || !addModal) return;
          const nextRoot = insertEntrySibling(structure.root, addModal.path, addModal.position, name);
          await upsertStructure({ projectId, root: nextRoot });
          setStructure({ projectId, root: nextRoot });
        }}
        validate={(name) => {
          // 同级重名校验在结构函数中也会做，这里做基础提示即可
          if (name.includes('.')) return "名称不能包含 '.'";
          return null;
        }}
      />

      <EntryNameModal
        open={!!renameModal?.open}
        onOpenChange={(v) => setRenameModal((cur) => (cur ? { ...cur, open: v } : cur))}
        title="重命名条目"
        placeholder="请输入新名称（不含点）"
        defaultValue={renameModal?.path ? renameModal.path.split('.').pop() : ''}
        onConfirm={async (newName) => {
          if (!projectId || !structure || !renameModal) return;
          const { root: nextRoot, newPath } = renameEntryAtPath(structure.root, renameModal.path, newName);
          await upsertStructure({ projectId, root: nextRoot });
          await renameEntryInAllLanguages(projectId, renameModal.path, newPath);
          setStructure({ projectId, root: nextRoot });
          setValuesByLang((old) => {
            const copy: typeof old = {};
            for (const [langKey, vals] of Object.entries(old)) {
              if (Object.prototype.hasOwnProperty.call(vals, renameModal.path)) {
                const { [renameModal.path]: val, ...rest } = vals;
                copy[langKey] = { ...rest, [newPath]: val };
              } else {
                copy[langKey] = vals;
              }
            }
            return copy;
          });
        }}
        validate={(name) => {
          if (name.includes('.')) return "名称不能包含 '.'";
          return null;
        }}
      />
    </div>
  );
}


