import { useState } from "react";
import { useQuery, useQueryClient } from "@tanstack/react-query";
import {
  deleteProject, getGroups, getGroupMaps, getProjects, getSpaces,
  deleteGroup, addGroupMember, removeGroupMember,
  createGroup, updateGroup, reorderGroups, listTemplates, deleteTemplate,
  getGroupMentorReport,
  type ProductGroup, type Project, type ProjectTemplate,
} from "../../lib/commands";
import { useUIStore } from "../../store/ui";
import { PriorityBadge, StatusBadge } from "../ui/Badge";
import { Dialog } from "../ui/Dialog";
import { TemplateEditor } from "./TemplateEditor";
import { NewProjectModal } from "./NewProjectModal";
import { renderTechStack } from "./techStackUtils";
import { TagsManager } from "./TagsManager";
import { RegistryTab } from "../dashboard/RepoRegistryModal";

export function ManagePage() {
  const [tab, setTab] = useState<"projects" | "groups" | "templates" | "tags" | "repos">("projects");
  const { data: spaces = [] } = useQuery({ queryKey: ["spaces"], queryFn: getSpaces });
  const currentSpaceId = spaces.find((s) => s.is_current)?.id;

  const TAB_LABELS = { projects: "项目", groups: "产品组", templates: "项目模板", tags: "标签", repos: "仓库" };

  return (
    <div className="flex flex-col h-full min-h-0">
      <div className="shrink-0 border-b border-gray-200 bg-white px-8 flex gap-1">
        {(["projects", "groups", "templates", "tags", "repos"] as const).map((t) => (
          <button
            key={t}
            onClick={() => setTab(t)}
            className={`px-4 py-3 text-sm font-medium border-b-2 -mb-px transition-colors ${
              tab === t ? "border-blue-500 text-blue-600" : "border-transparent text-gray-500 hover:text-gray-700"
            }`}
          >
            {TAB_LABELS[t]}
          </button>
        ))}
      </div>

      <div className="flex-1 overflow-y-auto min-h-0">
        <div className="w-full px-8 py-8 pb-16">
          {tab === "projects" && <ProjectsTab spaceId={currentSpaceId} />}
          {tab === "groups" && <GroupsTab spaceId={currentSpaceId} />}
          {tab === "templates" && <TemplatesTab spaceId={currentSpaceId} />}
          {tab === "tags" && <TagsManager />}
          {tab === "repos" && (
            <div className="bg-white rounded-xl border border-gray-200 shadow-sm flex flex-col max-h-[70vh]">
              <RegistryTab />
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ── Projects Tab ──────────────────────────────────────────────────────────── */

function ProjectsTab({ spaceId }: { spaceId?: string }) {
  const openEdit = useUIStore((s) => s.openEdit);
  const showToast = useUIStore((s) => s.showToast);
  const qc = useQueryClient();
  const [delTarget, setDelTarget] = useState<string | null>(null);
  const [deleteLocal, setDeleteLocal] = useState(false);
  const [showNewProject, setShowNewProject] = useState(false);
  const [view, setView] = useState<"all" | "by-group">("all");

  const { data: projects = [] } = useQuery({
    queryKey: ["projects", spaceId],
    queryFn: () => getProjects(undefined, spaceId),
  });
  const { data: groups = [] } = useQuery({
    queryKey: ["groups", spaceId],
    queryFn: () => getGroups(spaceId),
  });
  const { data: maps = [] } = useQuery({ queryKey: ["maps"], queryFn: getGroupMaps });

  const getProjectGroupNames = (projectId: string): string[] => {
    const groupIds = maps.filter((m) => m.project_id === projectId).map((m) => m.group_id);
    return groupIds.map((id) => groups.find((g) => g.id === id)?.name ?? "").filter(Boolean);
  };

  const confirmDelete = async () => {
    if (!delTarget) return;
    await deleteProject(delTarget, deleteLocal);
    setDelTarget(null);
    setDeleteLocal(false);
    qc.invalidateQueries({ queryKey: ["projects"] });
    showToast("已删除");
  };

  const PROJECT_VIEWS = [
    { key: "all", label: "全览表格" },
    { key: "by-group", label: "按产品组分组" },
  ] as const;

  return (
    <>
      <div className="flex items-center justify-between mb-4">
        <h2 className="text-sm font-semibold text-gray-700">共 {projects.length} 个项目</h2>
        <div className="flex items-center gap-2">
          <div className="flex rounded-lg border border-gray-200 overflow-hidden">
            {PROJECT_VIEWS.map(({ key, label }) => (
              <button
                key={key}
                onClick={() => setView(key)}
                className={`px-3 py-1.5 text-xs transition-colors ${
                  view === key ? "bg-blue-50 text-blue-600 font-medium" : "text-gray-500 hover:text-gray-700 hover:bg-gray-50"
                }`}
              >
                {label}
              </button>
            ))}
          </div>
          <button
            onClick={() => setShowNewProject(true)}
            className="px-3 py-1.5 rounded-lg border border-indigo-200 text-indigo-600 bg-indigo-50 text-sm hover:bg-indigo-100"
          >
            🔨 新建项目
          </button>
          <button
            onClick={() => openEdit(null)}
            className="px-3 py-1.5 rounded-lg bg-blue-600 text-white text-sm hover:bg-blue-700"
          >
            + 添加项目
          </button>
        </div>
      </div>

      {/* 全览表格视图 */}
      {view === "all" && (
        <div className="overflow-x-auto rounded-xl border border-gray-200 shadow-sm">
          <table className="w-full text-sm">
            <thead>
              <tr className="bg-gray-50 border-b border-gray-200">
                {["名称 / 描述", "产品组", "状态", "优先级", "技术栈", "本地路径", "操作"].map((h) => (
                  <th key={h} className="px-5 py-3.5 text-left text-xs font-semibold text-gray-500 uppercase tracking-wide whitespace-nowrap">
                    {h}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-100">
              {projects.map((p) => {
                const groupNames = getProjectGroupNames(p.id);
                return (
                  <tr key={p.id} className="bg-white hover:bg-gray-50/60 transition-colors group">
                    <td className="px-5 py-4">
                      <div className="font-semibold text-gray-900">{p.name}</div>
                      {p.description && (
                        <div className="text-xs text-gray-400 mt-0.5 max-w-[200px] truncate">{p.description}</div>
                      )}
                    </td>
                    <td className="px-5 py-4">
                      <div className="flex flex-wrap gap-1">
                        {groupNames.length > 0 ? groupNames.map((gName) => (
                          <span key={gName} className="px-2 py-0.5 rounded-md bg-blue-50 text-blue-700 text-xs font-medium border border-blue-100">
                            {gName}
                          </span>
                        )) : (
                          <span className="text-xs text-gray-300">—</span>
                        )}
                      </div>
                    </td>
                    <td className="px-5 py-4"><StatusBadge status={p.status} /></td>
                    <td className="px-5 py-4"><PriorityBadge priority={p.priority} /></td>
                    <td className="px-5 py-4 max-w-[160px]">
                      <div className="flex flex-wrap gap-1">
                        {(p.tech_stack ?? "").split(",").filter(Boolean).map((t) => (
                          <span key={t} className="px-1.5 py-0.5 rounded-full bg-gray-100 text-gray-600 text-xs">{t.trim()}</span>
                        ))}
                      </div>
                    </td>
                    <td className="px-5 py-4 max-w-[200px]">
                      <div className="flex flex-col gap-1 text-xs font-mono">
                        {p.wsl_path && (
                          <div className="flex items-center gap-1.5 truncate">
                            <span className="shrink-0 text-[11px] font-semibold text-green-700 bg-green-50 border border-green-200 rounded px-1">WSL</span>
                            <span className="text-gray-500 truncate" title={p.wsl_path}>{p.wsl_path}</span>
                          </div>
                        )}
                        {p.win_path && (
                          <div className="flex items-center gap-1.5 truncate">
                            <span className="shrink-0 text-[11px] font-semibold text-blue-700 bg-blue-50 border border-blue-200 rounded px-1">WIN</span>
                            <span className="text-gray-500 truncate" title={p.win_path}>{p.win_path}</span>
                          </div>
                        )}
                      </div>
                    </td>
                    <td className="px-5 py-4">
                      <div className="flex gap-2 opacity-70 group-hover:opacity-100 transition-opacity">
                        <button onClick={() => openEdit(p)} className="px-3 py-1.5 rounded-lg border border-gray-200 text-xs text-gray-600 hover:bg-gray-100 transition-colors">
                          编辑
                        </button>
                        <button onClick={() => setDelTarget(p.id)} className="px-3 py-1.5 rounded-lg border border-red-200 text-xs text-red-500 hover:bg-red-50 transition-colors">
                          删除
                        </button>
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
          {projects.length === 0 && (
            <div className="text-center py-20 text-gray-400 text-sm">暂无项目</div>
          )}
        </div>
      )}

      {/* 按产品组分组视图 */}
      {view === "by-group" && (
        <div className="space-y-6">
          {groups.map((g) => {
            const groupProjects = maps
              .filter((m) => m.group_id === g.id)
              .map((m) => projects.find((p) => p.id === m.project_id))
              .filter((p): p is Project => p !== undefined);
            return (
              <div key={g.id} className="rounded-xl border border-gray-200 shadow-sm overflow-hidden">
                <div className="px-5 py-3 bg-gray-50 border-b border-gray-200 flex items-center gap-2">
                  <span className="font-semibold text-gray-700">{g.name}</span>
                  <span className="text-xs text-gray-400 bg-white border border-gray-200 rounded-full px-2 py-0.5">
                    {groupProjects.length}
                  </span>
                  {g.description && (
                    <span className="text-xs text-gray-400 border-l border-gray-200 pl-2">{g.description}</span>
                  )}
                </div>
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-gray-100">
                      {["名称 / 描述", "状态", "优先级", "操作"].map((h) => (
                        <th key={h} className="px-5 py-2.5 text-left text-xs font-semibold text-gray-400 uppercase tracking-wide whitespace-nowrap">
                          {h}
                        </th>
                      ))}
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-gray-50">
                    {groupProjects.map((p) => (
                      <tr key={p.id} className="bg-white hover:bg-gray-50/60 transition-colors group">
                        <td className="px-5 py-3">
                          <div className="font-medium text-gray-900">{p.name}</div>
                          {p.description && (
                            <div className="text-xs text-gray-400 mt-0.5 max-w-[240px] truncate">{p.description}</div>
                          )}
                        </td>
                        <td className="px-5 py-3"><StatusBadge status={p.status} /></td>
                        <td className="px-5 py-3"><PriorityBadge priority={p.priority} /></td>
                        <td className="px-5 py-3">
                          <div className="flex gap-2 opacity-60 group-hover:opacity-100 transition-opacity">
                            <button onClick={() => openEdit(p)} className="px-2.5 py-1 rounded-lg border border-gray-200 text-xs text-gray-600 hover:bg-gray-100">编辑</button>
                            <button onClick={() => setDelTarget(p.id)} className="px-2.5 py-1 rounded-lg border border-red-200 text-xs text-red-500 hover:bg-red-50">删除</button>
                          </div>
                        </td>
                      </tr>
                    ))}
                    {groupProjects.length === 0 && (
                      <tr>
                        <td colSpan={4} className="px-5 py-4 text-xs text-gray-300 text-center">暂无项目</td>
                      </tr>
                    )}
                  </tbody>
                </table>
              </div>
            );
          })}
          {(() => {
            const ungrouped = projects.filter((p) => !maps.some((m) => m.project_id === p.id));
            if (ungrouped.length === 0) return null;
            return (
              <div className="rounded-xl border border-dashed border-gray-200 overflow-hidden">
                <div className="px-5 py-3 bg-gray-50/50 border-b border-gray-200 flex items-center gap-2">
                  <span className="font-semibold text-gray-400">未分组</span>
                  <span className="text-xs text-gray-400 bg-white border border-gray-200 rounded-full px-2 py-0.5">{ungrouped.length}</span>
                </div>
                <table className="w-full text-sm">
                  <thead>
                    <tr className="border-b border-gray-100">
                      {["名称 / 描述", "状态", "优先级", "操作"].map((h) => (
                        <th key={h} className="px-5 py-2.5 text-left text-xs font-semibold text-gray-400 uppercase tracking-wide whitespace-nowrap">{h}</th>
                      ))}
                    </tr>
                  </thead>
                  <tbody className="divide-y divide-gray-50">
                    {ungrouped.map((p) => (
                      <tr key={p.id} className="bg-white hover:bg-gray-50/60 transition-colors group">
                        <td className="px-5 py-3">
                          <div className="font-medium text-gray-900">{p.name}</div>
                          {p.description && <div className="text-xs text-gray-400 mt-0.5 max-w-[240px] truncate">{p.description}</div>}
                        </td>
                        <td className="px-5 py-3"><StatusBadge status={p.status} /></td>
                        <td className="px-5 py-3"><PriorityBadge priority={p.priority} /></td>
                        <td className="px-5 py-3">
                          <div className="flex gap-2 opacity-60 group-hover:opacity-100 transition-opacity">
                            <button onClick={() => openEdit(p)} className="px-2.5 py-1 rounded-lg border border-gray-200 text-xs text-gray-600 hover:bg-gray-100">编辑</button>
                            <button onClick={() => setDelTarget(p.id)} className="px-2.5 py-1 rounded-lg border border-red-200 text-xs text-red-500 hover:bg-red-50">删除</button>
                          </div>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            );
          })()}
          {groups.length === 0 && projects.length === 0 && (
            <div className="text-center py-16 text-gray-400 text-sm">暂无产品组，请先创建产品组并添加成员</div>
          )}
        </div>
      )}

      {delTarget && (
        <Dialog title="确认删除" onClose={() => { setDelTarget(null); setDeleteLocal(false); }} size="sm">
          <div className="px-6 py-4">
            <p className="text-sm text-gray-600 mb-2">删除后不可恢复，关联记录也会一并删除。</p>
            <p className="text-xs font-mono text-gray-400 mb-4">{delTarget}</p>
            <label className="flex items-center gap-2 mb-6 cursor-pointer select-none">
              <input
                type="checkbox"
                checked={deleteLocal}
                onChange={(e) => setDeleteLocal(e.target.checked)}
                className="w-4 h-4 rounded border-gray-300 text-red-600"
              />
              <span className="text-sm text-red-600">同时删除本地文件夹（不可恢复）</span>
            </label>
            <div className="flex justify-end gap-3">
              <button onClick={() => { setDelTarget(null); setDeleteLocal(false); }} className="px-4 py-2 rounded-lg text-sm border border-gray-200 text-gray-600 hover:bg-gray-50">取消</button>
              <button onClick={confirmDelete} className="px-4 py-2 rounded-lg text-sm bg-red-600 text-white hover:bg-red-700">确认删除</button>
            </div>
          </div>
        </Dialog>
      )}

      {showNewProject && (
        <NewProjectModal spaceId={spaceId} onClose={() => setShowNewProject(false)} />
      )}
    </>
  );
}

/* ── Groups Tab ────────────────────────────────────────────────────────────── */

function GroupsTab({ spaceId }: { spaceId?: string }) {
  const showToast = useUIStore((s) => s.showToast);
  const qc = useQueryClient();
  const [groupView, setGroupView] = useState<"overview" | "health" | "detail">("overview");
  const [groupModal, setGroupModal] = useState<ProductGroup | null | undefined>(undefined);
  const [memberTarget, setMemberTarget] = useState<ProductGroup | null>(null);
  const [delGroup, setDelGroup] = useState<string | null>(null);
  const [inspecting, setInspecting] = useState<Set<string>>(new Set());

  const handleInspect = async (groupId: string) => {
    setInspecting((prev) => new Set(prev).add(groupId));
    try {
      const report = await getGroupMentorReport(groupId);
      await navigator.clipboard.writeText(report);
      showToast("已复制，可粘贴给 Claude 进行全组分析");
    } catch (e) {
      showToast(`❌ 巡检失败: ${e}`);
    } finally {
      setInspecting((prev) => { const s = new Set(prev); s.delete(groupId); return s; });
    }
  };

  const { data: groups = [] } = useQuery({
    queryKey: ["groups", spaceId],
    queryFn: () => getGroups(spaceId),
  });
  const { data: maps = [] } = useQuery({ queryKey: ["maps"], queryFn: getGroupMaps });
  const { data: projects = [] } = useQuery({
    queryKey: ["projects", spaceId],
    queryFn: () => getProjects(undefined, spaceId),
  });

  const confirmDel = async () => {
    if (!delGroup) return;
    await deleteGroup(delGroup);
    setDelGroup(null);
    qc.invalidateQueries({ queryKey: ["groups", spaceId] });
    qc.invalidateQueries({ queryKey: ["maps"] });
    showToast("已删除");
  };

  const move = async (index: number, dir: -1 | 1) => {
    const next = index + dir;
    if (next < 0 || next >= groups.length) return;
    const ids = groups.map((g) => g.id);
    [ids[index], ids[next]] = [ids[next], ids[index]];
    await reorderGroups(ids);
    qc.invalidateQueries({ queryKey: ["groups", spaceId] });
  };

  const GROUP_VIEWS = [
    { key: "overview", label: "产品组概览" },
    { key: "health", label: "健康度" },
    { key: "detail", label: "成员详情" },
  ] as const;

  const renderGroupActions = (g: ProductGroup) => (
    <div className="flex gap-1.5 shrink-0">
      <button
        onClick={() => handleInspect(g.id)}
        disabled={inspecting.has(g.id)}
        className="px-2.5 py-1 rounded-lg border border-indigo-200 text-xs text-indigo-600 hover:bg-indigo-50 transition-colors disabled:opacity-50 flex items-center gap-1"
        title="聚合全组导师报告并复制到剪贴板"
      >
        {inspecting.has(g.id) ? (
          <svg className="w-3 h-3 animate-spin" viewBox="0 0 24 24" fill="none">
            <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"/>
            <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8v8H4z"/>
          </svg>
        ) : "🔍"}
        巡检
      </button>
      <button onClick={() => setMemberTarget(g)} className="px-2.5 py-1 rounded-lg border border-gray-200 text-xs text-gray-600 hover:bg-gray-100">+ 成员</button>
      <button onClick={() => setGroupModal(g)} className="px-2.5 py-1 rounded-lg border border-gray-200 text-xs text-gray-600 hover:bg-gray-100">编辑</button>
      <button onClick={() => setDelGroup(g.id)} className="px-2.5 py-1 rounded-lg border border-red-200 text-xs text-red-500 hover:bg-red-50">删除</button>
    </div>
  );

  return (
    <>
      <div className="flex items-center justify-between mb-4">
        <h2 className="text-sm font-semibold text-gray-700">共 {groups.length} 个产品组</h2>
        <div className="flex items-center gap-2">
          <div className="flex rounded-lg border border-gray-200 overflow-hidden">
            {GROUP_VIEWS.map(({ key, label }) => (
              <button
                key={key}
                onClick={() => setGroupView(key)}
                className={`px-3 py-1.5 text-xs transition-colors ${
                  groupView === key ? "bg-blue-50 text-blue-600 font-medium" : "text-gray-500 hover:text-gray-700 hover:bg-gray-50"
                }`}
              >
                {label}
              </button>
            ))}
          </div>
          <button
            onClick={() => setGroupModal(null)}
            className="px-3 py-1.5 rounded-lg bg-blue-600 text-white text-sm hover:bg-blue-700"
          >
            + 新建产品组
          </button>
        </div>
      </div>

      {/* 产品组概览视图 */}
      {groupView === "overview" && (
        <div className="overflow-x-auto rounded-xl border border-gray-200 shadow-sm">
          <table className="w-full text-sm">
            <thead>
              <tr className="bg-gray-50 border-b border-gray-200">
                {["产品组名称", "项目", "描述", "操作"].map((h) => (
                  <th key={h} className="px-5 py-3.5 text-left text-xs font-semibold text-gray-500 uppercase tracking-wide whitespace-nowrap">
                    {h}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-100">
              {groups.map((g) => {
                const groupProjectEntries = maps
                  .filter((m) => m.group_id === g.id)
                  .map((m) => { const p = projects.find((x) => x.id === m.project_id); return p ? { id: p.id, name: p.name } : null; })
                  .filter((e): e is { id: string; name: string } => e !== null);
                return (
                  <tr key={g.id} className="bg-white hover:bg-gray-50/60 transition-colors group">
                    <td className="px-5 py-4">
                      <div className="font-semibold text-gray-900">{g.name}</div>
                      <div className="text-xs font-mono text-gray-400 mt-0.5">{g.id}</div>
                    </td>
                    <td className="px-5 py-4 max-w-[320px]">
                      <div className="flex flex-wrap gap-1">
                        {groupProjectEntries.length > 0 ? groupProjectEntries.map(({ id, name }) => (
                          <span key={id} className="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-blue-50 text-blue-700 text-xs font-medium border border-blue-100">
                            {name}
                            <button
                              onClick={async () => { await removeGroupMember(id, g.id); qc.invalidateQueries({ queryKey: ["maps"] }); }}
                              className="text-blue-400 hover:text-red-400 transition-colors leading-none"
                            >×</button>
                          </span>
                        )) : (
                          <span className="text-xs text-gray-300">—</span>
                        )}
                      </div>
                    </td>
                    <td className="px-5 py-4 max-w-[280px]">
                      <span className="text-sm text-gray-500 truncate block">{g.description ?? "—"}</span>
                    </td>
                    <td className="px-5 py-4">
                      <div className="opacity-60 group-hover:opacity-100 transition-opacity">
                        {renderGroupActions(g)}
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
          {groups.length === 0 && (
            <div className="text-center py-20 text-gray-400 text-sm">暂无产品组</div>
          )}
        </div>
      )}

      {/* 健康度视图 */}
      {groupView === "health" && (
        <div className="overflow-x-auto rounded-xl border border-gray-200 shadow-sm">
          <table className="w-full text-sm">
            <thead>
              <tr className="bg-gray-50 border-b border-gray-200">
                {["产品组名称", "进行中", "维护中", "暂停", "已归档", "合计"].map((h) => (
                  <th key={h} className="px-5 py-3.5 text-left text-xs font-semibold text-gray-500 uppercase tracking-wide whitespace-nowrap">
                    {h}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-100">
              {groups.map((g) => {
                const groupProjectIds = maps.filter((m) => m.group_id === g.id).map((m) => m.project_id);
                const gps = groupProjectIds
                  .map((id) => projects.find((p) => p.id === id))
                  .filter((p): p is Project => p !== undefined);
                const counts = {
                  active: gps.filter((p) => p.status === "active").length,
                  maintenance: gps.filter((p) => p.status === "maintenance").length,
                  paused: gps.filter((p) => p.status === "paused").length,
                  archived: gps.filter((p) => p.status === "archived").length,
                };
                return (
                  <tr key={g.id} className="bg-white hover:bg-gray-50/60 transition-colors">
                    <td className="px-5 py-4 font-semibold text-gray-900">{g.name}</td>
                    <td className="px-5 py-4">
                      {counts.active > 0
                        ? <span className="px-2 py-0.5 rounded-full bg-green-100 text-green-800 text-xs font-medium">{counts.active}</span>
                        : <span className="text-gray-300 text-xs">—</span>}
                    </td>
                    <td className="px-5 py-4">
                      {counts.maintenance > 0
                        ? <span className="px-2 py-0.5 rounded-full bg-yellow-100 text-yellow-800 text-xs font-medium">{counts.maintenance}</span>
                        : <span className="text-gray-300 text-xs">—</span>}
                    </td>
                    <td className="px-5 py-4">
                      {counts.paused > 0
                        ? <span className="px-2 py-0.5 rounded-full bg-gray-100 text-gray-600 text-xs font-medium">{counts.paused}</span>
                        : <span className="text-gray-300 text-xs">—</span>}
                    </td>
                    <td className="px-5 py-4">
                      {counts.archived > 0
                        ? <span className="px-2 py-0.5 rounded-full bg-red-100 text-red-700 text-xs font-medium">{counts.archived}</span>
                        : <span className="text-gray-300 text-xs">—</span>}
                    </td>
                    <td className="px-5 py-4">
                      <span className="text-sm font-medium text-gray-600">{Object.values(counts).reduce((a, b) => a + b, 0)}</span>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
          {groups.length === 0 && (
            <div className="text-center py-20 text-gray-400 text-sm">暂无产品组</div>
          )}
        </div>
      )}

      {/* 成员详情视图 */}
      {groupView === "detail" && (
        <div className="space-y-4">
          {groups.map((g, idx) => {
            const members = maps.filter((m) => m.group_id === g.id);
            return (
              <div key={g.id} className="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
                <div className="flex items-center justify-between px-5 py-4 border-b border-gray-100 bg-gray-50/60">
                  <div className="flex items-center gap-3 min-w-0">
                    <div className="flex flex-col gap-0.5 shrink-0">
                      <button onClick={() => move(idx, -1)} disabled={idx === 0} className="text-gray-300 hover:text-gray-600 disabled:opacity-20 leading-none text-[10px]" title="上移">▲</button>
                      <button onClick={() => move(idx, 1)} disabled={idx === groups.length - 1} className="text-gray-300 hover:text-gray-600 disabled:opacity-20 leading-none text-[10px]" title="下移">▼</button>
                    </div>
                    <span className="font-semibold text-gray-800">{g.name}</span>
                    <span className="text-xs font-mono text-gray-400 bg-white border border-gray-200 rounded px-1.5 py-0.5">{g.id}</span>
                    {g.description && (
                      <span className="text-xs text-gray-400 border-l border-gray-200 pl-3 truncate">{g.description}</span>
                    )}
                  </div>
                  {renderGroupActions(g)}
                </div>
                <div className="px-5 py-4 flex flex-wrap gap-2">
                  {members.map((m) => {
                    const p = projects.find((x) => x.id === m.project_id);
                    const hasPath = !!(p?.win_path || p?.wsl_path);
                    return p ? (
                      <div key={m.project_id} className="flex items-center gap-2 px-3 py-1.5 rounded-lg bg-gray-50 border border-gray-200 text-xs">
                        <span className="font-medium text-gray-700">{p.name}</span>
                        {p.platform && (
                          <span className={`px-1.5 py-0.5 rounded border text-xs ${
                            p.platform === "wsl" ? "bg-orange-50 text-orange-600 border-orange-200" : "bg-blue-50 text-blue-600 border-blue-200"
                          }`}>
                            {p.platform === "wsl" ? "WSL" : "Win"}
                          </span>
                        )}
                        {hasPath ? (
                          <span className="flex items-center gap-1 px-1.5 py-0.5 rounded border bg-green-50 text-green-600 border-green-200" title={`MCP 已注入：${p.win_path || p.wsl_path}`}>
                            <span className="w-1.5 h-1.5 rounded-full bg-green-500 shrink-0" />
                            MCP
                          </span>
                        ) : (
                          <span className="px-1.5 py-0.5 rounded border bg-gray-100 text-gray-400 border-gray-200" title="项目未配置路径，MCP 注入已跳过">无路径</span>
                        )}
                        {m.role && <span className="text-gray-400 border-l border-gray-200 pl-2">{m.role}</span>}
                        <button
                          onClick={async () => { await removeGroupMember(m.project_id, g.id); qc.invalidateQueries({ queryKey: ["maps"] }); }}
                          className="text-gray-300 hover:text-red-400 transition-colors ml-0.5"
                        >×</button>
                      </div>
                    ) : null;
                  })}
                  {members.length === 0 && (
                    <span className="text-xs text-gray-400 py-1">暂无成员，点击「+ 成员」添加</span>
                  )}
                </div>
              </div>
            );
          })}
          {groups.length === 0 && (
            <div className="text-center py-16 text-gray-400 text-sm">暂无产品组</div>
          )}
        </div>
      )}

      {groupModal !== undefined && (
        <GroupFormModal
          group={groupModal}
          spaceId={spaceId}
          onClose={() => setGroupModal(undefined)}
          onSave={() => {
            setGroupModal(undefined);
            qc.invalidateQueries({ queryKey: ["groups", spaceId] });
            showToast(groupModal ? "已更新" : "已创建");
          }}
        />
      )}
      {memberTarget && (
        <AddMemberModal
          group={memberTarget}
          projects={projects}
          existingIds={new Set(maps.filter((m) => m.group_id === memberTarget.id).map((m) => m.project_id))}
          onClose={() => setMemberTarget(null)}
          onSave={() => {
            setMemberTarget(null);
            qc.invalidateQueries({ queryKey: ["maps"] });
            showToast("成员已添加");
          }}
        />
      )}
      {delGroup && (
        <Dialog title="确认删除产品组" onClose={() => setDelGroup(null)} size="sm">
          <div className="px-6 py-4">
            <p className="text-sm text-gray-600 mb-6">删除产品组不会删除项目，但会移除所有成员关系。</p>
            <div className="flex justify-end gap-3">
              <button onClick={() => setDelGroup(null)} className="px-4 py-2 rounded-lg text-sm border border-gray-200 text-gray-600 hover:bg-gray-50">取消</button>
              <button onClick={confirmDel} className="px-4 py-2 rounded-lg text-sm bg-red-600 text-white hover:bg-red-700">确认删除</button>
            </div>
          </div>
        </Dialog>
      )}
    </>
  );
}

function GroupFormModal({ group, spaceId, onClose, onSave }: {
  group: ProductGroup | null; spaceId?: string; onClose: () => void; onSave: () => void;
}) {
  const showToast = useUIStore((s) => s.showToast);
  const [form, setForm] = useState({ id: group?.id ?? "", name: group?.name ?? "", description: group?.description ?? "" });

  const save = async () => {
    if (!form.name.trim()) { showToast("❌ 名称不能为空"); return; }
    if (!group && !form.id.trim()) { showToast("❌ ID 不能为空"); return; }
    if (group) await updateGroup(group.id, { name: form.name, description: form.description || undefined });
    else await createGroup({ id: form.id, name: form.name, description: form.description || undefined, space_id: spaceId });
    onSave();
  };

  return (
    <Dialog title={group ? "编辑产品组" : "新建产品组"} onClose={onClose} size="sm">
      <div className="px-6 py-4 space-y-3">
        {!group && (
          <div>
            <label className="block text-xs font-medium text-gray-600 mb-1">ID *</label>
            <div className="flex gap-2">
              <input className="flex-1 border border-gray-200 rounded-lg px-3 py-2 text-sm font-mono" value={form.id} onChange={(e) => setForm((f) => ({ ...f, id: e.target.value }))} />
              <button
                type="button"
                onClick={() => setForm((f) => ({ ...f, id: crypto.randomUUID().replace(/-/g, "").slice(0, 8) }))}
                className="px-3 py-2 rounded-lg border border-gray-200 text-xs text-gray-500 hover:bg-gray-50 shrink-0"
                title="自动生成 ID"
              >
                自动生成
              </button>
            </div>
          </div>
        )}
        <div>
          <label className="block text-xs font-medium text-gray-600 mb-1">名称 *</label>
          <input className="w-full border border-gray-200 rounded-lg px-3 py-2 text-sm" value={form.name} onChange={(e) => setForm((f) => ({ ...f, name: e.target.value }))} />
        </div>
        <div>
          <label className="block text-xs font-medium text-gray-600 mb-1">描述</label>
          <input className="w-full border border-gray-200 rounded-lg px-3 py-2 text-sm" value={form.description} onChange={(e) => setForm((f) => ({ ...f, description: e.target.value }))} />
        </div>
        <div className="flex justify-end gap-3 pt-2">
          <button onClick={onClose} className="px-4 py-2 rounded-lg text-sm border border-gray-200 text-gray-600">取消</button>
          <button onClick={save} className="px-4 py-2 rounded-lg text-sm bg-blue-600 text-white hover:bg-blue-700">保存</button>
        </div>
      </div>
    </Dialog>
  );
}

function AddMemberModal({ group, projects, existingIds, onClose, onSave }: {
  group: ProductGroup; projects: Project[]; existingIds: Set<string>;
  onClose: () => void; onSave: () => void;
}) {
  const showToast = useUIStore((s) => s.showToast);
  const [selected, setSelected] = useState("");
  const [role, setRole] = useState("");
  const available = projects.filter((p) => !existingIds.has(p.id));

  const save = async () => {
    if (!selected) return;
    try {
      const warning = await addGroupMember(selected, group.id, role || undefined);
      if (warning) {
        showToast(`成员已添加，但 MCP 注入失败：${warning}`);
      }
      onSave();
    } catch (e) {
      showToast(`❌ 添加失败: ${e}`);
    }
  };

  return (
    <Dialog title={`添加成员到 ${group.name}`} onClose={onClose} size="sm">
      <div className="px-6 py-4 space-y-3">
        <div>
          <label className="block text-xs font-medium text-gray-600 mb-1">选择项目</label>
          <select className="w-full border border-gray-200 rounded-lg px-3 py-2 text-sm" value={selected} onChange={(e) => setSelected(e.target.value)}>
            <option value="">— 请选择 —</option>
            {available.map((p) => <option key={p.id} value={p.id}>{p.name}{p.description ? ` — ${p.description}` : ""}</option>)}
          </select>
        </div>
        <div>
          <label className="block text-xs font-medium text-gray-600 mb-1">角色（可选）</label>
          <input className="w-full border border-gray-200 rounded-lg px-3 py-2 text-sm" value={role} onChange={(e) => setRole(e.target.value)} placeholder="主服务 / 前端 / SDK…" />
        </div>
        <div className="flex justify-end gap-3 pt-2">
          <button onClick={onClose} className="px-4 py-2 rounded-lg text-sm border border-gray-200 text-gray-600">取消</button>
          <button onClick={save} disabled={!selected} className="px-4 py-2 rounded-lg text-sm bg-blue-600 text-white hover:bg-blue-700 disabled:opacity-50">添加</button>
        </div>
      </div>
    </Dialog>
  );
}


/* ── Templates Tab ─────────────────────────────────────────────────────────── */

function TemplatesTab({ spaceId: _spaceId }: { spaceId?: string }) {
  const showToast = useUIStore((s) => s.showToast);
  const qc = useQueryClient();
  const [editorTarget, setEditorTarget] = useState<string | null | undefined>(undefined);
  const [delTarget, setDelTarget] = useState<ProjectTemplate | null>(null);

  const { data: templates = [] } = useQuery({
    queryKey: ["templates"],
    queryFn: listTemplates,
  });

  const handleDelete = async () => {
    if (!delTarget) return;
    try {
      await deleteTemplate(delTarget.id);
      qc.invalidateQueries({ queryKey: ["templates"] });
      showToast("已删除");
    } catch (e) {
      showToast(`❌ ${e}`);
    } finally {
      setDelTarget(null);
    }
  };

  const PLATFORM_COLOR: Record<string, string> = {
    both: "bg-gray-100 text-gray-500 border-gray-200",
    win:  "bg-blue-50 text-blue-600 border-blue-200",
    wsl:  "bg-green-50 text-green-600 border-green-200",
  };
  const PLATFORM_LABEL: Record<string, string> = { both: "通用", win: "Windows", wsl: "WSL" };

  return (
    <>
      <div className="flex items-center justify-between mb-4">
        <h2 className="text-sm font-semibold text-gray-700">共 {templates.length} 个模板</h2>
        <button
          onClick={() => setEditorTarget(null)}
          className="px-3 py-1.5 rounded-lg bg-blue-600 text-white text-sm hover:bg-blue-700"
        >
          + 新建模板
        </button>
      </div>

      <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
        {templates.map((t) => (
          <div key={t.id} className="bg-white rounded-xl border border-gray-200 shadow-sm px-5 py-4 flex flex-col gap-2">
            <div className="flex items-start justify-between gap-2">
              <div className="flex-1 min-w-0">
                <div className="flex items-center gap-2 flex-wrap">
                  <span className="font-semibold text-sm text-gray-800">{t.name}</span>
                  {t.isBuiltin && (
                    <span className="text-[10px] px-1.5 py-0.5 rounded bg-gray-100 text-gray-500 border border-gray-200">内置</span>
                  )}
                  <span className={`text-[10px] px-1.5 py-0.5 rounded border ${PLATFORM_COLOR[t.platform] ?? PLATFORM_COLOR.both}`}>
                    {PLATFORM_LABEL[t.platform] ?? t.platform}
                  </span>
                </div>
                {t.description && (
                  <p className="text-xs text-gray-400 mt-0.5">{t.description}</p>
                )}
              </div>
              <div className="flex gap-1.5 shrink-0">
                <button
                  onClick={() => setEditorTarget(t.id)}
                  className="px-2.5 py-1 rounded-lg border border-gray-200 text-xs text-gray-600 hover:bg-gray-100"
                >
                  {t.isBuiltin ? "查看" : "编辑"}
                </button>
                {!t.isBuiltin && (
                  <button
                    onClick={() => setDelTarget(t)}
                    className="px-2.5 py-1 rounded-lg border border-red-200 text-xs text-red-500 hover:bg-red-50"
                  >
                    删除
                  </button>
                )}
              </div>
            </div>
            {t.techStack && renderTechStack(t.techStack)}
            {t.initCommands && (
              <code className="text-[11px] text-gray-400 font-mono">
                $ {t.initCommands.split("\n")[0]}
              </code>
            )}
          </div>
        ))}
        {templates.length === 0 && (
          <div className="col-span-2 text-center py-16 text-gray-400 text-sm">暂无模板</div>
        )}
      </div>

      {editorTarget !== undefined && (
        <TemplateEditor
          templateId={editorTarget}
          onClose={() => setEditorTarget(undefined)}
        />
      )}

      {delTarget && (
        <Dialog title="确认删除模板" onClose={() => setDelTarget(null)} size="sm">
          <div className="px-6 py-4">
            <p className="text-sm text-gray-600 mb-6">
              删除「{delTarget.name}」后不可恢复。
            </p>
            <div className="flex justify-end gap-3">
              <button onClick={() => setDelTarget(null)} className="px-4 py-2 rounded-lg text-sm border border-gray-200 text-gray-600 hover:bg-gray-50">取消</button>
              <button onClick={handleDelete} className="px-4 py-2 rounded-lg text-sm bg-red-600 text-white hover:bg-red-700">确认删除</button>
            </div>
          </div>
        </Dialog>
      )}
    </>
  );
}
