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

export const dynamic = 'force-dynamic';

function generatePaymentNumber(): string {
  return `PAY-${Date.now()}-${Math.floor(Math.random() * 9999).toString().padStart(4, '0')}`;
}

// POST — Process payment (cash, card, split)
export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const { action } = body;

    // ── PROCESS PAYMENT ──
    if (action === 'pay' || !action) {
      const { orderId, method, amount, tipAmount, tendered, cardLast4, cardBrand, referenceNumber, cashierId } = body;

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

      const tip = Number(tipAmount || 0);
      const payAmt = Number(amount);
      const tend = Number(tendered || payAmt);
      const changeDue = method === 'cash' ? Math.max(0, tend - payAmt - tip) : 0;

      const payment = await prisma.pOSPayment.create({
        data: {
          orderId,
          paymentNumber: generatePaymentNumber(),
          method: method || 'cash',
          amount: payAmt,
          tipAmount: tip,
          tendered: tend,
          changeDue,
          cardLast4: cardLast4 || null,
          cardBrand: cardBrand || null,
          referenceNumber: referenceNumber || null,
          status: 'completed',
        },
      });

      // Update order tip
      const allPayments = await prisma.pOSPayment.findMany({
        where: { orderId, status: 'completed' },
      });
      const totalTips = allPayments.reduce((s, p) => s + p.tipAmount, 0);
      const totalPaid = allPayments.reduce((s, p) => s + p.amount, 0);

      const orderUpdate: Record<string, unknown> = { tipAmount: totalTips };
      // Auto-close if fully paid
      if (totalPaid >= order.total) {
        orderUpdate.status = 'closed';
      } else {
        orderUpdate.status = 'partial';
      }

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

      await logAuditEvent({
        action: 'payment', resource: 'pos_payment', resourceId: payment.id,
        performedBy: cashierId || 'system',
        reason: `${method} payment of $${payAmt.toFixed(2)}` + (tip > 0 ? ` + $${tip.toFixed(2)} tip` : ''),
        previousState: { orderStatus: order.status },
        newState: { paymentId: payment.id, orderStatus: updated.status, totalPaid },
      });

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

    // ── REFUND ── (guardrail: reason + approval for ≥$100)
    if (action === 'refund') {
      const { paymentId, amount, reason, performedBy } = body;
      if (!reason) return NextResponse.json({ error: 'Refund reason required (Standing Orders §14)' }, { status: 400 });

      const payment = await prisma.pOSPayment.findUnique({ where: { id: paymentId }, include: { order: true } });
      if (!payment) return NextResponse.json({ error: 'Payment not found' }, { status: 404 });

      const refundAmt = Number(amount || payment.amount);

      // §13 + §14: Refunds ≥ $100 require manager approval
      if (refundAmt >= 100 && !body.approvedBy) {
        return NextResponse.json({
          error: 'Manager approval required for refunds ≥ $100',
          guardrail: true,
          requiresApproval: true,
          amount: refundAmt,
        }, { status: 409 });
      }

      // Create refund as negative payment
      const refund = await prisma.pOSPayment.create({
        data: {
          orderId: payment.orderId,
          paymentNumber: generatePaymentNumber(),
          method: payment.method,
          amount: -refundAmt,
          status: 'completed',
          approvedBy: body.approvedBy || null,
          metadata: { refundOf: paymentId, reason } as Record<string, string>,
        },
      });

      await logAuditEvent({
        action: 'refund', resource: 'pos_payment', resourceId: refund.id,
        performedBy: performedBy || 'system', reason: `Refund: ${reason}`,
        previousState: { paymentId, amount: payment.amount },
        newState: { refundId: refund.id, refundAmount: -refundAmt },
      });

      return NextResponse.json({ refund, originalPayment: payment });
    }

    // ── VOID PAYMENT ── (guardrail: reason required, immutable audit)
    if (action === 'void') {
      const { paymentId, reason, performedBy } = body;
      if (!reason) return NextResponse.json({ error: 'Void reason required (Standing Orders §13.3)' }, { status: 400 });

      const payment = await prisma.pOSPayment.findUnique({ where: { id: paymentId } });
      if (!payment) return NextResponse.json({ error: 'Payment not found' }, { status: 404 });

      const voidCheck = checkVoidAllowed(payment.status, payment.amount, 'transaction');
      if (voidCheck.requiresApproval && !body.approvedBy) {
        return NextResponse.json({
          error: `Manager approval required for voiding payment of $${payment.amount.toFixed(2)}`,
          guardrail: true,
          requiresApproval: true,
        }, { status: 409 });
      }

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

      // Reopen the order
      await prisma.pOSOrder.update({
        where: { id: payment.orderId },
        data: { status: 'open' },
      });

      await logAuditEvent({
        action: 'void', resource: 'pos_payment', resourceId: paymentId,
        performedBy: performedBy || 'system', reason,
        previousState: { status: payment.status, amount: payment.amount },
        newState: { status: 'voided' },
      });

      return NextResponse.json({ success: true });
    }

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

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