import { Injectable, Logger } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import {
  CoordinatorClientService,
  QualityCheckRequest,
  QualityCheckResponse,
} from "./coordinator-client.service";
import { GateRequirements } from "./types/gate-config.types";

/**
 * Parameters for pre-commit quality check
 */
export interface PreCommitCheckParams {
  taskId: string;
  agentId: string;
  files: string[];
  diffSummary: string;
}

/**
 * Parameters for post-commit quality check
 */
export interface PostCommitCheckParams {
  taskId: string;
  agentId: string;
  files: string[];
  diffSummary: string;
}

/**
 * Result from quality gate check
 */
export interface QualityGateResult {
  approved: boolean;
  gate: string;
  message?: string;
  details?: Record<string, unknown>;
}

/**
 * Service for running quality gate checks via coordinator
 *
 * Pre-commit gates: Fast checks before git commit
 * - Type checking
 * - Linting
 * - Unit tests
 *
 * Post-commit gates: Comprehensive checks before git push
 * - Code coverage
 * - Build verification
 * - Integration tests
 * - AI reviewer confirmation (optional)
 */
@Injectable()
export class QualityGatesService {
  private readonly logger = new Logger(QualityGatesService.name);

  constructor(
    private readonly coordinatorClient: CoordinatorClientService,
    private readonly configService: ConfigService
  ) {}

  /**
   * Run pre-commit quality checks
   *
   * Pre-commit gates are fast checks that run before git commit:
   * - TypeScript type checking
   * - ESLint linting
   * - Unit tests (fast)
   *
   * If any gate fails, the commit is blocked and detailed errors are returned.
   *
   * YOLO mode: If enabled, skips all quality gates and returns approved result.
   *
   * Gate configuration: If provided, specifies which gates to run and their thresholds.
   *
   * @param params Pre-commit check parameters
   * @param gateRequirements Optional gate requirements for task-specific configuration
   * @returns Quality gate result with approval status and details
   * @throws Error if coordinator is unavailable or returns invalid response
   */
  async preCommitCheck(
    params: PreCommitCheckParams,
    gateRequirements?: GateRequirements
  ): Promise<QualityGateResult> {
    this.logger.debug(
      `Running pre-commit checks for task ${params.taskId} (${params.files.length.toString()} files)` +
        (gateRequirements ? ` with ${String(gateRequirements.metadata?.profile)} profile` : "")
    );

    // YOLO mode: Skip quality gates
    if (this.isYoloModeEnabled()) {
      return this.bypassQualityGates("pre-commit", params);
    }

    const request: QualityCheckRequest = {
      taskId: params.taskId,
      agentId: params.agentId,
      files: params.files,
      diffSummary: params.diffSummary,
      ...(gateRequirements && { gateRequirements }),
    };

    try {
      const response = await this.coordinatorClient.checkQuality(request);

      this.logger.log(
        `Pre-commit check ${response.approved ? "passed" : "failed"} for task ${params.taskId}` +
          (response.message ? `: ${response.message}` : "")
      );

      return this.mapResponse(response);
    } catch (error) {
      this.logger.error(
        `Pre-commit check failed for task ${params.taskId}: ${error instanceof Error ? error.message : String(error)}`
      );
      throw error;
    }
  }

