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

export class TestOutputStrategy extends BaseVerificationStrategy {
  name = "test-output";
  private readonly COVERAGE_THRESHOLD = 85;

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

    // If no test results, assume tests weren't run (neutral result)
    if (!context.testResults) {
      return Promise.resolve({
        strategyName: this.name,
        passed: true,
        confidence: 50,
        issues: [],
      });
    }

    const { testResults } = context;

    // Check for failed tests
    if (testResults.failed > 0) {
      issues.push({
        type: "test-failure",
        severity: "error",
        message: `${testResults.failed.toString()} test(s) failed out of ${testResults.total.toString()}`,
      });
    }

    // Check for skipped tests
    if (testResults.skipped > 0) {
      issues.push({
        type: "test-failure",
        severity: "warning",
        message: `${testResults.skipped.toString()} test(s) skipped`,
      });
    }

    // Check coverage threshold
    if (testResults.coverage !== undefined && testResults.coverage < this.COVERAGE_THRESHOLD) {
      issues.push({
        type: "low-coverage",
        severity: "error",
        message: `Code coverage ${testResults.coverage.toString()}% is below threshold of ${this.COVERAGE_THRESHOLD.toString()}%`,
      });
    }

    // Calculate confidence based on test results
    let confidence = 100;

    // Reduce confidence based on failure rate (use minimum, not average)
    if (testResults.total > 0) {
      const passRate = (testResults.passed / testResults.total) * 100;
      confidence = Math.min(confidence, passRate);
    }

    // Further reduce for coverage (use minimum of pass rate and coverage)
    if (testResults.coverage !== undefined) {
      confidence = Math.min(confidence, testResults.coverage);
    }

    // Additional penalty for failures (more aggressive)
    if (testResults.failed > 0) {
      const failurePenalty = (testResults.failed / testResults.total) * 30;
      confidence -= failurePenalty;
    }

    // Penalty for skipped tests
    if (testResults.skipped > 0) {
      const skipPenalty = (testResults.skipped / testResults.total) * 20;
      confidence -= skipPenalty;
    }

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

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