import fs from 'fs/promises';
import path from 'path';
import { logger } from '../utils/logger.js';

export interface ChinaRegionOption {
  label: string;
  value: string;
  children?: ChinaRegionOption[];
}

interface CachedRegions {
  mtimeMs: number;
  regions: ChinaRegionOption[];
}

function getServerRootDir(): string {
  return path.basename(process.cwd()).toLowerCase() === 'server'
    ? process.cwd()
    : path.resolve(process.cwd(), 'server');
}

function normalizeCsvCell(value: string): string {
  return String(value || '')
    .replace(/^\uFEFF/, '')
    .trim();
}

export class RegionService {
  private cache: CachedRegions | null = null;

  async getChinaRegionsFromCsv(): Promise<ChinaRegionOption[]> {
    const serverRoot = getServerRootDir();
    const csvPath = path.resolve(serverRoot, '中国地区编码表.csv');

    let stat: { mtimeMs: number } | null = null;
    try {
      stat = await fs.stat(csvPath);
    } catch {
      logger.warn(`[RegionService] csv not found: ${csvPath}`);
      return [];
    }

    if (this.cache && this.cache.mtimeMs === stat.mtimeMs) return this.cache.regions;

    const content = await fs.readFile(csvPath, 'utf-8');
    const lines = content.split(/\r?\n/).filter(Boolean);
    if (lines.length <= 1) return [];

    const provinceMap = new Map<string, ChinaRegionOption>();
    const cityMapByProvince = new Map<string, Map<string, ChinaRegionOption>>();
    const districtMapByCity = new Map<string, Set<string>>();

    for (let i = 1; i < lines.length; i++) {
      const rawLine = lines[i];
      if (!rawLine) continue;
      const parts = rawLine.split(',');
      if (parts.length < 6) continue;

      const provinceName = normalizeCsvCell(parts[0]);
      const provinceCode = normalizeCsvCell(parts[1]);
      const cityName = normalizeCsvCell(parts[2]);
      const cityCode = normalizeCsvCell(parts[3]);
      const districtName = normalizeCsvCell(parts[4]);
      const districtCode = normalizeCsvCell(parts[5]);

      if (!provinceCode || !provinceName) continue;
      if (!cityCode || !cityName) continue;
      if (!districtCode || !districtName) continue;

      let province = provinceMap.get(provinceCode);
      if (!province) {
        province = { label: provinceName, value: provinceCode, children: [] };
        provinceMap.set(provinceCode, province);
        cityMapByProvince.set(provinceCode, new Map());
      }

      const cityMap = cityMapByProvince.get(provinceCode)!;
      let city = cityMap.get(cityCode);
      if (!city) {
        city = { label: cityName, value: cityCode, children: [] };
        cityMap.set(cityCode, city);
        province.children!.push(city);
      }

      const districtKey = `${cityCode}:${districtCode}`;
      if (!districtMapByCity.has(cityCode)) districtMapByCity.set(cityCode, new Set());
      const districtSet = districtMapByCity.get(cityCode)!;
      if (districtSet.has(districtKey)) continue;
      districtSet.add(districtKey);

      city.children!.push({ label: districtName, value: districtCode });
    }

    const regions = Array.from(provinceMap.values())
      .sort((a, b) => Number(a.value) - Number(b.value))
      .map(p => ({
        ...p,
        children: (p.children || [])
          .slice()
          .sort((a, b) => Number(a.value) - Number(b.value))
          .map(c => ({
            ...c,
            children: (c.children || []).slice().sort((a, b) => Number(a.value) - Number(b.value)),
          })),
      }));

    this.cache = { mtimeMs: stat.mtimeMs, regions };
    return regions;
  }
}
