/**
 * AI Routes
 *
 * API endpoints for AI-powered product validation features.
 * Provides embedding generation and similarity-based suggestions.
 */

import express from 'express';
import aiService from '../services/ai/index.js';
import { getDbConnection, closeAllConnections } from '../utils/dbConnection.js';

const router = express.Router();

// Track initialization state
let initializationPromise = null;

/**
 * Ensure AI service is initialized
 * Uses lazy initialization on first request
 */
async function ensureInitialized() {
  if (aiService.isReady()) {
    return true;
  }

  if (initializationPromise) {
    await initializationPromise;
    return aiService.isReady();
  }

  initializationPromise = (async () => {
    try {
      console.log('[AI Routes] Initializing AI service...');

      // Get database connection for taxonomy
      const { connection } = await getDbConnection();

      const result = await aiService.initialize({
        openaiApiKey: process.env.OPENAI_API_KEY,
        groqApiKey: process.env.GROQ_API_KEY,
        mysqlConnection: connection,
        pool: null, // Will be set by setPool()
        logger: console
      });

      if (!result.success) {
        console.error('[AI Routes] AI service initialization failed:', result.message);
        return false;
      }

      console.log('[AI Routes] AI service initialized:', {
        ...result.stats,
        groqEnabled: result.groqEnabled
      });

      // Watch for taxonomy changes in the background (checks every hour)
      aiService.startBackgroundCheck(getDbConnection);

      return true;
    } catch (error) {
      console.error('[AI Routes] Failed to initialize AI service:', error);
      return false;
    }
  })();

  await initializationPromise;
  return aiService.isReady();
}

/**
 * GET /api/ai/status
 * Get AI service status
 */
