import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { db } from '@/lib/db';
import { z } from 'zod';
import { Decimal } from '@prisma/client/runtime/library';

interface RouteContext {
  params: Promise<{ id: string }>;
}

// Validation schema for manual transaction
const manualTransactionSchema = z.object({
  type: z.enum(['DEPOSIT', 'WITHDRAWAL']),
  amount: z.number().positive('Amount must be positive'),
  reason: z.string().min(1, 'Reason is required').max(500),
});

// GET /api/cash-register/[id]/transactions - List all transactions for this register
export async function GET(
  request: NextRequest,
  context: RouteContext
) {
  try {
    const session = await getServerSession(authOptions);

    if (!session?.user) {
      return NextResponse.json(
        { error: 'Unauthorized' },
        { status: 401 }
      );
    }

    const { id } = await context.params;

    // Verify the cash register exists and belongs to user's organization
    const cashRegister = await db.cashRegister.findFirst({
      where: {
        id,
        site: {
          organizationId: session.user.organizationId,
        },
      },
    });

    if (!cashRegister) {
      return NextResponse.json(
        { error: 'Cash register not found' },
        { status: 404 }
      );
    }

    // Get all payments (transactions) for this register
    const transactions = await db.payment.findMany({
      where: {
        cashRegisterId: id,
      },
      include: {
        booking: {
          select: {
            id: true,
            startTime: true,
            endTime: true,
            court: {
              select: {
                name: true,
              },
            },
            client: {
              select: {
                firstName: true,
                lastName: true,
              },
            },
          },
        },
        sale: {
          select: {
            id: true,
            total: true,
            items: {
              select: {
                product: {
                  select: {
                    name: true,
                  },
                },
                quantity: true,
              },
            },
          },
        },
        client: {
          select: {
            id: true,
            firstName: true,
            lastName: true,
          },
        },
      },
      orderBy: {
        createdAt: 'desc',
      },
    });

    // Categorize transactions
    const categorizedTransactions = transactions.map(transaction => {
      let category: string;
      let description: string;

      if (transaction.booking) {
        category = 'BOOKING';
        const client = transaction.booking.client;
        description = `Booking payment${client ? ` - ${client.firstName} ${client.lastName}` : ''} - ${transaction.booking.court?.name || 'Unknown court'}`;
      } else if (transaction.sale) {
        category = 'SALE';
        const itemCount = transaction.sale.items.reduce((sum, item) => sum + item.quantity, 0);
        description = `Sale payment - ${itemCount} item(s)`;
      } else if (transaction.notes?.startsWith('DEPOSIT:') || transaction.notes?.startsWith('WITHDRAWAL:')) {
        category = transaction.notes.startsWith('DEPOSIT:') ? 'DEPOSIT' : 'WITHDRAWAL';
        description = transaction.notes.substring(transaction.notes.indexOf(':') + 1).trim();
      } else {
        category = 'OTHER';
        description = transaction.notes || 'Unknown transaction';
      }

      return {
        id: transaction.id,
        amount: transaction.amount,
        paymentType: transaction.paymentType,
        reference: transaction.reference,
        category,
        description,
        createdAt: transaction.createdAt,
        bookingId: transaction.booking?.id || null,
        saleId: transaction.sale?.id || null,
        client: transaction.client,
      };
    });

    // Calculate summary
    const summary = {
      totalDeposits: categorizedTransactions
        .filter(t => t.category === 'DEPOSIT')
        .reduce((sum, t) => sum + Number(t.amount), 0),
      totalWithdrawals: categorizedTransactions
        .filter(t => t.category === 'WITHDRAWAL')
        .reduce((sum, t) => sum + Number(t.amount), 0),
      totalBookingPayments: categorizedTransactions
        .filter(t => t.category === 'BOOKING')
        .reduce((sum, t) => sum + Number(t.amount), 0),
      totalSalePayments: categorizedTransactions
        .filter(t => t.category === 'SALE')
        .reduce((sum, t) => sum + Number(t.amount), 0),
      totalOther: categorizedTransactions
        .filter(t => t.category === 'OTHER')
        .reduce((sum, t) => sum + Number(t.amount), 0),
      transactionCount: categorizedTransactions.length,
    };

    return NextResponse.json({
      transactions: categorizedTransactions,
      summary,
    });
  } catch (error) {
    console.error('Error fetching transactions:', error);
    return NextResponse.json(
      { error: 'Failed to fetch transactions' },
      { status: 500 }
    );
  }
}

