import type { DocumentRecord } from "@/lib/documents";
import type { SidebarSectionId, TrashRecord } from "@/components/sidebar/types";
import type { Database } from "@/types/supabase";
import type { MediaAsset } from "@/types/media";
import {
  buildKernelSidebarProjection,
  buildSidebarTreeFromKernelProjection,
  type SidebarTreeNode,
} from "@/lib/kernel-sidebar";

type TypedClient = {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  from: (table: keyof Database["public"]["Tables"] | string) => any;
};

export type SidebarTableRow = {
  id: string;
  workspace_id: string | null;
  document_id: string;
  title: string | null;
  created_at: string | null;
  updated_at: string | null;
};

export interface SidebarDataset {
  documents: DocumentRecord[];
  trashedDocuments: TrashRecord[];
  trashedMediaAssets: MediaAsset[];
  /**
   * 仅依据远端 mindmap_data 判定的页面 id 列表；本地文件检测由服务器侧辅助完成
   */
  mindmapDocs: string[];
  mediaAssets?: MediaAsset[];
  tables?: SidebarTableRow[];
}

export async function fetchSidebarDataset(
  client: TypedClient,
  workspaceId: string,
): Promise<SidebarDataset> {
  const { data: documentRows, error } = await client
    .from("documents")
    .select(
      "id,title,parent_id,sort_order,is_starred,access_scope,is_template,created_at,updated_at,workspace_id,mindmap_data",
    )
    .eq("workspace_id", workspaceId)
    .is("deleted_at", null)
    .order("sort_order", { ascending: true, nullsFirst: false })
    .order("created_at", { ascending: true });

  if (error) {
    throw new Error(`获取工作空间文档列表失败：${error.message}`);
  }

  const documentRowsAny = (documentRows ?? []) as any[];
  const documents: DocumentRecord[] = documentRowsAny.map((row) => ({
    access_scope: (row.access_scope ?? "private") as DocumentRecord["access_scope"],
    id: row.id,
    workspace_id: row.workspace_id,
    title: row.title ?? "无标题",
    parent_id: row.parent_id,
    sort_order: row.sort_order,
    is_starred: row.is_starred,
    is_template: row.is_template ?? false,
    created_at: row.created_at ?? "",
    updated_at: row.updated_at ?? null,
  }));

  const { data: trashRows, error: trashError } = await client
    .from("documents")
    .select("id,title,parent_id,deleted_at,access_scope")
    .eq("workspace_id", workspaceId)
    .not("deleted_at", "is", null)
    .order("deleted_at", { ascending: false })
    .limit(100);

  if (trashError) {
    throw new Error(`获取垃圾桶内容失败：${trashError.message}`);
  }

  const trashRowsAny = (trashRows ?? []) as any[];
  const trashedDocuments: TrashRecord[] = trashRowsAny.map((row) => ({
    id: row.id,
    title: row.title,
    parent_id: row.parent_id,
    deleted_at: row.deleted_at!,
    access_scope: (row.access_scope ?? "private") as DocumentRecord["access_scope"],
  }));

  const mindmapDocs = documentRowsAny.filter((row) => row.mindmap_data != null).map((row) => row.id);

  const { data: assetRows, error: assetError } = await client
    .from("media_assets")
    .select("*")
    .eq("workspace_id", workspaceId)
    .is("deleted_at", null)
    .order("created_at", { ascending: false });

  if (assetError) {
    throw new Error(`获取附件列表失败：${assetError.message}`);
  }

  const mediaAssets: MediaAsset[] = (assetRows ?? []) as MediaAsset[];

  const { data: trashedAssetRows, error: trashedAssetError } = await client
    .from("media_assets")
    .select("*")
    .eq("workspace_id", workspaceId)
    .not("deleted_at", "is", null)
    .is("purged_at", null)
    .order("deleted_at", { ascending: false })
    .limit(200);

  if (trashedAssetError) {
    throw new Error(`获取附件垃圾桶失败：${trashedAssetError.message}`);
  }

  const trashedMediaAssets: MediaAsset[] = (trashedAssetRows ?? []) as MediaAsset[];

  // 说明：当前 supabase types 可能未包含 document_tables；这里用 any 兜底，
  // 避免类型缺失阻塞侧边栏功能。
  const { data: tableRows, error: tableError } = await (client as any)
    .from("document_tables")
    .select("id,workspace_id,document_id,title,created_at,updated_at,is_archived")
    .eq("workspace_id", workspaceId)
    .eq("is_archived", false)
    .order("created_at", { ascending: true });

  if (tableError) {
    throw new Error(`获取在线表格列表失败：${tableError.message}`);
  }

  const tables: SidebarTableRow[] = (tableRows ?? []) as unknown as SidebarTableRow[];

  return {
    documents,
    trashedDocuments,
    trashedMediaAssets,
    mindmapDocs,
    mediaAssets,
    tables,
  };
}

type NodePredicate = (node: SidebarTreeNode) => boolean;

function projectTree(nodes: SidebarTreeNode[], predicate: NodePredicate): SidebarTreeNode[] {
  const result: SidebarTreeNode[] = [];
  nodes.forEach((node) => {
    const projectedChildren = projectTree(node.children, predicate);
    if (predicate(node)) {
      result.push({
        ...node,
        children: projectedChildren,
      });
    } else {
      result.push(...projectedChildren);
    }
  });
  return result;
}

export function flattenDocumentTree(
  nodes: SidebarTreeNode[],
  expanded: Set<string>,
  depth = 0,
  parentId: string | null = null,
): Array<{ node: SidebarTreeNode; depth: number; parentId: string | null }> {
  const list: Array<{ node: SidebarTreeNode; depth: number; parentId: string | null }> = [];
  nodes.forEach((node) => {
    list.push({ node, depth, parentId });
    if (node.children.length > 0 && expanded.has(node.id)) {
      list.push(...flattenDocumentTree(node.children, expanded, depth + 1, node.id));
    }
  });
  return list;
}

const SECTION_META: Record<SidebarSectionId, { title: string; icon: string }> = {
  starred: { title: "星标置顶", icon: "star" },
  public: { title: "公共页面", icon: "globe" },
  shared: { title: "共享页面", icon: "users" },
  private: { title: "私有 / 我的页面", icon: "lock" },
  templates: { title: "模板中心", icon: "grid" },
};

type SidebarSectionSnapshot = {
  id: SidebarSectionId;
  title: string;
  icon?: string;
  nodes: SidebarTreeNode[];
};

export function buildSidebarSections(records: DocumentRecord[]): SidebarSectionSnapshot[] {
  const tree = buildSidebarTreeFromKernelProjection({
    records,
    projection: buildKernelSidebarProjection(records),
  });
  return buildSidebarSectionsFromTree(tree);
}

export function buildSidebarSectionsFromTree(
  tree: SidebarTreeNode[],
): SidebarSectionSnapshot[] {
  const sections: Array<{ id: SidebarSectionId; predicate: NodePredicate }> = [
    { id: "starred", predicate: (node) => Boolean(node.is_starred) },
    { id: "public", predicate: (node) => node.access_scope === "public" },
    { id: "shared", predicate: (node) => node.access_scope === "shared" },
    { id: "private", predicate: (node) => node.access_scope === "private" },
    { id: "templates", predicate: (node) => node.is_template },
  ];

  return sections.map(({ id, predicate }) => ({
    id,
    title: SECTION_META[id].title,
    icon: SECTION_META[id].icon,
    nodes: projectTree(tree, predicate),
  }));
}
