import { RequirementItem, RequirementType } from "@/lib/document-mock";

export interface SectionTreeNode {
  key: string;
  sectionNumber: string;
  sectionTitle: string;
  level: number;
  requirements: RequirementItem[];
  children: SectionTreeNode[];
}

const TYPE_LABEL: Record<RequirementType, string> = {
  functional: "功能需求",
  interface: "接口需求",
  performance: "性能需求",
  security: "安全需求",
  reliability: "可靠性需求",
  other: "其他需求",
};

const LABEL_TYPE: Record<string, RequirementType> = Object.entries(TYPE_LABEL).reduce(
  (acc, [type, label]) => {
    acc[label] = type as RequirementType;
    return acc;
  },
  {} as Record<string, RequirementType>
);

const asRequirementType = (value: unknown): RequirementType => {
  if (
    value === "functional" ||
    value === "interface" ||
    value === "performance" ||
    value === "security" ||
    value === "reliability" ||
    value === "other"
  ) {
    return value;
  }
  if (typeof value === "string" && LABEL_TYPE[value]) {
    return LABEL_TYPE[value];
  }
  return "functional";
};

const sectionKey = (number?: string, title?: string) =>
  `${(number || "").trim()}__${(title || "").trim()}`;

const normalizeSectionNumber = (value?: string) =>
  (value || "").replace(/\s+/g, "").trim();

const parseSectionParts = (value?: string): number[] | null => {
  const normalized = normalizeSectionNumber(value);
  if (!normalized || !/^\d+(?:\.\d+)*$/.test(normalized)) {
    return null;
  }
  return normalized.split(".").map((part) => Number(part));
};

const compareSectionNumbers = (left?: string, right?: string) => {
  const leftParts = parseSectionParts(left);
  const rightParts = parseSectionParts(right);

  if (leftParts && rightParts) {
    const len = Math.max(leftParts.length, rightParts.length);
    for (let index = 0; index < len; index += 1) {
      const a = leftParts[index];
      const b = rightParts[index];
      if (a === undefined) {
        return -1;
      }
      if (b === undefined) {
        return 1;
      }
      if (a !== b) {
        return a - b;
      }
    }
    return 0;
  }

  if (leftParts) {
    return -1;
  }
  if (rightParts) {
    return 1;
  }

  return (left || "").localeCompare(right || "", "zh-CN", { numeric: true });
};

const compareSectionNodes = (left: SectionTreeNode, right: SectionTreeNode) => {
  const byNumber = compareSectionNumbers(left.sectionNumber, right.sectionNumber);
  if (byNumber !== 0) {
    return byNumber;
  }

  return left.sectionTitle.localeCompare(right.sectionTitle, "zh-CN", {
    numeric: true,
  });
};

const sortRequirements = (requirements: RequirementItem[]) => {
  return [...requirements].sort((left, right) => {
    const leftOrder = typeof left.sortOrder === "number" ? left.sortOrder : Number.MAX_SAFE_INTEGER;
    const rightOrder = typeof right.sortOrder === "number" ? right.sortOrder : Number.MAX_SAFE_INTEGER;
    if (leftOrder !== rightOrder) {
      return leftOrder - rightOrder;
    }
    return left.id.localeCompare(right.id, "zh-CN", { numeric: true });
  });
};

const sortSectionTree = (nodes: SectionTreeNode[]): SectionTreeNode[] => {
  return [...nodes]
    .map((node) => ({
      ...node,
      requirements: sortRequirements(node.requirements),
      children: sortSectionTree(node.children),
    }))
    .sort(compareSectionNodes);
};

const flattenSectionTree = (nodes: SectionTreeNode[]): SectionTreeNode[] => {
  const result: SectionTreeNode[] = [];
  const walk = (node: SectionTreeNode) => {
    result.push(node);
    node.children.forEach((child) => walk(child));
  };
  nodes.forEach((node) => walk(node));
  return result;
};

