import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { db } from '@/lib/db';

// GET /api/dashboard/stats - Get dashboard statistics
export async function GET(request: NextRequest) {
  try {
    const session = await getServerSession(authOptions);

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

    const { searchParams } = new URL(request.url);
    const siteId = searchParams.get('siteId') || session.user.siteId;
    const dateParam = searchParams.get('date');

    // Default to today
    const targetDate = dateParam ? new Date(dateParam) : new Date();
    const startOfDay = new Date(targetDate);
    startOfDay.setHours(0, 0, 0, 0);
    const endOfDay = new Date(targetDate);
    endOfDay.setHours(23, 59, 59, 999);

    // Build where clause for site filtering
    interface SiteFilter {
      organizationId: string;
      id?: string;
    }

    const siteFilter: SiteFilter = {
      organizationId: session.user.organizationId,
    };

    if (siteId) {
      siteFilter.id = siteId;
    }

    // Get sites matching the filter
    const sites = await db.site.findMany({
      where: siteFilter,
      select: { id: true, openTime: true, closeTime: true },
    });

    const siteIds = sites.map(s => s.id);

    // 1. Today's bookings count
    const todayBookings = await db.booking.count({
      where: {
        siteId: { in: siteIds },
        startTime: {
          gte: startOfDay,
          lte: endOfDay,
        },
        status: {
          in: ['PENDING', 'CONFIRMED', 'COMPLETED'],
        },
      },
    });

    // 2. Today's revenue (from sales + booking payments)
    // Get sales from today
    const todaySales = await db.sale.aggregate({
      where: {
        createdBy: {
          organizationId: session.user.organizationId,
        },
        createdAt: {
          gte: startOfDay,
          lte: endOfDay,
        },
        ...(siteId
          ? {
              cashRegister: {
                siteId,
              },
            }
          : {}),
      },
      _sum: {
        total: true,
      },
    });

    // Get booking payments from today
    const todayBookingPayments = await db.booking.aggregate({
      where: {
        siteId: { in: siteIds },
        startTime: {
          gte: startOfDay,
          lte: endOfDay,
        },
        status: 'COMPLETED',
      },
      _sum: {
        paidAmount: true,
      },
    });

    const salesTotal = Number(todaySales._sum.total || 0);
    const bookingPaymentsTotal = Number(todayBookingPayments._sum.paidAmount || 0);
    const todayRevenue = salesTotal + bookingPaymentsTotal;

    // 3. Calculate occupancy rate
    // Get all courts for the sites
    const courts = await db.court.findMany({
      where: {
        siteId: { in: siteIds },
        isActive: true,
        status: 'AVAILABLE',
      },
      include: {
        site: {
          select: {
            openTime: true,
            closeTime: true,
          },
        },
      },
    });

    // Calculate total available hours per court for the day
    let totalAvailableSlots = 0;
    let bookedSlots = 0;

    for (const court of courts) {
      // Parse open/close times (format: "HH:MM")
      const openTime = court.site.openTime || '08:00';
      const closeTime = court.site.closeTime || '22:00';

      const [openHour] = openTime.split(':').map(Number);
      const [closeHour] = closeTime.split(':').map(Number);

      // Each slot is 1 hour
      const availableHours = closeHour - openHour;
      totalAvailableSlots += availableHours;

      // Count booked hours for this court today
      const courtBookings = await db.booking.findMany({
        where: {
          courtId: court.id,
          startTime: {
            gte: startOfDay,
            lte: endOfDay,
          },
          status: {
            in: ['PENDING', 'CONFIRMED', 'COMPLETED'],
          },
        },
        select: {
          startTime: true,
          endTime: true,
        },
      });

      // Calculate booked hours
      for (const booking of courtBookings) {
        const durationMs = booking.endTime.getTime() - booking.startTime.getTime();
        const durationHours = durationMs / (1000 * 60 * 60);
        bookedSlots += durationHours;
      }
    }

    const occupancyRate = totalAvailableSlots > 0
      ? Math.round((bookedSlots / totalAvailableSlots) * 100)
      : 0;

    // 4. Active memberships count
    const now = new Date();
    const activeMembers = await db.membership.count({
      where: {
        status: 'ACTIVE',
        endDate: {
          gte: now,
        },
        plan: {
          organizationId: session.user.organizationId,
        },
      },
    });

    // 5. Pending bookings (awaiting payment/confirmation)
    const pendingBookings = await db.booking.count({
      where: {
        siteId: { in: siteIds },
        status: 'PENDING',
        startTime: {
          gte: startOfDay,
        },
      },
    });

    // 6. Upcoming tournaments (next 30 days)
    const thirtyDaysFromNow = new Date();
    thirtyDaysFromNow.setDate(thirtyDaysFromNow.getDate() + 30);

    const upcomingTournaments = await db.tournament.count({
      where: {
        organizationId: session.user.organizationId,
        ...(siteId ? { siteId } : {}),
        startDate: {
          gte: now,
          lte: thirtyDaysFromNow,
        },
        status: {
          in: ['DRAFT', 'REGISTRATION_OPEN', 'REGISTRATION_CLOSED', 'IN_PROGRESS'],
        },
      },
    });

    // Get court occupancy details for chart
    const courtOccupancy = await Promise.all(
      courts.map(async (court) => {
        const openTime = court.site.openTime || '08:00';
        const closeTime = court.site.closeTime || '22:00';

        const [openHour] = openTime.split(':').map(Number);
        const [closeHour] = closeTime.split(':').map(Number);
        const availableHours = closeHour - openHour;

        const courtBookings = await db.booking.findMany({
          where: {
            courtId: court.id,
            startTime: {
              gte: startOfDay,
              lte: endOfDay,
            },
            status: {
              in: ['PENDING', 'CONFIRMED', 'COMPLETED'],
            },
          },
          select: {
            startTime: true,
            endTime: true,
          },
        });

        let bookedHours = 0;
        for (const booking of courtBookings) {
          const durationMs = booking.endTime.getTime() - booking.startTime.getTime();
          bookedHours += durationMs / (1000 * 60 * 60);
        }

        return {
          courtId: court.id,
          courtName: court.name,
          availableHours,
          bookedHours: Math.round(bookedHours * 10) / 10,
          occupancyPercent: availableHours > 0
            ? Math.round((bookedHours / availableHours) * 100)
            : 0,
        };
      })
    );

    // Get recent bookings for the day
    const recentBookings = await db.booking.findMany({
      where: {
        siteId: { in: siteIds },
        startTime: {
          gte: startOfDay,
          lte: endOfDay,
        },
      },
      include: {
        court: {
          select: {
            id: true,
            name: true,
          },
        },
        client: {
          select: {
            id: true,
            firstName: true,
            lastName: true,
          },
        },
      },
      orderBy: {
        startTime: 'asc',
      },
      take: 10,
    });

    return NextResponse.json({
      stats: {
        todayBookings,
        todayRevenue,
        occupancyRate,
        activeMembers,
        pendingBookings,
        upcomingTournaments,
      },
      courtOccupancy,
      recentBookings: recentBookings.map((booking) => ({
        id: booking.id,
        startTime: booking.startTime,
        endTime: booking.endTime,
        status: booking.status,
        court: booking.court,
        client: booking.client
          ? {
              id: booking.client.id,
              name: `${booking.client.firstName} ${booking.client.lastName}`,
            }
          : null,
      })),
      date: targetDate.toISOString().split('T')[0],
    });
  } catch (error) {
    console.error('Error fetching dashboard stats:', error);
    return NextResponse.json(
      { error: 'Error al obtener estadísticas del dashboard' },
      { status: 500 }
    );
  }
}