// POST /api/cash-register/[id]/transactions - Add manual transaction (deposit/withdrawal)
export async function POST(
  request: NextRequest,
  context: RouteContext
) {
  try {
    const session = await getServerSession(authOptions);

    if (!session?.user) {
      return NextResponse.json(
        { error: 'Unauthorized' },
        { status: 401 }
      );
    }

    // Check if user has appropriate role
    const allowedRoles = ['SUPER_ADMIN', 'ORG_ADMIN', 'SITE_ADMIN', 'RECEPTIONIST'];
    if (!allowedRoles.includes(session.user.role)) {
      return NextResponse.json(
        { error: 'Forbidden: Insufficient permissions' },
        { status: 403 }
      );
    }

    const { id } = await context.params;

    // Verify the cash register exists and belongs to user's organization
    const cashRegister = await db.cashRegister.findFirst({
      where: {
        id,
        site: {
          organizationId: session.user.organizationId,
        },
      },
    });

    if (!cashRegister) {
      return NextResponse.json(
        { error: 'Cash register not found' },
        { status: 404 }
      );
    }

    // Check if register is already closed
    if (cashRegister.closedAt) {
      return NextResponse.json(
        { error: 'Cannot add transactions to a closed cash register' },
        { status: 400 }
      );
    }

    // If user is SITE_ADMIN or RECEPTIONIST, verify they have access to this site
    if (['SITE_ADMIN', 'RECEPTIONIST'].includes(session.user.role) && session.user.siteId !== cashRegister.siteId) {
      return NextResponse.json(
        { error: 'Forbidden: You do not have access to this cash register' },
        { status: 403 }
      );
    }

    const body = await request.json();

    // Validate input with Zod schema
    const validationResult = manualTransactionSchema.safeParse(body);
    if (!validationResult.success) {
      return NextResponse.json(
        {
          error: 'Invalid transaction data',
          details: validationResult.error.flatten().fieldErrors,
        },
        { status: 400 }
      );
    }

    const { type, amount, reason } = validationResult.data;

    // For withdrawals, verify there's enough cash in the register
    if (type === 'WITHDRAWAL') {
      // Get current cash balance
      const cashPayments = await db.payment.aggregate({
        where: {
          cashRegisterId: id,
          paymentType: 'CASH',
        },
        _sum: {
          amount: true,
        },
      });

      const totalCashPayments = cashPayments._sum.amount ? Number(cashPayments._sum.amount) : 0;
      const currentCashBalance = Number(cashRegister.openingAmount) + totalCashPayments;

      if (amount > currentCashBalance) {
        return NextResponse.json(
          { error: `Insufficient cash balance. Available: ${currentCashBalance.toFixed(2)}, Requested: ${amount.toFixed(2)}` },
          { status: 400 }
        );
      }
    }

    // Create the payment record
    // For deposits, amount is positive; for withdrawals, amount is negative in the payment record
    const paymentAmount = type === 'WITHDRAWAL' ? -amount : amount;

    const transaction = await db.payment.create({
      data: {
        amount: new Decimal(paymentAmount),
        paymentType: 'CASH',
        notes: `${type}: ${reason}`,
        cashRegisterId: id,
      },
    });

    return NextResponse.json({
      id: transaction.id,
      type,
      amount: Math.abs(Number(transaction.amount)),
      reason,
      createdAt: transaction.createdAt,
      message: `${type.toLowerCase()} of ${amount.toFixed(2)} recorded successfully`,
    }, { status: 201 });
  } catch (error) {
    console.error('Error creating transaction:', error);
    return NextResponse.json(
      { error: 'Failed to create transaction' },
      { status: 500 }
    );
  }
}
