import { NextRequest, NextResponse } from 'next/server';
import { withAuth } from '@/lib/api-guards';

// POST: Configure calculation rules (restricted to admin and director)
export const POST = withAuth(async (req, { session, prisma, params }) => {
  const unwrappedParams = await params;
  const planId = parseInt(unwrappedParams.id);
  const body = await req.json(); // Expected: { rules: [{ type: 'TIER', minAchievement: 0.9, maxAchievement: 1.0, rate: 0.015, payoutAmount: 0 }, ...] }

  if (isNaN(planId)) {
    return NextResponse.json({ error: 'ID no válido.' }, { status: 400 });
  }

  const plan = await prisma.compensationPlan.findUnique({
    where: { id: planId }
  });

  if (!plan) {
    return NextResponse.json({ error: 'Plan no encontrado.' }, { status: 404 });
  }

  console.log("[DEBUG RULES] body.rules:", JSON.stringify(body.rules));
  // Validate rules before database execution
  if (body.rules && Array.isArray(body.rules)) {
    try {
      const sortedRules = [...body.rules].sort((a: any, b: any) => parseFloat(a.minAchievement) - parseFloat(b.minAchievement));

      for (let i = 0; i < sortedRules.length; i++) {
        const rule = sortedRules[i];
        
        if (!rule.type || rule.minAchievement === undefined || rule.maxAchievement === undefined) {
          return NextResponse.json({ error: 'Parámetros de regla de cálculo no válidos.' }, { status: 400 });
        }

        const min = parseFloat(rule.minAchievement);
        const max = parseFloat(rule.maxAchievement);

        if (isNaN(min) || isNaN(max)) {
          console.log("[DEBUG RULES] isNaN(min) || isNaN(max) failed:", min, max);
          return NextResponse.json({ error: 'Los límites de cumplimiento deben ser números válidos.' }, { status: 400 });
        }

        if (min >= max) {
          console.log("[DEBUG RULES] min >= max failed:", min, max);
          return NextResponse.json({ error: `El cumplimiento mínimo de la regla (${min}) debe ser estrictamente menor que el cumplimiento máximo (${max}).` }, { status: 400 });
        }

        if (i < sortedRules.length - 1) {
          const nextRule = sortedRules[i + 1];
          const nextMin = parseFloat(nextRule.minAchievement);
          const nextMax = parseFloat(nextRule.maxAchievement);

          if (isNaN(nextMin) || isNaN(nextMax)) {
            console.log("[DEBUG RULES] isNaN(nextMin) || isNaN(nextMax) failed:", nextMin, nextMax);
            return NextResponse.json({ error: 'Los límites de cumplimiento deben ser números válidos.' }, { status: 400 });
          }

          if (nextMin < max) {
            console.log("[DEBUG RULES] nextMin < max failed:", nextMin, max);
            return NextResponse.json({ error: `Se detectó superposición en las reglas de cálculo: el rango [${min}, ${max}] se superpone con el rango [${nextMin}, ${nextMax}].` }, { status: 400 });
          }

          if (Math.abs(nextMin - max) > 0.0001) {
            console.log("[DEBUG RULES] Math.abs(nextMin - max) > 0.0001 failed:", nextMin, max, Math.abs(nextMin - max));
            return NextResponse.json({ error: `Las reglas de cálculo deben ser contiguas: el rango [${min}, ${max}] no es contiguo con el rango [${nextMin}, ${nextMax}].` }, { status: 400 });
          }
        }
      }
    } catch (e: any) {
      console.log("[DEBUG RULES] Catch error:", e);
      return NextResponse.json({ error: e.message || 'Error de validación.' }, { status: 400 });
    }
  }

  // Bulk overwrite rules inside a transaction
  const rules = await prisma.$transaction(async (tx: any) => {
    // 1. Delete existing rules
    await tx.calculationRule.deleteMany({
      where: { planId }
    });

    // 2. Insert new ones if provided
    if (body.rules && Array.isArray(body.rules)) {
      await tx.calculationRule.createMany({
        data: body.rules.map((r: any) => ({
          planId,
          type: r.type,
          minAchievement: parseFloat(r.minAchievement),
          maxAchievement: parseFloat(r.maxAchievement),
          rate: r.rate !== undefined ? parseFloat(r.rate) : 0.0,
          payoutAmount: r.payoutAmount !== undefined ? parseFloat(r.payoutAmount) : 0.0
        }))
      });
    }

    return tx.calculationRule.findMany({
      where: { planId }
    });
  });

  return NextResponse.json({ rules });
}, ['admin', 'director']);
