import { resolve } from 'path';
import { createModuleLogger } from '../../utils/logger.js';
import { VLMAnalyzer, createVLMAnalyzer } from '../openrouter/vlm.js';
import { dataStore } from '../data-store/index.js';
import { atomicWriteJSON } from '../data-store/file-ops.js';
import type { QualityReport } from '../../types/api.js';

const logger = createModuleLogger('quality-control');

const DEFAULT_THRESHOLD = 7.0;
const DEFAULT_MAX_ATTEMPTS = 3;

export class QualityController {
  private readonly vlm: VLMAnalyzer;

  constructor(vlm?: VLMAnalyzer) {
    this.vlm = vlm ?? createVLMAnalyzer();
  }

  /**
   * Runs VLM analysis on an image and saves the quality report.
   */
  async checkQuality(
    imageUrl: string,
    characterId: string,
    imageId: string,
    taskId: string,
    threshold: number = DEFAULT_THRESHOLD,
  ): Promise<QualityReport> {
    const dna = await dataStore.getCharacter(characterId);
    if (!dna) {
      throw new Error(`Character not found: ${characterId}`);
    }

    const report = await this.vlm.analyzeImage(imageUrl, dna, imageId, taskId, threshold);

    // Save quality report
    const reportsDir = dataStore.getQualityReportsDir(characterId);
    const reportPath = resolve(reportsDir, `${imageId}.json`);
    await atomicWriteJSON(reportPath, report);

    logger.info(
      { imageId, totalScore: report.totalScore, passed: report.passed },
      'Quality check complete, report saved',
    );

    return report;
  }

  /**
   * Checks quality with auto-retry. If below threshold, calls regenerateFn
   * with VLM feedback and re-checks. Max attempts before marking for manual review.
   */
  async checkWithRetry(
    imageUrl: string,
    characterId: string,
    imageId: string,
    taskId: string,
    regenerateFn: (feedback: string) => Promise<string>,
    threshold: number = DEFAULT_THRESHOLD,
    maxAttempts: number = DEFAULT_MAX_ATTEMPTS,
  ): Promise<QualityReport> {
    let currentUrl = imageUrl;
    let currentImageId = imageId;
    let lastReport: QualityReport | undefined;

    for (let attempt = 1; attempt <= maxAttempts; attempt++) {
      logger.info({ attempt, maxAttempts, imageId: currentImageId }, 'Quality check attempt');

      const report = await this.checkQuality(
        currentUrl,
        characterId,
        currentImageId,
        taskId,
        threshold,
      );
      lastReport = report;

      if (report.passed) {
        logger.info({ attempt, totalScore: report.totalScore }, 'Image passed quality check');
        return report;
      }

      // If not the last attempt, regenerate with feedback
      if (attempt < maxAttempts) {
        logger.info(
          { attempt, totalScore: report.totalScore, feedback: report.feedback },
          'Image below threshold, requesting regeneration',
        );

        const newUrl = await regenerateFn(report.feedback);
        currentUrl = newUrl;
        currentImageId = `${imageId}_retry${attempt}`;
      }
    }

    // All attempts exhausted — mark for manual review
    logger.warn(
      { imageId, attempts: maxAttempts, totalScore: lastReport!.totalScore },
      'Max attempts reached, marking for manual review',
    );

    const finalReport: QualityReport = {
      ...lastReport!,
      passed: false,
      feedback: `[MANUAL_REVIEW_REQUIRED] ${lastReport!.feedback}`,
    };

    // Overwrite the last report with manual review flag
    const reportsDir = dataStore.getQualityReportsDir(characterId);
    const reportPath = resolve(reportsDir, `${lastReport!.imageId}.json`);
    await atomicWriteJSON(reportPath, finalReport);

    return finalReport;
  }
}

let _qualityController: QualityController | null = null;

/** Lazy singleton — avoids requiring API keys at import time. */
export function getQualityController(): QualityController {
  if (!_qualityController) {
    _qualityController = new QualityController();
  }
  return _qualityController;
}
