import { BaseVerificationStrategy } from "./base-verification.strategy";
import type { VerificationContext, StrategyResult, VerificationIssue } from "../interfaces";

export class BuildOutputStrategy extends BaseVerificationStrategy {
  name = "build-output";

  verify(context: VerificationContext): Promise<StrategyResult> {
    const issues: VerificationIssue[] = [];

    // If no build output, assume build wasn't run (neutral result)
    if (!context.buildOutput) {
      return Promise.resolve({
        strategyName: this.name,
        passed: true,
        confidence: 50,
        issues: [],
      });
    }

    const { buildOutput } = context;

    // Check for TypeScript errors
    const tsErrorPattern = /error TS\d+:/gi;
    const tsErrors = this.extractEvidence(buildOutput, tsErrorPattern);
    if (tsErrors.length > 0) {
      issues.push({
        type: "build-error",
        severity: "error",
        message: `Found ${tsErrors.length.toString()} TypeScript error(s)`,
        evidence: tsErrors.slice(0, 5).join("\n"), // Limit to first 5
      });
    }

    // Check for ESLint errors
    const eslintErrorPattern = /ESLint.*error/gi;
    const eslintErrors = this.extractEvidence(buildOutput, eslintErrorPattern);
    if (eslintErrors.length > 0) {
      issues.push({
        type: "build-error",
        severity: "error",
        message: `Found ${eslintErrors.length.toString()} ESLint error(s)`,
        evidence: eslintErrors.slice(0, 5).join("\n"),
      });
    }

    // Check for generic build errors
    const buildErrorPattern = /\berror\b.*(?:build|compilation|failed)/gi;
    const buildErrors = this.extractEvidence(buildOutput, buildErrorPattern);
    if (buildErrors.length > 0 && tsErrors.length === 0) {
      // Only add if not already counted as TS errors
      issues.push({
        type: "build-error",
        severity: "error",
        message: `Build errors detected`,
        evidence: buildErrors.slice(0, 5).join("\n"),
      });
    }

    // Check for compilation failure
    const compilationFailedPattern = /compilation failed|build failed/gi;
    if (compilationFailedPattern.test(buildOutput) && issues.length === 0) {
      issues.push({
        type: "build-error",
        severity: "error",
        message: "Compilation failed",
      });
    }

    // Check for warnings
    const warningPattern = /\bwarning\b/gi;
    const warnings = this.extractEvidence(buildOutput, warningPattern);
    if (warnings.length > 0) {
      issues.push({
        type: "build-error",
        severity: "warning",
        message: `Found ${warnings.length.toString()} warning(s)`,
        evidence: warnings.slice(0, 3).join("\n"),
      });
    }

    // Calculate confidence
    let confidence = 100;

    // Count total errors
    const errorCount = tsErrors.length + eslintErrors.length + buildErrors.length;
    if (errorCount > 0) {
      // More aggressive penalty: 30 points per error (3 errors = 10% confidence)
      confidence = Math.max(0, 100 - errorCount * 30);
    }

    // Penalty for warnings
    if (warnings.length > 0) {
      confidence -= Math.min(10, warnings.length * 2);
    }

    confidence = Math.max(0, Math.round(confidence));

    return Promise.resolve({
      strategyName: this.name,
      passed: issues.filter((i) => i.severity === "error").length === 0,
      confidence,
      issues,
    });
  }
}
