import { Injectable } from "@nestjs/common";
import {
  VerificationContext,
  VerificationResult,
  VerificationIssue,
  StrategyResult,
} from "./interfaces";
import {
  BaseVerificationStrategy,
  FileChangeStrategy,
  TestOutputStrategy,
  BuildOutputStrategy,
} from "./strategies";

@Injectable()
export class CompletionVerificationService {
  private strategies: BaseVerificationStrategy[] = [];

  constructor() {
    this.registerDefaultStrategies();
  }

  private registerDefaultStrategies(): void {
    this.strategies.push(new FileChangeStrategy());
    this.strategies.push(new TestOutputStrategy());
    this.strategies.push(new BuildOutputStrategy());
  }

  async verify(context: VerificationContext): Promise<VerificationResult> {
    // Run all strategies in parallel
    const strategyResults = await Promise.all(
      this.strategies.map((strategy) => strategy.verify(context))
    );

    // Detect deferred work in claim message
    const deferredWorkIssues = this.detectDeferredWork(context.claimMessage);

    // Aggregate all issues
    const allIssues = [
      ...strategyResults.flatMap((result) => result.issues),
      ...deferredWorkIssues,
    ];

    // Calculate overall confidence
    const confidence = this.calculateConfidence(strategyResults);

    // Determine verdict
    const hasErrors = allIssues.some((issue) => issue.severity === "error");
    const hasWarnings = allIssues.some((issue) => issue.severity === "warning");

    let verdict: "complete" | "incomplete" | "needs-review";
    if (hasErrors) {
      verdict = "incomplete";
    } else if (hasWarnings || (confidence >= 60 && confidence < 80)) {
      verdict = "needs-review";
    } else {
      verdict = "complete";
    }

    // Generate suggestions
    const suggestions = this.generateSuggestions(allIssues);

    return {
      isComplete: verdict === "complete",
      confidence,
      issues: allIssues,
      suggestions,
      verdict,
    };
  }

  registerStrategy(strategy: BaseVerificationStrategy): void {
    this.strategies.push(strategy);
  }

  detectDeferredWork(claimMessage: string): VerificationIssue[] {
    const issues: VerificationIssue[] = [];

    const deferredPatterns = [
      /follow-up/gi,
      /to\s+be\s+added\s+later/gi,
      /incremental\s+improvement/gi,
      /future\s+enhancement/gi,
      /TODO:.{0,100}complete/gi,
      /placeholder\s+implementation/gi,
      /\bstub\b/gi,
      /will\s+(?:add|complete|finish|implement).{0,100}later/gi,
      /partially?\s+(?:implemented|complete)/gi,
      /work\s+in\s+progress/gi,
    ];

    for (const pattern of deferredPatterns) {
      const matches = claimMessage.match(pattern);
      if (matches && matches.length > 0) {
        issues.push({
          type: "deferred-work",
          severity: "warning",
          message: "Claim message indicates deferred work",
          evidence: matches.join(", "),
        });
        break; // Only report once
      }
    }

    return issues;
  }

  calculateConfidence(results: StrategyResult[]): number {
    if (results.length === 0) {
      return 0;
    }

    const totalConfidence = results.reduce((sum, result) => sum + result.confidence, 0);
    return Math.round(totalConfidence / results.length);
  }

  generateSuggestions(issues: VerificationIssue[]): string[] {
    const suggestions: string[] = [];
    const issueTypes = new Set(issues.map((i) => i.type));

    if (issueTypes.has("test-failure")) {
      suggestions.push("Fix all failing tests before marking task complete");
    }

    if (issueTypes.has("build-error")) {
      suggestions.push("Resolve all build errors and type-check issues");
    }

    if (issueTypes.has("low-coverage")) {
      suggestions.push("Increase test coverage to meet the 85% threshold");
    }

    if (issueTypes.has("missing-files")) {
      suggestions.push("Ensure all necessary files have been modified");
    }

    if (issueTypes.has("incomplete-implementation")) {
      suggestions.push("Remove TODO/FIXME comments and complete placeholder implementations");
    }

    if (issueTypes.has("deferred-work")) {
      suggestions.push("Complete all deferred work or create separate tasks for follow-up items");
    }

    return suggestions;
  }
}
