import { SAFETY } from "@/core/constants.js";
import type { SafetyReport } from "@/types/index.js";

interface DiffFileEntry {
  path: string;
  linesAdded: number;
  linesRemoved: number;
  isDeleted: boolean;
}

export function validateDiff(rawDiff: string): SafetyReport {
  const files = parseDiffFiles(rawDiff);
  const violations: string[] = [];

  const totalLinesChanged = files.reduce((sum, f) => sum + f.linesAdded + f.linesRemoved, 0);

  const filesDeleted = files.filter((f) => f.isDeleted).length;
  const filesChanged = files.length;

  if (totalLinesChanged > SAFETY.MAX_DIFF_LINES) {
    violations.push(`Diff exceeds ${SAFETY.MAX_DIFF_LINES} lines (${totalLinesChanged} changed)`);
  }

  if (filesChanged > SAFETY.MAX_FILES_CHANGED) {
    violations.push(`More than ${SAFETY.MAX_FILES_CHANGED} files changed (${filesChanged})`);
  }

  if (filesDeleted > SAFETY.MAX_FILES_DELETED) {
    violations.push(`More than ${SAFETY.MAX_FILES_DELETED} files deleted (${filesDeleted})`);
  }

  for (const file of files) {
    for (const forbidden of SAFETY.FORBIDDEN_PATHS) {
      if (file.path.includes(forbidden)) {
        violations.push(`Modifies forbidden path: ${file.path}`);
      }
    }

    for (const lockFile of SAFETY.LOCK_FILES) {
      if (file.path.endsWith(lockFile)) {
        violations.push(`Modifies lock file: ${file.path}`);
      }
    }
  }

  return {
    passed: violations.length === 0,
    totalLinesChanged,
    filesChanged,
    filesDeleted,
    violations,
  };
}

function parseDiffFiles(rawDiff: string): DiffFileEntry[] {
  const files: DiffFileEntry[] = [];
  const diffSections = rawDiff.split(/^diff --git /m).filter(Boolean);

  for (const section of diffSections) {
    const pathMatch = section.match(/a\/(.+?) b\//);
    if (!pathMatch?.[1]) continue;

    const path = pathMatch[1];
    const isDeleted = section.includes("deleted file mode");

    let linesAdded = 0;
    let linesRemoved = 0;

    const lines = section.split("\n");
    let inHunk = false;

    for (const line of lines) {
      if (line.startsWith("@@")) {
        inHunk = true;
        continue;
      }
      if (!inHunk) continue;

      if (line.startsWith("+") && !line.startsWith("+++")) {
        linesAdded++;
      } else if (line.startsWith("-") && !line.startsWith("---")) {
        linesRemoved++;
      }
    }

    files.push({ path, linesAdded, linesRemoved, isDeleted });
  }

  return files;
}
