import type { Requirement, RequirementStatus } from './requirement';

export type RequirementScopeSelection =
  | { type: 'all' }
  | { type: 'product'; productId: string }
  | { type: 'project'; projectId: string };

export interface RequirementScopeCount {
  total: number;
  byStatus: Partial<Record<RequirementStatus, number>>;
}

export interface RequirementProjectScopeNode {
  id: string;
  name: string;
  count: RequirementScopeCount;
}

export interface RequirementProductScopeNode {
  id: string;
  name: string;
  count: RequirementScopeCount;
  projects: RequirementProjectScopeNode[];
}

export function filterRequirementsByScope(
  requirements: Requirement[],
  scope: RequirementScopeSelection,
): Requirement[] {
  if (scope.type === 'product') {
    return requirements.filter((requirement) => requirement.productId === scope.productId);
  }
  if (scope.type === 'project') {
    return requirements.filter((requirement) => requirement.projectId === scope.projectId);
  }
  return requirements;
}

export function buildRequirementScopeTree(
  overview: { id: string; name: string; projects: { id: string; name: string }[] }[],
  requirements: Requirement[],
): RequirementProductScopeNode[] {
  return overview.map((product) => {
    const productRequirements = requirements.filter((requirement) => requirement.productId === product.id);
    return {
      id: product.id,
      name: product.name,
      count: countRequirements(productRequirements),
      projects: product.projects.map((project) => {
        const projectRequirements = requirements.filter((requirement) => requirement.projectId === project.id);
        return {
          id: project.id,
          name: project.name,
          count: countRequirements(projectRequirements),
        };
      }),
    };
  });
}

export function filterRequirementScopeTreeByKeyword(
  tree: RequirementProductScopeNode[],
  keyword: string,
): RequirementProductScopeNode[] {
  const query = normalizeScopeKeyword(keyword);
  if (!query) return tree;

  const filtered: RequirementProductScopeNode[] = [];
  for (const product of tree) {
    if (normalizeScopeKeyword(product.name).includes(query)) {
      filtered.push(product);
      continue;
    }

    const projects = product.projects.filter((project) => normalizeScopeKeyword(project.name).includes(query));
    if (projects.length > 0) {
      filtered.push({ ...product, projects });
    }
  }

  return filtered;
}

function countRequirements(requirements: Requirement[]): RequirementScopeCount {
  const byStatus: Partial<Record<RequirementStatus, number>> = {};
  for (const requirement of requirements) {
    byStatus[requirement.status] = (byStatus[requirement.status] ?? 0) + 1;
  }
  return {
    total: requirements.length,
    byStatus,
  };
}

function normalizeScopeKeyword(value: string): string {
  return value.trim().toLowerCase();
}