router.get('/status', async (req, res) => {
  try {
    const status = aiService.getStatus();
    res.json(status);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/ai/initialize
 * Manually trigger initialization (also happens automatically on first use)
 */
router.post('/initialize', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    const status = aiService.getStatus();

    res.json({
      success: ready,
      ...status
    });
  } catch (error) {
    console.error('[AI Routes] Initialize error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * GET /api/ai/taxonomy
 * Get all taxonomy data (categories, themes, colors) without embeddings
 */
router.get('/taxonomy', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    const taxonomy = aiService.getTaxonomyData();
    res.json(taxonomy);
  } catch (error) {
    console.error('[AI Routes] Taxonomy error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/ai/embedding
 * Generate embedding for a single product
 *
 * Body: { product: { name, description, company_name, line_name } }
 * Returns: { embedding: number[], latencyMs: number }
 */
router.post('/embedding', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    const { product } = req.body;

    if (!product) {
      return res.status(400).json({ error: 'Product is required' });
    }

    const result = await aiService.getProductEmbedding(product);
    res.json(result);
  } catch (error) {
    console.error('[AI Routes] Embedding error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/ai/embeddings
 * Generate embeddings for multiple products
 *
 * Body: { products: Array<{ name, description, company_name, line_name }> }
 * Returns: { embeddings: Array<{ index, embedding }>, latencyMs }
 */
router.post('/embeddings', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    const { products } = req.body;

    if (!Array.isArray(products)) {
      return res.status(400).json({ error: 'Products array is required' });
    }

    const result = await aiService.getProductEmbeddings(products);
    res.json(result);
  } catch (error) {
    console.error('[AI Routes] Embeddings error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/ai/suggestions
 * Get category/theme/color suggestions for a single product
 * Generates embedding and finds similar taxonomy items
 *
 * Body: { product: { name, description, company_name, line_name }, options?: { topCategories, topThemes, topColors } }
 * Returns: { categories: Array, themes: Array, colors: Array, latencyMs }
 */
router.post('/suggestions', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    const { product, options } = req.body;

    if (!product) {
      return res.status(400).json({ error: 'Product is required' });
    }

    const suggestions = await aiService.getSuggestionsForProduct(product, options);
    res.json(suggestions);
  } catch (error) {
    console.error('[AI Routes] Suggestions error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/ai/suggestions/batch
 * Get suggestions for multiple products
 * More efficient than calling /suggestions multiple times
 *
 * Body: { products: Array, options?: { topCategories, topThemes, topColors } }
 * Returns: { results: Array<{ index, categories, themes, colors }>, latencyMs }
 */
router.post('/suggestions/batch', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    const { products, options } = req.body;

    if (!Array.isArray(products)) {
      return res.status(400).json({ error: 'Products array is required' });
    }

    const startTime = Date.now();

    // Generate all embeddings at once
    const { embeddings, latencyMs: embeddingLatency } = await aiService.getProductEmbeddings(products);

    // Find suggestions for each embedding
    const results = embeddings.map(({ index, embedding }) => {
      const suggestions = aiService.findSimilarTaxonomy(embedding, options);
      return {
        index,
        ...suggestions
      };
    });

    const totalLatency = Date.now() - startTime;

    res.json({
      results,
      latencyMs: totalLatency,
      embeddingLatencyMs: embeddingLatency,
      searchLatencyMs: totalLatency - embeddingLatency,
      productCount: products.length,
      embeddingCount: embeddings.length
    });
  } catch (error) {
    console.error('[AI Routes] Batch suggestions error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/ai/similar
 * Find similar taxonomy items given a pre-computed embedding
 * Useful when frontend has cached the embedding
 *
 * Body: { embedding: number[], options?: { topCategories, topThemes, topColors } }
 * Returns: { categories, themes, colors }
 */
router.post('/similar', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    const { embedding, options } = req.body;

    if (!embedding || !Array.isArray(embedding)) {
      return res.status(400).json({ error: 'Embedding array is required' });
    }

    const startTime = Date.now();
    const suggestions = aiService.findSimilarTaxonomy(embedding, options);

    res.json({
      ...suggestions,
      latencyMs: Date.now() - startTime
    });
  } catch (error) {
    console.error('[AI Routes] Similar error:', error);
    res.status(500).json({ error: error.message });
  }
});

// ============================================================================
// INLINE AI VALIDATION ENDPOINTS (Groq-powered)
// ============================================================================

/**
 * POST /api/ai/validate/inline/name
 * Validate a single product name for spelling, grammar, and naming conventions
 *
 * Body: { product: { name, company_name, company_id, line_name, description } }
 * Returns: { isValid, suggestion?, issues[], latencyMs }
 */
router.post('/validate/inline/name', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    if (!aiService.hasChatCompletion()) {
      return res.status(503).json({
        error: 'Chat completion not available - GROQ_API_KEY not configured'
      });
    }

    const { product } = req.body;

    if (!product) {
      return res.status(400).json({ error: 'Product is required' });
    }

    // Get pool from app.locals (set by server.js)
    const pool = req.app.locals.pool;

    const result = await aiService.runTask(aiService.TASK_IDS.VALIDATE_NAME, {
      product,
      pool
    });

    if (!result.success) {
      return res.status(500).json({
        error: result.error || 'Validation failed',
        code: result.code
      });
    }

    res.json(result);
  } catch (error) {
    console.error('[AI Routes] Name validation error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/ai/validate/inline/description
 * Validate a single product description for quality and guideline compliance
 *
 * Body: { product: { name, description, company_name, company_id, categories } }
 * Returns: { isValid, suggestion?, issues[], latencyMs }
 */
router.post('/validate/inline/description', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    if (!aiService.hasChatCompletion()) {
      return res.status(503).json({
        error: 'Chat completion not available - GROQ_API_KEY not configured'
      });
    }

    const { product } = req.body;

    if (!product) {
      return res.status(400).json({ error: 'Product is required' });
    }

    // Get pool from app.locals (set by server.js)
    const pool = req.app.locals.pool;

    const result = await aiService.runTask(aiService.TASK_IDS.VALIDATE_DESCRIPTION, {
      product,
      pool
    });

    if (!result.success) {
      return res.status(500).json({
        error: result.error || 'Validation failed',
        code: result.code
      });
    }

    res.json(result);
  } catch (error) {
    console.error('[AI Routes] Description validation error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * POST /api/ai/validate/sanity-check
 * Run consistency/sanity check on a batch of products
 *
 * Body: { products: Array<product data> }
 * Returns: { issues: Array<{ productIndex, field, issue, suggestion? }>, summary, latencyMs }
 */
router.post('/validate/sanity-check', async (req, res) => {
  try {
    const ready = await ensureInitialized();
    if (!ready) {
      return res.status(503).json({ error: 'AI service not available' });
    }

    if (!aiService.hasChatCompletion()) {
      return res.status(503).json({
        error: 'Chat completion not available - GROQ_API_KEY not configured'
      });
    }

    const { products } = req.body;

    if (!Array.isArray(products) || products.length === 0) {
      return res.status(400).json({ error: 'Products array is required' });
    }

    // Get pool from app.locals (set by server.js)
    const pool = req.app.locals.pool;

    const result = await aiService.runTask(aiService.TASK_IDS.SANITY_CHECK, {
      products,
      pool
    });

    if (!result.success) {
      return res.status(500).json({
        error: result.error || 'Sanity check failed',
        code: result.code
      });
    }

    res.json(result);
  } catch (error) {
    console.error('[AI Routes] Sanity check error:', error);
    res.status(500).json({ error: error.message });
  }
});

/**
 * Kick off AI initialization in the background (no-op if already initialized).
 * Call once from server startup so the taxonomy embeddings are ready before
 * the first user request hits a taxonomy dropdown.
 */
export function initInBackground() {
  ensureInitialized().catch(err =>
    console.error('[AI Routes] Background initialization failed:', err)
  );
}

export default router;
