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

export async function POST(request: Request) {
  try {
    const body = await request.json();
    const { farmId, agency, awb, hawb, items } = body;

    if (!farmId || !agency || !awb || !items || !Array.isArray(items) || items.length === 0) {
      return NextResponse.json({ error: 'Finca, Agencia de Carga, AWB y al menos un ítem son obligatorios' }, { status: 400 });
    }

    const farm: any = await prisma.farm.findUnique({ where: { id: farmId } });
    if (!farm) {
      return NextResponse.json({ error: 'Finca no encontrada' }, { status: 404 });
    }

    const farmRuc = farm.ruc?.trim() || '1793023088001';
    const now = new Date();

    // Determine the highest existing boxNumber to generate next sequential codes (including cancelled boxes)
    let currentBoxSeq = 100000;
    const existingBoxes = await prisma.orderLine.findMany({
      where: { boxNumber: { not: null } },
      select: { boxNumber: true }
    });
    const cancelledBoxes = await prisma.cancelledLabel.findMany({
      select: { boxNumber: true }
    });
    for (const b of existingBoxes) {
      const n = parseInt(b.boxNumber || '', 10);
      if (!isNaN(n)) currentBoxSeq = Math.max(currentBoxSeq, n);
    }
    for (const c of cancelledBoxes) {
      const n = parseInt(c.boxNumber || '', 10);
      if (!isNaN(n)) currentBoxSeq = Math.max(currentBoxSeq, n);
    }

    const updatedLineIds: string[] = [];
    const createdPurchaseDetails: Array<{
      itemCode: string;
      boxNumber: string;
      uniqueCode: string;
      boxType?: string;
      unitPrice: number;
      farmDepartureDate?: string;
      shipDate?: string;
      deliverDate?: string;
    }> = [];

    // Process each item in the purchase request
    for (const reqItem of items) {
      const { itemCode, farmQty, boxType, unitPrice, farmDepartureDate, shipDate, deliverDate } = reqItem;
      const qtyToAssign = parseInt(farmQty, 10) || 0;
      if (qtyToAssign <= 0) continue;

      // Extract target delivery date string (YYYY-MM-DD) if specified to prioritize matching delivery lines
      const targetDeliverStr = deliverDate ? (deliverDate.includes('T') ? deliverDate.split('T')[0] : deliverDate.trim()) : '';
      let availableLines: any[] = [];

      // 1. Prioritize pending lines matching product code AND the specific deliveryDate of this group
      if (targetDeliverStr) {
        const startOfDay = new Date(`${targetDeliverStr}T00:00:00.000Z`);
        const endOfDay = new Date(`${targetDeliverStr}T23:59:59.999Z`);
        availableLines = await prisma.orderLine.findMany({
          where: {
            id: { notIn: updatedLineIds },
            product: { code: itemCode },
            farmId: null,
            status: 'NEW',
            order: {
              deliveryDate: {
                gte: startOfDay,
                lte: endOfDay
              }
            }
          },
          include: {
            order: {
              include: {
                shippingCustomer: true,
                billingCustomer: true
              }
            },
            product: true
          },
          orderBy: {
            order: {
              creationDate: 'asc' // FIFO within delivery date
            }
          },
          take: qtyToAssign
        });
      }

      // 2. Fallback: if user purchased more boxes than pending for this deliveryDate, take from other pending delivery dates FIFO
      if (availableLines.length < qtyToAssign) {
        const needed = qtyToAssign - availableLines.length;
        const alreadyFetchedIds = [...updatedLineIds, ...availableLines.map(l => l.id)];
        const fallbackLines = await prisma.orderLine.findMany({
          where: {
            id: { notIn: alreadyFetchedIds },
            product: { code: itemCode },
            farmId: null,
            status: 'NEW'
          },
          include: {
            order: {
              include: {
                shippingCustomer: true,
                billingCustomer: true
              }
            },
            product: true
          },
          orderBy: {
            order: {
              creationDate: 'asc' // FIFO
            }
          },
          take: needed
        });
        availableLines = [...availableLines, ...fallbackLines];
      }

      for (let i = 0; i < qtyToAssign; i++) {
        currentBoxSeq++;
        const boxNumber = String(currentBoxSeq).padStart(10, '0'); // e.g. "0000236710"
        const uniqueCode = `${farmRuc}-${itemCode}-${boxNumber}`;

        if (i < availableLines.length) {
          const line = availableLines[i];
          const updated = await prisma.orderLine.update({
            where: { id: line.id },
            data: {
              farmId: farm.id,
              airwayBill: awb.trim(),
              hawb: hawb?.trim() || `FC-${now.getFullYear()}`,
              boxNumber,
              uniqueCode,
              boxType: boxType || line.product.boxType || 'QB',
              farmPrice: parseFloat(unitPrice) || 0,
              farmDepartureDate: farmDepartureDate ? new Date(farmDepartureDate) : null,
              farmOrderDate: now,
              status: 'FARM ASIGNED' // As specified: "la orden debe cambiar a Status Farm asigned"
            }
          });
          updatedLineIds.push(updated.id);
        } else {
          // If more boxes are purchased than current pending orders, create a standby stock line
          let defaultOrder = await prisma.order.findFirst({
            where: { po: 'STOCK-PO' }
          });
          if (!defaultOrder) {
            defaultOrder = await prisma.order.create({
              data: {
                po: 'STOCK-PO',
                orderNumber: `ORD-STK-${Date.now().toString().slice(-6)}`,
                creationDate: now,
                deliveryDate: deliverDate ? new Date(deliverDate) : new Date(now.getTime() + 5 * 86400000),
                shipdt: shipDate || null,
                awb: awb.trim(),
                status: 'FARM ASIGNED'
              }
            });
          }

          const product = await prisma.product.findUnique({ where: { code: itemCode } });
          if (product) {
            const newLine = await prisma.orderLine.create({
              data: {
                orderId: defaultOrder.id,
                productId: product.id,
                quantity: 1,
                farmId: farm.id,
                airwayBill: awb.trim(),
                hawb: hawb?.trim() || `FC-${now.getFullYear()}`,
                boxNumber,
                uniqueCode,
                boxType: boxType || product.boxType || 'QB',
                farmPrice: parseFloat(unitPrice) || 0,
                farmDepartureDate: farmDepartureDate ? new Date(farmDepartureDate) : null,
                farmOrderDate: now,
                status: 'FARM ASIGNED'
              }
            });
            updatedLineIds.push(newLine.id);
          }
        }

        createdPurchaseDetails.push({
          itemCode,
          boxNumber,
          uniqueCode,
          boxType,
          unitPrice: parseFloat(unitPrice) || 0,
          farmDepartureDate,
          shipDate,
          deliverDate: targetDeliverStr || deliverDate
        });
      }
    }

    // Determine recipients according to notification checkboxes
    const recipients: Array<{ role: string; name?: string | null; email: string; phone?: string | null }> = [];
    if (farm.emailOrders && farm.notifyOrders !== false) {
      recipients.push({ role: 'Órdenes', name: farm.contactOrders, email: farm.emailOrders.trim(), phone: farm.phoneOrders });
    }
    if (farm.emailLabels && farm.notifyLabels !== false) {
      recipients.push({ role: 'Etiquetas', name: farm.contactLabels, email: farm.emailLabels.trim(), phone: farm.phoneLabels });
    }
    if (farm.emailCoord && farm.notifyCoord !== false) {
      recipients.push({ role: 'Coordinación', name: farm.contactCoord, email: farm.emailCoord.trim(), phone: farm.phoneCoord });
    }

    const recipientEmails = Array.from(new Set(recipients.map(r => r.email)));
    const farmNotice = recipientEmails.length > 0
      ? `Notificación enviada a: ${recipients.map(r => `${r.role} (${r.name ? `${r.name}: ` : ''}${r.email})`).join(', ')}`
      : 'Sin destinatarios de notificación activos (verifique la configuración de la finca).';

    return NextResponse.json({
      success: true,
      message: `Orden colocada a ${farm.name} exitosamente. ${updatedLineIds.length} cajas asignadas.`,
      farmNotice,
      assignedCount: updatedLineIds.length,
      assignedLineIds: updatedLineIds,
      updatedLineIds,
      purchaseDetails: createdPurchaseDetails,
      awb,
      agency,
      farm: {
        id: farm.id,
        name: farm.name,
        ruc: farm.ruc
      }
    });

  } catch (error: any) {
    console.error('Error in place-order:', error);
    return NextResponse.json({ error: error.message || 'Error al procesar el pedido a la finca' }, { status: 500 });
  }
}