const buildSectionTreeWithParents = (sourceNodes: SectionTreeNode[]): SectionTreeNode[] => {
  const numbered = new Map<string, SectionTreeNode>();
  const fallbackNodes: SectionTreeNode[] = [];
  const flattened = flattenSectionTree(sourceNodes);

  flattened.forEach((source) => {
    const sectionNumber = normalizeSectionNumber(source.sectionNumber);
    const normalized: SectionTreeNode = {
      ...source,
      sectionNumber,
      requirements: sortRequirements(source.requirements),
      children: [],
    };

    const numberParts = parseSectionParts(sectionNumber);
    if (!numberParts) {
      fallbackNodes.push(normalized);
      return;
    }

    const existing = numbered.get(sectionNumber);
    if (!existing) {
      numbered.set(sectionNumber, normalized);
      return;
    }

    existing.requirements = sortRequirements([...existing.requirements, ...normalized.requirements]);
    if (!existing.sectionTitle && normalized.sectionTitle) {
      existing.sectionTitle = normalized.sectionTitle;
    }
    if (existing.sectionTitle === "未归类章节" && normalized.sectionTitle) {
      existing.sectionTitle = normalized.sectionTitle;
    }
  });

  Array.from(numbered.keys()).forEach((number) => {
    const parts = parseSectionParts(number);
    if (!parts || parts.length <= 1) {
      return;
    }

    for (let index = 1; index < parts.length; index += 1) {
      const parentNumber = parts.slice(0, index).join(".");
      if (numbered.has(parentNumber)) {
        continue;
      }

      numbered.set(parentNumber, {
        key: `synthetic-${parentNumber}`,
        sectionNumber: parentNumber,
        sectionTitle: "",
        level: index,
        requirements: [],
        children: [],
      });
    }
  });

  const roots: SectionTreeNode[] = [];
  const sortedNumbers = Array.from(numbered.keys()).sort(compareSectionNumbers);
  sortedNumbers.forEach((number) => {
    const node = numbered.get(number);
    if (!node) {
      return;
    }

    const parts = parseSectionParts(number);
    node.level = parts ? parts.length : node.level;
    if (!parts || parts.length <= 1) {
      roots.push(node);
      return;
    }

    const parentNumber = parts.slice(0, -1).join(".");
    const parent = numbered.get(parentNumber);
    if (!parent) {
      roots.push(node);
      return;
    }
    parent.children.push(node);
  });

  const sortedRoots = sortSectionTree(roots);
  const sortedFallback = sortSectionTree(fallbackNodes);
  return [...sortedRoots, ...sortedFallback];
};

const deepClone = (value: Record<string, unknown>) =>
  JSON.parse(JSON.stringify(value)) as Record<string, unknown>;

const toRawRequirement = (item: RequirementItem): Record<string, unknown> => {
  const reqType = asRequirementType(item.requirementType);
  const raw: Record<string, unknown> = {
    需求类型: TYPE_LABEL[reqType],
    需求编号: item.id,
    需求描述: item.description,
    优先级: item.priority || "中",
  };

  if (reqType === "interface") {
    raw["接口名称"] = item.interfaceName || "";
    raw["接口类型"] = item.interfaceType || "";
    raw["数据来源"] = item.dataSource || "";
    raw["数据目的地"] = item.dataDestination || "";
  }

  return raw;
};

const groupRequirementsBySection = (requirements: RequirementItem[]) => {
  const grouped = new Map<string, RequirementItem[]>();
  requirements.forEach((item) => {
    const key = sectionKey(item.sectionNumber, item.sectionTitle);
    const list = grouped.get(key) || [];
    list.push(item);
    grouped.set(key, list);
  });

  for (const value of grouped.values()) {
    value.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0));
  }

  return grouped;
};

const rewriteContentRequirements = (
  content: Record<string, unknown>,
  grouped: Map<string, RequirementItem[]>
) => {
  Object.values(content).forEach((section) => {
    if (!section || typeof section !== "object") {
      return;
    }

    const sectionNode = section as Record<string, unknown>;
    const sectionInfo =
      sectionNode["章节信息"] && typeof sectionNode["章节信息"] === "object"
        ? (sectionNode["章节信息"] as Record<string, unknown>)
        : {};
    const key = sectionKey(
      typeof sectionInfo["章节编号"] === "string" ? sectionInfo["章节编号"] : "",
      typeof sectionInfo["章节标题"] === "string" ? sectionInfo["章节标题"] : ""
    );

    const sectionReqs = grouped.get(key);
    if (sectionReqs) {
      sectionNode["需求列表"] = sectionReqs.map((item) => toRawRequirement(item));
      grouped.delete(key);
    } else if (Array.isArray(sectionNode["需求列表"])) {
      sectionNode["需求列表"] = [];
    }

    const children =
      sectionNode["子章节"] && typeof sectionNode["子章节"] === "object"
        ? (sectionNode["子章节"] as Record<string, unknown>)
        : null;
    if (children) {
      rewriteContentRequirements(children, grouped);
    }
  });
};

