const fs = require('fs-extra');
const path = require('path');
const { getCadInfo } = require('./router');

const CODE_FOLDER_REGEX = /^\d{3}$/;
const MAX_SCAN_DEPTH = 6;

function toCadKey(cadInfo) {
  return String(cadInfo?.key || '').toLowerCase();
}

async function buildDestinationIndexes(destinationRoot, onProgress) {
  const folderIndex = new Map();
  const cadKeyIndex = new Set();

  if (!destinationRoot || !(await fs.pathExists(destinationRoot))) {
    return { folderIndex, cadKeyIndex };
  }

  let topEntries;
  try {
    topEntries = await fs.readdir(destinationRoot, { withFileTypes: true });
  } catch {
    return { folderIndex, cadKeyIndex };
  }

  const topDirs = topEntries
    .filter((e) => e.isDirectory())
    .map((e) => ({ name: e.name, fullPath: path.join(destinationRoot, e.name) }));

  const total = topDirs.length;
  let completed = 0;
  let scannedFiles = 0;

  for (const entry of topEntries) {
    if (!entry.isFile()) continue;
    const cadInfo = getCadInfo(entry.name);
    if (cadInfo) {
      scannedFiles += 1;
      cadKeyIndex.add(toCadKey(cadInfo));
    }
  }

  async function walkSubtree(dirPath, depth) {
    if (depth > MAX_SCAN_DEPTH) return;

    let entries;
    try {
      entries = await fs.readdir(dirPath, { withFileTypes: true });
    } catch {
      return;
    }

    const subdirPromises = [];

    for (const entry of entries) {
      const fullPath = path.join(dirPath, entry.name);

      if (entry.isDirectory()) {
        if (CODE_FOLDER_REGEX.test(entry.name)) {
          const rows = folderIndex.get(entry.name) || [];
          rows.push(fullPath);
          folderIndex.set(entry.name, rows);
        }
        subdirPromises.push(walkSubtree(fullPath, depth + 1));
      } else if (entry.isFile()) {
        const cadInfo = getCadInfo(entry.name);
        if (cadInfo) {
          scannedFiles += 1;
          onProgress?.({ phase: 'index-dup', scanned: scannedFiles, file: entry.name });
          cadKeyIndex.add(toCadKey(cadInfo));
        }
      }
    }

    await Promise.all(subdirPromises);
  }

  await Promise.all(
    topDirs.map(async ({ name, fullPath }) => {
      onProgress?.({ phase: 'index-dest', current: completed, total, folder: name });

      if (CODE_FOLDER_REGEX.test(name)) {
        const rows = folderIndex.get(name) || [];
        rows.push(fullPath);
        folderIndex.set(name, rows);
      }

      await walkSubtree(fullPath, 1);

      completed += 1;
      onProgress?.({ phase: 'index-dest', current: completed, total, folder: name });
    })
  );

  return { folderIndex, cadKeyIndex };
}

module.exports = { buildDestinationIndexes, toCadKey };
