import { defineHandler, useConfig } from '@kb-labs/sdk';
import { getGitStatus } from '@kb-labs/commit-core/analyzer';
import { COMMIT_CACHE_PREFIX, resolveCommitConfig } from '@kb-labs/commit-contracts';
import * as path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';

// src/rest/handlers/files-handler.ts
function resolveScopePath(baseCwd, scopeId = "root", scopes) {
  const scopeDef = scopes?.find((s) => s.id === scopeId);
  const relativePath = scopeDef?.path ?? (scopeId === "root" ? "." : scopeId);
  return relativePath === "." ? baseCwd : path.join(baseCwd, relativePath);
}
var execAsync = promisify(exec);
var FILES_CACHE_TTL = 5e3;
var files_handler_default = defineHandler({
  async execute(ctx, input) {
    const scope = input.query?.scope || "root";
    const cacheKey = `${COMMIT_CACHE_PREFIX}files-list:${scope}`;
    const cached = await ctx.platform.cache.get(cacheKey);
    if (cached !== null && cached !== void 0) {
      return cached;
    }
    try {
      const fileConfig = await useConfig();
      const config = resolveCommitConfig(fileConfig ?? {});
      const scopeCwd = resolveScopePath(ctx.cwd, scope, config.scope?.scopes);
      const gitStatus = await getGitStatus(scopeCwd);
      const allFiles = [
        ...gitStatus.staged,
        ...gitStatus.unstaged,
        ...gitStatus.untracked
      ];
      const diffStats = await getDiffStats(scopeCwd, allFiles);
      const rows = [];
      for (const file of gitStatus.staged) {
        const stats = diffStats.get(file) ?? { additions: 0, deletions: 0 };
        const filename = file.split("/").pop() || file;
        rows.push({
          path: file,
          filename,
          status: stats.deletions > 0 && stats.additions === 0 ? "deleted" : "modified",
          additions: stats.additions,
          deletions: stats.deletions,
          changes: `+${stats.additions} -${stats.deletions}`
        });
      }
      for (const file of gitStatus.unstaged) {
        if (!rows.find((r) => r.path === file)) {
          const stats = diffStats.get(file) ?? { additions: 0, deletions: 0 };
          const filename = file.split("/").pop() || file;
          rows.push({
            path: file,
            filename,
            status: "modified",
            additions: stats.additions,
            deletions: stats.deletions,
            changes: `+${stats.additions} -${stats.deletions}`
          });
        }
      }
      for (const file of gitStatus.untracked) {
        const stats = diffStats.get(file) ?? { additions: 0, deletions: 0 };
        const filename = file.split("/").pop() || file;
        rows.push({
          path: file,
          filename,
          status: "added",
          additions: stats.additions,
          deletions: stats.deletions,
          changes: `+${stats.additions}`
        });
      }
      rows.sort((a, b) => a.path.localeCompare(b.path));
      const result = {
        rows,
        total: rows.length
      };
      await ctx.platform.cache.set(cacheKey, result, FILES_CACHE_TTL);
      return result;
    } catch (error) {
      return { rows: [], total: 0 };
    }
  }
});
async function getDiffStats(cwd, files) {
  const stats = /* @__PURE__ */ new Map();
  if (files.length === 0) {
    return stats;
  }
  try {
    const batchSize = 100;
    for (let i = 0; i < files.length; i += batchSize) {
      const batch = files.slice(i, i + batchSize);
      const escapedFiles = batch.map((f) => `"${f.replace(/"/g, '\\"')}"`).join(" ");
      try {
        const { stdout } = await execAsync(`git diff --numstat HEAD -- ${escapedFiles}`, { cwd });
        const lines = stdout.trim().split("\n");
        for (const line of lines) {
          if (!line) {
            continue;
          }
          const parts = line.split("	");
          if (parts.length < 3 || !parts[2]) {
            continue;
          }
          const additions = parseInt(parts[0] || "0", 10);
          const deletions = parseInt(parts[1] || "0", 10);
          const path2 = parts[2];
          stats.set(path2, { additions, deletions });
        }
      } catch {
        for (const file of batch) {
          if (!stats.has(file)) {
            stats.set(file, { additions: 0, deletions: 0 });
          }
        }
      }
    }
    for (const file of files) {
      if (!stats.has(file)) {
        try {
          const safeFile = file.replace(/"/g, '\\"');
          const { stdout: content } = await execAsync(`wc -l "${safeFile}"`, { cwd });
          const match = content.trim().match(/^\s*(\d+)/);
          const lines = match && match[1] ? parseInt(match[1], 10) : 0;
          stats.set(file, { additions: lines, deletions: 0 });
        } catch {
          stats.set(file, { additions: 0, deletions: 0 });
        }
      }
    }
  } catch {
    for (const file of files) {
      stats.set(file, { additions: 0, deletions: 0 });
    }
  }
  return stats;
}

export { files_handler_default as default };
//# sourceMappingURL=files-handler.js.map
//# sourceMappingURL=files-handler.js.map