const appendUnmatched = (
  content: Record<string, unknown>,
  grouped: Map<string, RequirementItem[]>
) => {
  if (grouped.size === 0) {
    return;
  }

  let orphan = content["未归类章节"];
  if (!orphan || typeof orphan !== "object") {
    orphan = {
      章节信息: {
        章节编号: "",
        章节标题: "未归类章节",
        章节级别: 1,
      },
      需求列表: [],
    };
    content["未归类章节"] = orphan;
  }

  const orphanNode = orphan as Record<string, unknown>;
  const orphanReqs = Array.isArray(orphanNode["需求列表"])
    ? (orphanNode["需求列表"] as Array<Record<string, unknown>>)
    : [];

  grouped.forEach((items) => {
    items.forEach((item) => orphanReqs.push(toRawRequirement(item)));
  });
  orphanNode["需求列表"] = orphanReqs;
};

const buildFlatRawOutput = (
  requirements: RequirementItem[],
  documentName: string
): Record<string, unknown> => {
  const grouped = groupRequirementsBySection(requirements);
  const content: Record<string, unknown> = {};

  grouped.forEach((items, key) => {
    const [number = "", title = "未归类章节"] = key.split("__");
    const display = `${number} ${title}`.trim() || "未归类章节";
    content[display] = {
      章节信息: {
        章节编号: number,
        章节标题: title || "未归类章节",
        章节级别: number ? number.split(".").length : 1,
      },
      需求列表: items.map((item) => toRawRequirement(item)),
    };
  });

  return {
    文档元数据: {
      标题: documentName,
      生成时间: new Date().toISOString(),
      总需求数: requirements.length,
      需求类型统计: {},
    },
    需求内容: content,
  };
};

const refreshMetadata = (
  rawOutput: Record<string, unknown>,
  requirements: RequirementItem[],
  documentName: string
) => {
  const metadata =
    rawOutput["文档元数据"] && typeof rawOutput["文档元数据"] === "object"
      ? (rawOutput["文档元数据"] as Record<string, unknown>)
      : {};

  const typeStats: Record<string, number> = {};
  requirements.forEach((item) => {
    const reqType = asRequirementType(item.requirementType);
    const label = TYPE_LABEL[reqType] || "功能需求";
    typeStats[label] = (typeStats[label] || 0) + 1;
  });

  metadata["标题"] = documentName;
  metadata["生成时间"] = new Date().toISOString();
  metadata["总需求数"] = requirements.length;
  metadata["需求类型统计"] = typeStats;
  rawOutput["文档元数据"] = metadata;
};

const toFallbackRequirement = (
  req: Record<string, unknown>,
  sectionNumber: string,
  sectionTitle: string,
  order: number
): RequirementItem => {
  const requirementType = asRequirementType(req["需求类型"]);
  const description = typeof req["需求描述"] === "string" ? req["需求描述"] : "";
  return {
    id:
      typeof req["需求编号"] === "string" && req["需求编号"].trim().length > 0
        ? req["需求编号"]
        : `REQ-${String(order + 1).padStart(3, "0")}`,
    description,
    priority:
      req["优先级"] === "高" || req["优先级"] === "中" || req["优先级"] === "低"
        ? req["优先级"]
        : "中",
    acceptanceCriteria: description ? [description] : ["待补充验收标准"],
    sourceField: `${sectionNumber} ${sectionTitle}`.trim() || "文档解析",
    sectionNumber,
    sectionTitle,
    requirementType,
    interfaceName: typeof req["接口名称"] === "string" ? req["接口名称"] : "",
    interfaceType: typeof req["接口类型"] === "string" ? req["接口类型"] : "",
    dataSource: typeof req["数据来源"] === "string" ? req["数据来源"] : "",
    dataDestination: typeof req["数据目的地"] === "string" ? req["数据目的地"] : "",
    sortOrder: order,
  };
};

