import path from "node:path";
import fs from "node:fs";
import type { Database as DBType } from "better-sqlite3";

interface ScanStats {
  modules: number;
  symbols: number;
}

/** 递归收集目录下匹配扩展名的所有文件 */
function walkDir(dir: string, exts: string[]): string[] {
  if (!fs.existsSync(dir)) return [];
  const results: string[] = [];
  const stack: string[] = [dir];
  while (stack.length > 0) {
    const current = stack.pop()!;
    let entries: fs.Dirent[];
    try {
      entries = fs.readdirSync(current, { withFileTypes: true });
    } catch {
      continue;
    }
    for (const entry of entries) {
      const fullPath = path.join(current, entry.name);
      if (entry.isDirectory()) {
        if (
          [
            "node_modules",
            "dist",
            ".git",
            "__pycache__",
            ".venv",
            "venv",
          ].includes(entry.name)
        )
          continue;
        stack.push(fullPath);
      } else if (entry.isFile()) {
        const ext = path.extname(entry.name);
        if (exts.includes(ext)) results.push(fullPath);
      }
    }
  }
  return results;
}

// Python 符号正则
const PY_FUNC_RE = /^(?:async\s+)?def\s+(\w+)\s*\(/gm;
const PY_CLASS_RE = /^class\s+(\w+)\s*[\(:]/gm;

export function scanPython(db: DBType, root: string): ScanStats {
  const insertModule = db.prepare(
    "INSERT OR IGNORE INTO modules (name, path, language, service, type) VALUES (?, ?, ?, ?, ?)",
  );
  const insertSymbol = db.prepare(
    "INSERT INTO symbols (module_id, name, kind, language, file_path, line_start, line_end, is_exported) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
  );
  const getModuleId = db.prepare("SELECT id FROM modules WHERE name = ?") as {
    get: (name: string) => { id: number } | undefined;
  };

  let modules = 0;
  let symbols = 0;

  // 扫描 services/* 下有 pyproject.toml 的服务
  const servicesDir = path.join(root, "services");
  if (!fs.existsSync(servicesDir)) return { modules, symbols };

  const entries = fs.readdirSync(servicesDir, { withFileTypes: true });
  for (const entry of entries) {
    if (!entry.isDirectory()) continue;
    const serviceName = entry.name;
    const servicePath = path.join(servicesDir, serviceName);
    const hasPyproject = fs.existsSync(
      path.join(servicePath, "pyproject.toml"),
    );
    if (!hasPyproject) continue;

    insertModule.run(
      serviceName,
      servicePath,
      "python",
      serviceName,
      "service",
    );
    const modRow = getModuleId.get(serviceName);
    if (modRow) {
      modules++;
      // 扫描 .py 文件
      const pyFiles = walkDir(servicePath, [".py"]);
      for (const filePath of pyFiles) {
        let content: string;
        try {
          content = fs.readFileSync(filePath, "utf-8");
        } catch {
          continue;
        }

        // 函数（含 async def）
        let match: RegExpExecArray | null;
        const funcRe = new RegExp(PY_FUNC_RE);
        while ((match = funcRe.exec(content)) !== null) {
          const name = match[1];
          const lineNum = content.slice(0, match.index).split("\n").length;
          // Python 中以 _ 开头的为私有
          const isExported = !name.startsWith("_") ? 1 : 0;
          insertSymbol.run(
            modRow.id,
            name,
            "function",
            "python",
            filePath,
            lineNum,
            lineNum,
            isExported,
          );
          symbols++;
        }

        // 类
        const classRe = new RegExp(PY_CLASS_RE);
        while ((match = classRe.exec(content)) !== null) {
          const name = match[1];
          const lineNum = content.slice(0, match.index).split("\n").length;
          insertSymbol.run(
            modRow.id,
            name,
            "class",
            "python",
            filePath,
            lineNum,
            lineNum,
            1,
          );
          symbols++;
        }
      }
    }
  }

  return { modules, symbols };
}
