import type { Priority, VersionWithContext } from './derive';

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

export interface VersionProjectNode {
  projectId: string;
  projectName: string;
  count: number;
}

export interface VersionProductNode {
  productId: string;
  productName: string;
  count: number;
  projects: VersionProjectNode[];
}

export interface VersionListFilter {
  scope: VersionListScope;
  keyword: string;
  priority: Priority | 'all';
}

function matchesKeyword(values: Array<string | undefined | null>, keyword: string): boolean {
  const normalized = keyword.trim().toLowerCase();
  if (!normalized) return true;
  return values.some((value) => value?.toLowerCase().includes(normalized));
}

export function buildVersionScopeTree(versions: VersionWithContext[], keyword: string): VersionProductNode[] {
  const normalized = keyword.trim().toLowerCase();
  const productMap = new Map<string, {
    productId: string;
    productName: string;
    projects: Map<string, VersionProjectNode>;
  }>();

  for (const version of versions) {
    const productMatches = matchesKeyword([version.productName], normalized);
    const projectMatches = matchesKeyword([version.projectName], normalized);
    const versionMatches = matchesKeyword([version.name], normalized);
    if (normalized && !productMatches && !projectMatches && !versionMatches) continue;

    let product = productMap.get(version.productId);
    if (!product) {
      product = {
        productId: version.productId,
        productName: version.productName,
        projects: new Map(),
      };
      productMap.set(version.productId, product);
    }

    const project = product.projects.get(version.projectId) ?? {
      projectId: version.projectId,
      projectName: version.projectName,
      count: 0,
    };
    project.count += 1;
    product.projects.set(version.projectId, project);
  }

  return Array.from(productMap.values()).map((product) => {
    const projects = Array.from(product.projects.values()).sort((a, b) => a.projectName.localeCompare(b.projectName, 'zh-Hans-CN'));
    return {
      productId: product.productId,
      productName: product.productName,
      count: projects.reduce((sum, project) => sum + project.count, 0),
      projects,
    };
  }).sort((a, b) => a.productName.localeCompare(b.productName, 'zh-Hans-CN'));
}

export function filterVersionsForList(versions: VersionWithContext[], filter: VersionListFilter): VersionWithContext[] {
  const filtered = versions.filter((version) => {
    if (filter.scope.type === 'product' && version.productId !== filter.scope.productId) return false;
    if (filter.scope.type === 'project' && version.projectId !== filter.scope.projectId) return false;
    if (filter.priority !== 'all' && (version.priority ?? 'P2') !== filter.priority) return false;
    return matchesKeyword([version.name], filter.keyword);
  });

  return filtered;
}
