"use client";

import type { KernelFileTreeProjectionItem } from "@/lib/kernel-file-tree";
import type { PageTreeProjectionItem } from "@/lib/tree-projection";

export type TreeShellPickerItem =
  | { kind: "root"; id: null; title: string; subtitle?: string; depth?: number }
  | { kind: "doc"; id: string; title: string; subtitle?: string; depth?: number };

export type TreeShellDomProjectionItem = {
  rowId?: string;
  nodeId: string;
  parentNodeId: string | null;
  title: string;
  depth: number;
  childCount: number;
  position: number;
  expandedByDefault: boolean;
  rowKind?: string;
  iconHint?: string;
  capabilities?: string[];
  resourceMeta?: {
    resourceKind?: string;
    documentId?: string;
    assetId?: string;
    workspaceId?: string;
    assetKind?: string;
    iconHint?: string;
  };
};

const normalizeString = (value: unknown, fallback = "") => {
  if (typeof value !== "string") {
    return fallback;
  }
  const trimmed = value.trim();
  return trimmed || fallback;
};

export function buildTreeShellDomPickerItems(
  items: TreeShellPickerItem[],
): TreeShellDomProjectionItem[] {
  return items
    .filter(
      (item): item is Extract<TreeShellPickerItem, { kind: "doc"; id: string }> =>
        item.kind === "doc" && Boolean(normalizeString(item.id)),
    )
    .map((item, index) => ({
      nodeId: normalizeString(item.id),
      parentNodeId: null,
      title: normalizeString(item.title, "无标题"),
      depth: typeof item.depth === "number" && Number.isFinite(item.depth) ? Math.max(0, item.depth) : 0,
      childCount: 0,
      position: index,
      expandedByDefault: false,
    }));
}

export function buildTreeShellDomPageItems(
  items: PageTreeProjectionItem[],
  expanded: ReadonlySet<string> = new Set(),
): TreeShellDomProjectionItem[] {
  return items
    .map((item) => ({
      rowId: normalizeString(item.rowId),
      nodeId: normalizeString(item.nodeId),
      parentNodeId: item.parentNodeId ?? null,
      title: normalizeString(item.title, "无标题"),
      depth: typeof item.depth === "number" && Number.isFinite(item.depth) ? Math.max(0, item.depth) : 0,
      childCount:
        typeof item.childCount === "number" && Number.isFinite(item.childCount)
          ? Math.max(0, item.childCount)
          : 0,
      position: typeof item.position === "number" && Number.isFinite(item.position) ? item.position : 0,
      expandedByDefault: item.childCount > 0 ? expanded.has(item.nodeId) : false,
      rowKind: "document",
      iconHint: normalizeString(item.iconHint, "page"),
      capabilities: Array.isArray(item.capabilities)
        ? item.capabilities.map((capability) => normalizeString(capability)).filter(Boolean)
        : [],
      resourceMeta: {
        resourceKind: normalizeString(item.resourceMeta?.resourceKind, "document"),
        documentId: normalizeString(item.resourceMeta?.documentId ?? item.nodeId),
        workspaceId: normalizeString(item.resourceMeta?.workspaceId),
        iconHint: normalizeString(item.resourceMeta?.iconHint, "page"),
      },
    }))
    .filter((item) => Boolean(item.nodeId));
}

export function buildTreeShellDomKernelFileTreeItems(
  items: KernelFileTreeProjectionItem[],
): TreeShellDomProjectionItem[] {
  return items
    .map((item) => ({
      rowId: normalizeString(item.rowId),
      nodeId: normalizeString(item.nodeId),
      parentNodeId: item.parentNodeId ?? null,
      title: normalizeString(item.title, "无标题"),
      depth: typeof item.depth === "number" && Number.isFinite(item.depth) ? Math.max(0, item.depth) : 0,
      childCount:
        typeof item.childCount === "number" && Number.isFinite(item.childCount)
          ? Math.max(0, item.childCount)
          : 0,
      position: typeof item.position === "number" && Number.isFinite(item.position) ? item.position : 0,
      expandedByDefault: item.expandedByDefault === true,
      rowKind: normalizeString(item.rowKind, "document"),
      iconHint: normalizeString(item.iconHint, "page"),
      capabilities: Array.isArray(item.capabilities)
        ? item.capabilities.map((capability) => normalizeString(capability)).filter(Boolean)
        : [],
      resourceMeta: {
        resourceKind: normalizeString(item.resourceMeta?.resourceKind),
        documentId: normalizeString(item.resourceMeta?.documentId),
        assetId: normalizeString(item.resourceMeta?.assetId),
        workspaceId: normalizeString(item.resourceMeta?.workspaceId),
        assetKind: normalizeString(item.resourceMeta?.assetKind),
        iconHint: normalizeString(item.resourceMeta?.iconHint, normalizeString(item.iconHint, "page")),
      },
    }))
    .filter((item) => Boolean(item.nodeId));
}

export function buildTreeShellDomChildrenByParent(items: TreeShellDomProjectionItem[]) {
  const ids = new Set(items.map((item) => item.nodeId));
  const childrenByParent = new Map<string, TreeShellDomProjectionItem[]>();
  for (const item of items) {
    const parentId = item.parentNodeId && ids.has(item.parentNodeId) ? item.parentNodeId : "";
    const bucket = childrenByParent.get(parentId) ?? [];
    bucket.push(item);
    childrenByParent.set(parentId, bucket);
  }
  for (const bucket of childrenByParent.values()) {
    bucket.sort((left, right) => {
      const byPosition = left.position - right.position;
      if (byPosition !== 0) return byPosition;
      return left.title.localeCompare(right.title, "zh-CN");
    });
  }
  return childrenByParent;
}

export function buildTreeShellDomFiletreeSelection(activeDocumentId?: string | null) {
  const documentId = normalizeString(activeDocumentId);
  if (!documentId) {
    return {
      selectedRowIds: [] as string[],
      anchorRowId: null as string | null,
      focusedRowId: null as string | null,
    };
  }
  const indexRowId = `index:${documentId}`;
  return {
    selectedRowIds: [indexRowId],
    anchorRowId: indexRowId,
    focusedRowId: indexRowId,
  };
}
