/**
 * Sanity Check Task
 */

import { MODELS } from '../providers/groqProvider.js';
import {
  loadSanityCheckPrompts,
  validateRequiredPrompts,
} from '../prompts/promptLoader.js';
import {
  buildSanityCheckUserPrompt,
  parseSanityCheckResponse,
} from '../prompts/sanityCheckPrompts.js';

export const TASK_ID = 'sanity.check';
export const MAX_PRODUCTS_PER_REQUEST = 50;

export function createSanityCheckTask() {
  return {
    id: TASK_ID,
    description: 'Review batch of products for consistency and appropriateness',

    async run(payload) {
      const { products, provider, pool, logger } = payload;
      const log = logger || console;

      if (!Array.isArray(products) || products.length === 0) {
        return { issues: [], summary: 'No products to check', skipped: true };
      }
      if (!provider) throw new Error('Groq provider not available');
      if (!pool) throw new Error('Database pool not available');

      try {
        const prompts = await loadSanityCheckPrompts(pool);
        validateRequiredPrompts(prompts, 'sanity_check');

        if (products.length <= MAX_PRODUCTS_PER_REQUEST) {
          return await checkBatch(products, prompts, provider, log);
        }

        log.info(`[SanityCheck] Processing ${products.length} products in chunks`);
        const allIssues = [];
        const summaries = [];

        for (let i = 0; i < products.length; i += MAX_PRODUCTS_PER_REQUEST) {
          const chunk = products.slice(i, i + MAX_PRODUCTS_PER_REQUEST);
          const chunkOffset = i;
          const result = await checkBatch(chunk, prompts, provider, log);
          const adjustedIssues = result.issues.map((issue) => ({
            ...issue,
            productIndex: issue.productIndex + chunkOffset,
          }));
          allIssues.push(...adjustedIssues);
          summaries.push(result.summary);
        }

        return {
          issues: allIssues,
          summary: summaries.length > 1
            ? `Reviewed ${products.length} products in ${summaries.length} batches. ${allIssues.length} issues found.`
            : summaries[0],
          totalProducts: products.length,
          issueCount: allIssues.length,
        };
      } catch (error) {
        log.error('[SanityCheck] Error:', error.message);
        throw error;
      }
    },
  };
}

async function checkBatch(products, prompts, provider, log) {
  const userPrompt = buildSanityCheckUserPrompt(products, prompts);
  let response;
  let result;

  try {
    response = await provider.chatCompletion({
      messages: [
        { role: 'system', content: prompts.system },
        { role: 'user', content: userPrompt },
      ],
      model: MODELS.LARGE,
      temperature: 0.2,
      maxTokens: 2000,
      responseFormat: { type: 'json_object' },
    });
    result = parseSanityCheckResponse(response.parsed, response.content);
  } catch (jsonError) {
    if (jsonError.failedGeneration) {
      log.warn('[SanityCheck] JSON mode failed, attempting to parse failed_generation');
      result = parseSanityCheckResponse(null, jsonError.failedGeneration);
      response = { latencyMs: 0, usage: {}, model: MODELS.LARGE };
    } else {
      log.warn('[SanityCheck] JSON mode failed, retrying without JSON mode');
      response = await provider.chatCompletion({
        messages: [
          { role: 'system', content: prompts.system },
          { role: 'user', content: userPrompt },
        ],
        model: MODELS.LARGE,
        temperature: 0.2,
        maxTokens: 2000,
      });
      result = parseSanityCheckResponse(response.parsed, response.content);
    }
  }

  log.info(`[SanityCheck] Checked ${products.length} products in ${response.latencyMs}ms`, {
    issueCount: result.issues.length,
  });

  return {
    ...result,
    latencyMs: response.latencyMs,
    usage: response.usage,
    model: response.model,
  };
}