export const rebuildRawOutput = (
  rawOutput: Record<string, unknown> | undefined,
  requirements: RequirementItem[],
  documentName: string
): Record<string, unknown> => {
  if (!rawOutput || typeof rawOutput !== "object") {
    const fallback = buildFlatRawOutput(requirements, documentName);
    refreshMetadata(fallback, requirements, documentName);
    return fallback;
  }

  const cloned = deepClone(rawOutput);
  const content =
    cloned["需求内容"] && typeof cloned["需求内容"] === "object"
      ? (cloned["需求内容"] as Record<string, unknown>)
      : null;

  if (!content) {
    const fallback = buildFlatRawOutput(requirements, documentName);
    refreshMetadata(fallback, requirements, documentName);
    return fallback;
  }

  const grouped = groupRequirementsBySection(requirements);
  rewriteContentRequirements(content, grouped);
  appendUnmatched(content, grouped);
  refreshMetadata(cloned, requirements, documentName);
  return cloned;
};

export const buildSectionTree = (
  rawOutput: Record<string, unknown> | undefined,
  requirements: RequirementItem[]
): SectionTreeNode[] => {
  const byId = new Map(requirements.map((item) => [item.id, item]));

  const content =
    rawOutput && rawOutput["需求内容"] && typeof rawOutput["需求内容"] === "object"
      ? (rawOutput["需求内容"] as Record<string, unknown>)
      : null;

  if (!content) {
    const grouped = groupRequirementsBySection(requirements);
    const nodes = Array.from(grouped.entries()).map(([key, items], index) => {
      const [sectionNumber = "", sectionTitle = "未归类章节"] = key.split("__");
      return {
        key: `${sectionNumber || "root"}-${index}`,
        sectionNumber,
        sectionTitle,
        level: sectionNumber ? sectionNumber.split(".").length : 1,
        requirements: items,
        children: [],
      };
    });
    return buildSectionTreeWithParents(nodes);
  }

  let fallbackOrder = 0;

  const walk = (node: unknown, path: string): SectionTreeNode | null => {
    if (!node || typeof node !== "object") {
      return null;
    }

    const sectionNode = node as Record<string, unknown>;
    const sectionInfo =
      sectionNode["章节信息"] && typeof sectionNode["章节信息"] === "object"
        ? (sectionNode["章节信息"] as Record<string, unknown>)
        : {};

    const sectionNumber =
      typeof sectionInfo["章节编号"] === "string"
        ? normalizeSectionNumber(sectionInfo["章节编号"])
        : "";
    const sectionTitle =
      typeof sectionInfo["章节标题"] === "string"
        ? sectionInfo["章节标题"]
        : "未归类章节";
    const level =
      typeof sectionInfo["章节级别"] === "number"
        ? sectionInfo["章节级别"]
        : sectionNumber
        ? sectionNumber.split(".").length
        : 1;

    const reqList = Array.isArray(sectionNode["需求列表"])
      ? (sectionNode["需求列表"] as Array<Record<string, unknown>>)
      : [];

    const mappedRequirements = reqList.map((req) => {
      const reqId = typeof req["需求编号"] === "string" ? req["需求编号"] : "";
      const current = byId.get(reqId);
      if (current) {
        return current;
      }
      const fallback = toFallbackRequirement(req, sectionNumber, sectionTitle, fallbackOrder);
      fallbackOrder += 1;
      return fallback;
    });

    const childrenRoot =
      sectionNode["子章节"] && typeof sectionNode["子章节"] === "object"
        ? (sectionNode["子章节"] as Record<string, unknown>)
        : null;
    const children = childrenRoot
      ? Object.entries(childrenRoot)
          .map(([name, child]) => walk(child, `${path}/${name}`))
          .filter((child): child is SectionTreeNode => Boolean(child))
      : [];

    if (mappedRequirements.length === 0 && children.length === 0) {
      return null;
    }

    return {
      key: `${path}/${sectionNumber}-${sectionTitle}`,
      sectionNumber,
      sectionTitle,
      level,
      requirements: mappedRequirements,
      children,
    };
  };

  const rawNodes = Object.entries(content)
    .map(([name, node]) => walk(node, name))
    .filter((node): node is SectionTreeNode => Boolean(node));

  return buildSectionTreeWithParents(rawNodes);
};
