import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/db';
import { logAuditEvent, logBlockedDelete, checkVoidAllowed } from '@/lib/gfs/guardrails';
import { Prisma } from '@prisma/client';

export const dynamic = 'force-dynamic';

function generateOrderNumber(): string {
  const d = new Date();
  const prefix = `POS-${d.getFullYear()}${String(d.getMonth()+1).padStart(2,'0')}${String(d.getDate()).padStart(2,'0')}`;
  const seq = String(Math.floor(Math.random() * 9999)).padStart(4, '0');
  return `${prefix}-${seq}`;
}

// GET — List orders (open, recent, by station, etc.)
export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const status = searchParams.get('status');
  const stationId = searchParams.get('stationId');
  const limit = Number(searchParams.get('limit') || '50');

  const where: Prisma.POSOrderWhereInput = {};
  if (status) where.status = status;
  if (stationId) where.stationId = stationId;

  const orders = await prisma.pOSOrder.findMany({
    where,
    orderBy: { createdAt: 'desc' },
    take: limit,
    include: {
      items: { include: { menuItem: true } },
      payments: true,
      station: true,
    },
  });

  return NextResponse.json({ orders });
}

// POST — Create order, add items, transfer, void
export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const { action } = body;

    // ── CREATE NEW ORDER ──
    if (action === 'create') {
      const order = await prisma.pOSOrder.create({
        data: {
          orderNumber: generateOrderNumber(),
          stationId: body.stationId || null,
          customerId: body.customerId || null,
          cashierId: body.cashierId || 'default',
          orderType: body.orderType || 'dine-in',
          tableNumber: body.tableNumber || null,
          guestCount: body.guestCount || 1,
        },
        include: { items: true, payments: true },
      });
      await logAuditEvent({
        action: 'create', resource: 'pos_order', resourceId: order.id,
        performedBy: body.cashierId || 'system', reason: 'New POS order created',
        previousState: {}, newState: { orderNumber: order.orderNumber, status: 'open' },
      });
      return NextResponse.json({ order }, { status: 201 });
    }

    // ── ADD ITEMS TO ORDER ──
    if (action === 'add_items') {
      const { orderId, items } = body;
      const order = await prisma.pOSOrder.findUnique({ where: { id: orderId } });
      if (!order) return NextResponse.json({ error: 'Order not found' }, { status: 404 });
      if (order.status === 'voided' || order.status === 'closed') {
        return NextResponse.json({ error: `Cannot add items to ${order.status} order` }, { status: 409 });
      }

      const createdItems = [];
      for (const item of items) {
        const modTotal = Number(item.modifierTotal || 0);
        const unitPrice = Number(item.unitPrice || item.price);
        const qty = Number(item.quantity || 1);
        const taxRate = Number(item.taxRate || 0);
        const lineTotal = (unitPrice + modTotal) * qty;
        const taxAmt = lineTotal * (taxRate / 100);

        const created = await prisma.pOSOrderItem.create({
          data: {
            orderId,
            menuItemId: item.menuItemId || null,
            name: item.name,
            quantity: qty,
            unitPrice,
            modifiers: item.modifiers || [],
            modifierTotal: modTotal,
            taxRate,
            taxAmount: taxAmt,
            total: lineTotal + taxAmt,
            notes: item.notes || null,
          },
        });
        createdItems.push(created);
      }

      // Recalculate order totals
      const allItems = await prisma.pOSOrderItem.findMany({
        where: { orderId, status: { not: 'voided' } },
      });
      const subtotal = allItems.reduce((s, i) => s + (i.unitPrice + i.modifierTotal) * i.quantity, 0);
      const taxAmount = allItems.reduce((s, i) => s + i.taxAmount, 0);

      const updated = await prisma.pOSOrder.update({
        where: { id: orderId },
        data: {
          subtotal,
          taxAmount,
          total: subtotal + taxAmount - (order.discountAmount || 0) + (order.tipAmount || 0),
        },
        include: { items: { include: { menuItem: true } }, payments: true },
      });

      return NextResponse.json({ order: updated, addedItems: createdItems });
    }

    // ── VOID ITEM ── (guardrail: reason required, audit trail)
    if (action === 'void_item') {
      const { orderId, itemId, reason, performedBy } = body;
      if (!reason) return NextResponse.json({ error: 'Reason code required for void (Standing Orders §13.3)' }, { status: 400 });

      const item = await prisma.pOSOrderItem.findUnique({ where: { id: itemId } });
      if (!item) return NextResponse.json({ error: 'Item not found' }, { status: 404 });

      await prisma.pOSOrderItem.update({
        where: { id: itemId },
        data: { status: 'voided', voidedAt: new Date(), voidedBy: performedBy || 'system', voidReason: reason },
      });

      // Recalculate
      const remaining = await prisma.pOSOrderItem.findMany({ where: { orderId, status: { not: 'voided' } } });
      const subtotal = remaining.reduce((s, i) => s + (i.unitPrice + i.modifierTotal) * i.quantity, 0);
      const taxAmount = remaining.reduce((s, i) => s + i.taxAmount, 0);
      const order = await prisma.pOSOrder.findUnique({ where: { id: orderId } });

      const updated = await prisma.pOSOrder.update({
        where: { id: orderId },
        data: { subtotal, taxAmount, total: subtotal + taxAmount - (order?.discountAmount || 0) + (order?.tipAmount || 0) },
        include: { items: { include: { menuItem: true } }, payments: true },
      });

      await logAuditEvent({
        action: 'void', resource: 'pos_order_item', resourceId: itemId,
        performedBy: performedBy || 'system', reason,
        previousState: { name: item.name, total: item.total, status: 'ordered' },
        newState: { status: 'voided' },
      });

      return NextResponse.json({ order: updated });
    }

    // ── VOID ENTIRE ORDER ── (guardrail: if payments exist, need manager approval)
    if (action === 'void_order') {
      const { orderId, reason, performedBy } = body;
      if (!reason) return NextResponse.json({ error: 'Reason required for order void (Standing Orders §14)' }, { status: 400 });

      const order = await prisma.pOSOrder.findUnique({
        where: { id: orderId },
        include: { payments: true },
      });
      if (!order) return NextResponse.json({ error: 'Order not found' }, { status: 404 });

      // §13.3: Posted/paid orders need approval
      const hasPaidPayments = order.payments.some(p => p.status === 'completed');
      if (hasPaidPayments) {
        const voidCheck = checkVoidAllowed(order.status, order.total, 'sales_order');
        if (voidCheck.requiresApproval && !body.approvedBy) {
          return NextResponse.json({
            error: 'Manager approval required for voiding order with completed payments',
            guardrail: true,
            requiresApproval: true,
            amount: order.total,
          }, { status: 409 });
        }
      }

      await prisma.pOSOrder.update({
        where: { id: orderId },
        data: { status: 'voided', voidedAt: new Date(), voidedBy: performedBy || 'system', voidReason: reason },
      });

      // Void all payments too
      for (const payment of order.payments) {
        if (payment.status === 'completed') {
          await prisma.pOSPayment.update({
            where: { id: payment.id },
            data: { status: 'voided', voidedAt: new Date(), voidedBy: performedBy || 'system', voidReason: reason },
          });
        }
      }

      await logAuditEvent({
        action: 'void', resource: 'pos_order', resourceId: orderId,
        performedBy: performedBy || 'system', reason,
        previousState: { status: order.status, total: order.total },
        newState: { status: 'voided' },
      });

      return NextResponse.json({ success: true, action: 'voided' });
    }

    // ── TRANSFER ORDER ──
    if (action === 'transfer') {
      const { orderId, toStationId, toTableNumber, performedBy } = body;
      const order = await prisma.pOSOrder.findUnique({ where: { id: orderId } });
      if (!order) return NextResponse.json({ error: 'Order not found' }, { status: 404 });

      const updated = await prisma.pOSOrder.update({
        where: { id: orderId },
        data: {
          stationId: toStationId || order.stationId,
          tableNumber: toTableNumber || order.tableNumber,
          transferredFrom: order.stationId || order.tableNumber || 'unknown',
          transferredTo: toStationId || toTableNumber || 'unknown',
        },
        include: { items: { include: { menuItem: true } }, payments: true },
      });

      await logAuditEvent({
        action: 'transfer', resource: 'pos_order', resourceId: orderId,
        performedBy: performedBy || 'system', reason: `Transferred to ${toStationId || toTableNumber}`,
        previousState: { stationId: order.stationId, tableNumber: order.tableNumber },
        newState: { stationId: updated.stationId, tableNumber: updated.tableNumber },
      });

      return NextResponse.json({ order: updated });
    }

    // ── APPLY DISCOUNT ──
    if (action === 'discount') {
      const { orderId, discountAmount, discountReason, performedBy } = body;
      if (!discountReason) return NextResponse.json({ error: 'Discount reason required' }, { status: 400 });

      const order = await prisma.pOSOrder.findUnique({ where: { id: orderId } });
      if (!order) return NextResponse.json({ error: 'Order not found' }, { status: 404 });

      // §14: Discount over threshold requires approval
      if (Number(discountAmount) >= 50 && !body.approvedBy) {
        return NextResponse.json({
          error: 'Manager approval required for discounts ≥ $50',
          guardrail: true,
          requiresApproval: true,
        }, { status: 409 });
      }

      const updated = await prisma.pOSOrder.update({
        where: { id: orderId },
        data: {
          discountAmount: Number(discountAmount),
          discountReason,
          total: order.subtotal + order.taxAmount - Number(discountAmount) + order.tipAmount,
        },
        include: { items: { include: { menuItem: true } }, payments: true },
      });

      await logAuditEvent({
        action: 'discount', resource: 'pos_order', resourceId: orderId,
        performedBy: performedBy || 'system', reason: discountReason,
        previousState: { discountAmount: order.discountAmount, total: order.total },
        newState: { discountAmount: updated.discountAmount, total: updated.total },
      });

      return NextResponse.json({ order: updated });
    }

    // ── CLOSE ORDER (after full payment) ──
    if (action === 'close') {
      const { orderId } = body;
      const order = await prisma.pOSOrder.findUnique({
        where: { id: orderId },
        include: { payments: true },
      });
      if (!order) return NextResponse.json({ error: 'Order not found' }, { status: 404 });

      const totalPaid = order.payments
        .filter(p => p.status === 'completed')
        .reduce((s, p) => s + p.amount + p.tipAmount, 0);

      if (totalPaid < order.total) {
        return NextResponse.json({
          error: `Payment incomplete. Paid: $${totalPaid.toFixed(2)}, Required: $${order.total.toFixed(2)}`,
          remaining: order.total - totalPaid,
        }, { status: 400 });
      }

      const updated = await prisma.pOSOrder.update({
        where: { id: orderId },
        data: { status: 'closed' },
        include: { items: { include: { menuItem: true } }, payments: true },
      });

      return NextResponse.json({ order: updated });
    }

    return NextResponse.json({ error: 'Unknown action' }, { status: 400 });
  } catch (error) {
    console.error('POS order error:', error);
    return NextResponse.json({ error: 'Failed to process order' }, { status: 500 });
  }
}

// DELETE — BLOCKED (Standing Orders §13 + §14)
export async function DELETE() {
  return NextResponse.json({
    error: 'POS orders cannot be deleted (Standing Orders §13 + §14). Use void_order action instead.',
    guardrail: true,
  }, { status: 403 });
}
