import taxonomyData from "../data/categoryTaxonomyV1.json";

export type TaxonomyCategoryType = "expense" | "income" | "transfer";

export interface TaxonomyNode {
  id: number;
  name: string;
  i18n_key: string;
  type: TaxonomyCategoryType;
  color: string;
  sort_order: number;
  children: TaxonomyNode[];
}

export type TaxonomyLeaf = TaxonomyNode & { children: [] };

export type TaxonomyRoot = TaxonomyNode;

export interface Taxonomy {
  version: string;
  description: string;
  roots: TaxonomyRoot[];
}

let cached: Taxonomy | null = null;

function loadTaxonomy(): Taxonomy {
  if (cached !== null) return cached;
  cached = taxonomyData as Taxonomy;
  return cached;
}

export function getTaxonomyV1(): Taxonomy {
  return loadTaxonomy();
}

export function findById(id: number): TaxonomyNode | null {
  const stack: TaxonomyNode[] = [...loadTaxonomy().roots];
  while (stack.length > 0) {
    const node = stack.pop() as TaxonomyNode;
    if (node.id === id) return node;
    stack.push(...node.children);
  }
  return null;
}

export function findByPath(path: string[]): TaxonomyNode | null {
  if (path.length === 0) return null;
  const { roots } = loadTaxonomy();
  let current: TaxonomyNode | undefined = roots.find((r) => r.name === path[0]);
  for (let i = 1; i < path.length && current !== undefined; i++) {
    current = current.children.find((c) => c.name === path[i]);
  }
  return current ?? null;
}

export function getLeaves(): TaxonomyLeaf[] {
  const leaves: TaxonomyLeaf[] = [];
  const walk = (node: TaxonomyNode): void => {
    if (node.children.length === 0) {
      leaves.push(node as TaxonomyLeaf);
      return;
    }
    for (const child of node.children) walk(child);
  };
  for (const root of loadTaxonomy().roots) walk(root);
  return leaves;
}

export function getParentById(id: number): TaxonomyNode | null {
  const visit = (node: TaxonomyNode): TaxonomyNode | null => {
    for (const child of node.children) {
      if (child.id === id) return node;
      const deeper = visit(child);
      if (deeper !== null) return deeper;
    }
    return null;
  };
  for (const root of loadTaxonomy().roots) {
    const result = visit(root);
    if (result !== null) return result;
  }
  return null;
}

export function resetTaxonomyCache(): void {
  cached = null;
}
