import { Router, Request, Response } from 'express';
import { GenerateSchema } from '../schemas/generate.schema.js';
import { validateLicence, incrementUsage, hashKey } from '../lib/licence.js';
import { licenceLimiter } from '../lib/rateLimiter.js';
import { generateProposalLines } from '../lib/anthropic.js';
import { logger } from '../lib/logger.js';

const NOTIFY_WEBHOOK_URL = process.env.NOTIFY_WEBHOOK_URL ?? '';

const router = Router();

router.post('/', async (req: Request, res: Response): Promise<void> => {
  const start = Date.now();

  const parsed = GenerateSchema.safeParse(req.body);
  if (!parsed.success) {
    res.status(400).json({ error: 'validation_error', details: parsed.error.flatten() });
    return;
  }

  const { licence_key, notes, photos, catalogue, contexte, verbosity, corrections } = parsed.data;

  const clientIp =
    (req.headers['x-forwarded-for'] as string | undefined)?.split(',')[0]?.trim() ??
    req.ip ??
    '0.0.0.0';

  const dolibarrDomain = (req.headers['x-dolibarr-domain'] as string | undefined) ?? undefined;

  const licenceResult = await validateLicence(licence_key, clientIp, dolibarrDomain);

  if (!licenceResult.valid) {
    if (licenceResult.reason === 'quota_exceeded') {
      res.status(402).json({ error: 'quota_exceeded' });
      return;
    }
    if (licenceResult.reason === 'domain_mismatch') {
      res.status(403).json({ error: 'domain_mismatch' });
      return;
    }
    res.status(401).json({ error: 'licence_invalid' });
    return;
  }

  const { licence } = licenceResult;

  if (!(await licenceLimiter(licence.id))) {
    res.status(429).json({ error: 'rate_limit_licence' });
    return;
  }

  let result;
  try {
    result = await generateProposalLines(notes, photos, catalogue, contexte, verbosity, corrections);
  } catch (err: unknown) {
    const errObj = err as { code?: string; rawText?: string; message?: string };

    if (errObj.code === 'PARSE_ERROR') {
      logger.error('AI parse error', { raw: String(errObj.rawText ?? '').slice(0, 300) });
      res.status(422).json({ error: 'ai_parse_error' });
      return;
    }

    const message = errObj.message ?? String(err);
    if (message.includes('rate_limit') || message.includes('overloaded')) {
      res.status(503).json({ error: 'anthropic_rate_limit' });
      return;
    }

    logger.error('Anthropic error', {
      message: message.replace(process.env.ANTHROPIC_API_KEY ?? '', '***'),
    });
    res.status(500).json({ error: 'internal_error' });
    return;
  }

  const latency = Date.now() - start;
  await incrementUsage(licence.id, {
    nb_photos:  photos.length,
    nb_lignes:  result.lignes.length,
    latency_ms: latency,
    key_hash:   hashKey(licence_key),
  }).catch((e: unknown) => logger.error('Usage log failed', { err: String(e) }));

  // Compute match_score: 100 if product_ref found in catalogue, 0 if ref not found, null if free-form
  const catalogueRefs = new Set(catalogue.map(item => item.ref));
  const lignes = result.lignes.map(ligne => ({
    ...ligne,
    match_score: ligne.product_ref != null
      ? (catalogueRefs.has(ligne.product_ref) ? 100 : 0)
      : null,
  }));

  // Fire-and-forget generation notification webhook (v2.0)
  if (NOTIFY_WEBHOOK_URL) {
    fetch(NOTIFY_WEBHOOK_URL, {
      method:  'POST',
      headers: { 'Content-Type': 'application/json' },
      body:    JSON.stringify({
        event:      'generation_complete',
        nb_lignes:  lignes.length,
        nb_photos:  photos.length,
        latency_ms: latency,
        contexte,
        timestamp:  new Date().toISOString(),
      }),
    }).catch((e: unknown) => logger.error('Notify webhook failed', { err: String(e) }));
  }

  res.json({ lignes });
});

export default router;
