/**
 * Sanity Check Task
 *
 * Reviews a batch of products for consistency and appropriateness.
 * Uses Groq with the larger model for complex batch analysis.
 * Loads all prompts from the database (no hardcoded prompts).
 */

const { MODELS } = require('../providers/groqProvider');
const {
  loadSanityCheckPrompts,
  validateRequiredPrompts
} = require('../prompts/promptLoader');
const {
  buildSanityCheckUserPrompt,
  parseSanityCheckResponse
} = require('../prompts/sanityCheckPrompts');

const TASK_ID = 'sanity.check';

// Maximum products to send in a single request (to avoid token limits)
const MAX_PRODUCTS_PER_REQUEST = 50;

/**
 * Create the sanity check task
 *
 * @returns {Object} Task definition
 */
function createSanityCheckTask() {
  return {
    id: TASK_ID,
    description: 'Review batch of products for consistency and appropriateness',

    /**
     * Run the sanity check
     *
     * @param {Object} payload
     * @param {Object[]} payload.products - Array of products to check
     * @param {Object} payload.provider - Groq provider instance
     * @param {Object} payload.pool - PostgreSQL pool
     * @param {Object} [payload.logger] - Logger instance
     * @returns {Promise<Object>}
     */
    async run(payload) {
      const { products, provider, pool, logger } = payload;
      const log = logger || console;

      // Validate required input
      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 {
        // Load prompts from database
        const prompts = await loadSanityCheckPrompts(pool);

        // Validate required prompts exist
        validateRequiredPrompts(prompts, 'sanity_check');

        // If batch is small enough, process in one request
        if (products.length <= MAX_PRODUCTS_PER_REQUEST) {
          return await checkBatch(products, prompts, provider, log);
        }

        // Otherwise, process in chunks and combine results
        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; // To adjust product indices in results

          const result = await checkBatch(chunk, prompts, provider, log);

          // Adjust product indices to match original array
          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;
      }
    }
  };
}

/**
 * Check a single batch of products
 *
 * @param {Object[]} products - Products to check
 * @param {Object} prompts - Loaded prompts from database
 * @param {Object} provider - Groq provider
 * @param {Object} log - Logger
 * @returns {Promise<Object>}
 */
async function checkBatch(products, prompts, provider, log) {
  const userPrompt = buildSanityCheckUserPrompt(products, prompts);

  let response;
  let result;

  try {
    // Try with JSON mode first
    response = await provider.chatCompletion({
      messages: [
        { role: 'system', content: prompts.system },
        { role: 'user', content: userPrompt }
      ],
      model: MODELS.LARGE,  // openai/gpt-oss-120b - needed for complex batch analysis
      temperature: 0.2,     // Low temperature for consistent analysis
      maxTokens: 2000,      // More tokens for batch results
      responseFormat: { type: 'json_object' }
    });

    result = parseSanityCheckResponse(response.parsed, response.content);
  } catch (jsonError) {
    // If JSON mode failed, check if we have failedGeneration to parse
    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 {
      // Retry without JSON mode
      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
        // No responseFormat - let the model respond freely
      });
      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
  };
}

module.exports = {
  TASK_ID,
  createSanityCheckTask,
  MAX_PRODUCTS_PER_REQUEST
};