  /**
   * Run post-commit quality checks
   *
   * Post-commit gates are comprehensive checks that run before git push:
   * - Code coverage (>= 85%)
   * - Build verification (tsup)
   * - Integration tests
   * - AI reviewer confirmation (optional)
   *
   * If any gate fails, the push is blocked and detailed errors are returned.
   *
   * YOLO mode: If enabled, skips all quality gates and returns approved result.
   *
   * Gate configuration: If provided, specifies which gates to run and their thresholds.
   *
   * @param params Post-commit check parameters
   * @param gateRequirements Optional gate requirements for task-specific configuration
   * @returns Quality gate result with approval status and details
   * @throws Error if coordinator is unavailable or returns invalid response
   */
  async postCommitCheck(
    params: PostCommitCheckParams,
    gateRequirements?: GateRequirements
  ): Promise<QualityGateResult> {
    this.logger.debug(
      `Running post-commit checks for task ${params.taskId} (${params.files.length.toString()} files)` +
        (gateRequirements ? ` with ${String(gateRequirements.metadata?.profile)} profile` : "")
    );

    // YOLO mode: Skip quality gates
    if (this.isYoloModeEnabled()) {
      return this.bypassQualityGates("post-commit", params);
    }

    const request: QualityCheckRequest = {
      taskId: params.taskId,
      agentId: params.agentId,
      files: params.files,
      diffSummary: params.diffSummary,
      ...(gateRequirements && { gateRequirements }),
    };

    try {
      const response = await this.coordinatorClient.checkQuality(request);

      this.logger.log(
        `Post-commit check ${response.approved ? "passed" : "failed"} for task ${params.taskId}` +
          (response.message ? `: ${response.message}` : "")
      );

      return this.mapResponse(response);
    } catch (error) {
      this.logger.error(
        `Post-commit check failed for task ${params.taskId}: ${error instanceof Error ? error.message : String(error)}`
      );
      throw error;
    }
  }

  /**
   * Check if quality gate result includes AI confirmation
   *
   * AI confirmation is present when the coordinator response includes
   * aiReview details from an independent AI reviewer agent.
   *
   * @param result Quality gate result to check
   * @returns True if AI confirmation is present
   */
  hasAIConfirmation(result: QualityGateResult): boolean {
    return result.details?.aiReview !== undefined && typeof result.details.aiReview === "object";
  }

  /**
   * Map coordinator response to quality gate result
   *
   * Preserves all fields from coordinator response while ensuring
   * type safety and consistent interface.
   *
   * For ORCH-116 (50% rule enforcement):
   * - Mechanical gates: typecheck, lint, tests, coverage
   * - AI confirmation: independent AI agent review
   * - Rejects if either mechanical OR AI gates fail
   * - Returns detailed failure reasons for debugging
   */
  private mapResponse(response: QualityCheckResponse): QualityGateResult {
    return {
      approved: response.approved,
      gate: response.gate,
      message: response.message,
      details: response.details,
    };
  }

  /**
   * Check if YOLO mode is enabled
   *
   * YOLO mode bypasses all quality gates.
   * Default: false (quality gates enabled)
   *
   * SECURITY: YOLO mode is blocked in production environments to prevent
   * bypassing quality gates in production deployments. This is a security
   * measure to ensure code quality standards are always enforced in production.
   *
   * @returns True if YOLO mode is enabled (always false in production)
   */
  private isYoloModeEnabled(): boolean {
    const yoloRequested = this.configService.get<boolean>("orchestrator.yolo.enabled") ?? false;

    // Block YOLO mode in production
    if (yoloRequested && this.isProductionEnvironment()) {
      this.logger.warn(
        "YOLO mode blocked in production environment - quality gates will be enforced",
        {
          requestedYoloMode: true,
          environment: "production",
          timestamp: new Date().toISOString(),
        }
      );
      return false;
    }

    return yoloRequested;
  }

  /**
   * Check if running in production environment
   *
   * @returns True if NODE_ENV is 'production'
   */
  private isProductionEnvironment(): boolean {
    const nodeEnv = this.configService.get<string>("NODE_ENV") ?? process.env.NODE_ENV;
    return nodeEnv === "production";
  }

  /**
   * Bypass quality gates and return approved result with warning
   *
   * Used when YOLO mode is enabled. Logs audit trail for compliance.
   *
   * @param gate Gate type (pre-commit or post-commit)
   * @param params Check parameters for audit logging
   * @returns Approved result with YOLO mode warning
   */
  private bypassQualityGates(
    gate: string,
    params: PreCommitCheckParams | PostCommitCheckParams
  ): QualityGateResult {
    // Log YOLO mode usage for audit trail
    this.logger.warn("YOLO mode enabled: skipping quality gates", {
      taskId: params.taskId,
      agentId: params.agentId,
      gate,
      files: params.files,
      timestamp: new Date().toISOString(),
    });

    return {
      approved: true,
      gate,
      message: "Quality gates disabled (YOLO mode)",
      details: {
        yoloMode: true,
        warning: "Quality gates were bypassed. Code may not meet quality standards.",
      },
    };
  }
}
