import { NextResponse } from 'next/server';
import { prisma } from '@/lib/prisma';
import { parseExcelDate } from '@/lib/dateUtils';

interface EditItemPayload {
  lineIds: string[];
  orderedQty?: number;
  newQty?: number;
  farmPrice?: number;
  farmDepartureDate?: string;
  boxType?: string;
  farmId?: string;
  airwayBill?: string;
  productId?: string;
  productCode?: string;
}

export async function POST(request: Request) {
  try {
    const body = await request.json();
    const { action, lineIds, updates, items } = body;

    // ── CANCEL ACTION ────────────────────────────────────────────────────────
    if (action === 'cancel') {
      const targetLineIds: string[] = lineIds || [];
      if (!Array.isArray(targetLineIds) || targetLineIds.length === 0) {
        return NextResponse.json({ error: 'Se requiere una lista de IDs de cajas/órdenes a cancelar' }, { status: 400 });
      }

      // Fetch all lines to be cancelled
      const linesToCancel = await prisma.orderLine.findMany({
        where: { id: { in: targetLineIds } },
        include: {
          order: {
            include: {
              shippingCustomer: true,
              billingCustomer: true,
              masterCustomer: true
            }
          },
          product: true,
          farm: true
        }
      });

      // Archive each to CancelledLabel so the boxNumber and uniqueCode are never reused
      for (const l of linesToCancel) {
        if (l.boxNumber || l.uniqueCode) {
          const customerName = l.order?.masterCustomer?.businessName ||
            l.order?.shippingCustomer?.businessName ||
            l.order?.billingCustomer?.businessName || '—';

          const uniqueCode = l.uniqueCode || `${l.farm?.ruc || 'FARM'}-${l.product?.code || 'ITEM'}-${l.boxNumber || '000'}`;

          await prisma.cancelledLabel.upsert({
            where: { uniqueCode },
            create: {
              orderLineId: l.id,
              boxNumber: l.boxNumber || '000000',
              uniqueCode,
              itemCode: l.product?.code || '',
              productName: l.product?.name || '',
              farmId: l.farmId,
              farmName: l.farm?.name || '',
              customerName,
              po: l.order?.po || '',
              airwayBill: l.airwayBill || '',
              agency: l.order?.service || '',
              boxType: l.boxType || l.product?.boxType || 'QB',
              farmPrice: l.farmPrice,
              farmDepartureDate: l.farmDepartureDate,
              orderDate: l.order?.creationDate,
              reason: updates?.reason || 'Cancelación directa de caja en Historial de Compras'
            },
            update: {
              reason: updates?.reason || 'Cancelación directa de caja en Historial de Compras'
            }
          });
        }
      }

      // Reset order lines to status NEW and clear farm assignment
      await prisma.orderLine.updateMany({
        where: { id: { in: targetLineIds } },
        data: {
          farmId: null,
          airwayBill: null,
          hawb: null,
          boxNumber: null,
          uniqueCode: null,
          farmPrice: null,
          farmOrderDate: null,
          farmDepartureDate: null,
          status: 'NEW'
        }
      });

      return NextResponse.json({
        success: true,
        message: `${targetLineIds.length} caja(s) cancelada(s) y regresada(s) a estado PENDIENTE (NEW) exitosamente.`
      });
    }

    // ── EDIT ACTION (Single or Multi-item) ────────────────────────────────────
    if (action === 'edit') {
      const editItems: EditItemPayload[] = Array.isArray(items) && items.length > 0
        ? items
        : [{ lineIds: lineIds || [], ...(updates || {}) }];

      if (editItems.length === 0 || editItems.every(it => !it.lineIds || it.lineIds.length === 0)) {
        return NextResponse.json({ error: 'No se enviaron líneas válidas para editar' }, { status: 400 });
      }

      let totalUpdated = 0;
      let totalCancelled = 0;

      for (const it of editItems) {
        if (!it.lineIds || it.lineIds.length === 0) continue;

        // Fetch existing lines ordered by customer order creationDate DESC
        // (FIFO cancellation: the newest client order dates are cancelled first, preserving older ones!)
        const currentLines = await prisma.orderLine.findMany({
          where: { id: { in: it.lineIds } },
          include: {
            order: {
              include: {
                shippingCustomer: true,
                billingCustomer: true,
                masterCustomer: true
              }
            },
            product: true,
            farm: true
          },
          orderBy: {
            order: {
              creationDate: 'desc'
            }
          }
        });

        const currentCount = currentLines.length;
        const targetQty = (it.newQty !== undefined && it.newQty !== null) ? Number(it.newQty) : currentCount;

        // Determine if quantity was reduced
        let linesToCancel: typeof currentLines = [];
        let linesToKeep: typeof currentLines = currentLines;

        if (targetQty < currentCount) {
          const cancelCount = currentCount - targetQty;
          linesToCancel = currentLines.slice(0, cancelCount);
          linesToKeep = currentLines.slice(cancelCount);
        }

        // Cancel the excess lines and record them in CancelledLabel
        for (const l of linesToCancel) {
          if (l.boxNumber || l.uniqueCode) {
            const customerName = l.order?.masterCustomer?.businessName ||
              l.order?.shippingCustomer?.businessName ||
              l.order?.billingCustomer?.businessName || '—';

            const uniqueCode = l.uniqueCode || `${l.farm?.ruc || 'FARM'}-${l.product?.code || 'ITEM'}-${l.boxNumber || '000'}`;

            await prisma.cancelledLabel.upsert({
              where: { uniqueCode },
              create: {
                orderLineId: l.id,
                boxNumber: l.boxNumber || '000000',
                uniqueCode,
                itemCode: l.product?.code || '',
                productName: l.product?.name || '',
                farmId: l.farmId,
                farmName: l.farm?.name || '',
                customerName,
                po: l.order?.po || '',
                airwayBill: l.airwayBill || '',
                agency: l.order?.service || '',
                boxType: l.boxType || l.product?.boxType || 'QB',
                farmPrice: l.farmPrice,
                farmDepartureDate: l.farmDepartureDate,
                orderDate: l.order?.creationDate,
                reason: 'Cancelado por reducción de cantidad al editar orden (FIFO)'
              },
              update: {
                reason: 'Cancelado por reducción de cantidad al editar orden (FIFO)'
              }
            });
          }

          // Revert cancelled line to NEW status for re-assignment
          await prisma.orderLine.update({
            where: { id: l.id },
            data: {
              farmId: null,
              airwayBill: null,
              hawb: null,
              boxNumber: null,
              uniqueCode: null,
              farmPrice: null,
              farmOrderDate: null,
              farmDepartureDate: null,
              status: 'NEW'
            }
          });
          totalCancelled++;
        }

        // Prepare fields to update for the remaining kept lines
        const dataToUpdate: any = {};
        if (it.farmPrice !== undefined && it.farmPrice !== null) {
          dataToUpdate.farmPrice = parseFloat(String(it.farmPrice)) || 0;
        }
        if (it.boxType !== undefined && it.boxType !== null) {
          dataToUpdate.boxType = it.boxType.trim();
        }
        if (it.farmDepartureDate !== undefined) {
          dataToUpdate.farmDepartureDate = it.farmDepartureDate ? parseExcelDate(it.farmDepartureDate) : null;
        }
        if (it.farmId !== undefined) {
          dataToUpdate.farmId = it.farmId || null;
        }
        if (it.airwayBill !== undefined) {
          dataToUpdate.airwayBill = it.airwayBill?.trim() || null;
        }

        // If product was changed
        if (it.productId) {
          dataToUpdate.productId = it.productId;
        } else if (it.productCode) {
          const foundProduct = await prisma.product.findUnique({ where: { code: it.productCode } });
          if (foundProduct) {
            dataToUpdate.productId = foundProduct.id;
          }
        }

        const keepIds = linesToKeep.map(l => l.id);
        if (keepIds.length > 0 && Object.keys(dataToUpdate).length > 0) {
          await prisma.orderLine.updateMany({
            where: { id: { in: keepIds } },
            data: dataToUpdate
          });
          totalUpdated += keepIds.length;
        } else {
          totalUpdated += keepIds.length;
        }
      }

      let msg = `${totalUpdated} caja(s) actualizada(s) exitosamente.`;
      if (totalCancelled > 0) {
        msg += ` ${totalCancelled} caja(s) cancelada(s) con prioridad FIFO y regresada(s) a estado PENDIENTE (NEW).`;
      }

      return NextResponse.json({
        success: true,
        message: msg,
        totalUpdated,
        totalCancelled
      });
    }

    return NextResponse.json({ error: 'Acción no válida. Use "cancel" o "edit".' }, { status: 400 });
  } catch (error: any) {
    console.error('Error in /api/pedidos/manage-lines:', error);
    return NextResponse.json({ error: error.message || 'Error al procesar la acción' }, { status: 500 });
  }
}
