import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { optimizeRoute, optimizeRouteBySchedule } from '@/lib/google-maps';

export async function GET(request: NextRequest) {
  try {
    const session = await getServerSession(authOptions);
    if (!session || session.user.role !== 'ADMIN') {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const { searchParams } = new URL(request.url);
    const driverId = searchParams.get('driverId');
    const status = searchParams.get('status');
    const date = searchParams.get('date');

    const where: any = {};
    if (driverId) where.driverId = driverId;
    if (status) where.status = status;
    if (date) {
      const startDate = new Date(date);
      const endDate = new Date(date);
      endDate.setDate(endDate.getDate() + 1);
      where.tourDate = {
        gte: startDate,
        lt: endDate,
      };
    }

    const tours = await prisma.tour.findMany({
      where,
      include: {
        driver: {
          select: {
            id: true,
            name: true,
            email: true,
            phoneNumber: true,
            vehiclePlate: true,
          },
        },
        bookings: {
          select: {
            id: true,
            bookingNumber: true,
            eventDate: true,
            eventAddress: true,
            eventCity: true,
            eventZip: true,
            eventLocation: true,
            customerName: true,
            setupTimeStart: true,
            setupTimeLatest: true,
          },
        },
      },
      orderBy: {
        tourDate: 'desc',
      },
    });

    return NextResponse.json({ tours });
  } catch (error: any) {
    console.error('Tour fetch error:', error);
    return NextResponse.json(
      { error: error.message || 'Failed to fetch tours' },
      { status: 500 }
    );
  }
}

export async function POST(request: NextRequest) {
  try {
    const session = await getServerSession(authOptions);
    if (!session || session.user.role !== 'ADMIN') {
      return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const body = await request.json();
    const { tourDate, driverId, bookingIds, optimizationType = 'fastest' } = body;

    if (!tourDate) {
      return NextResponse.json(
        { error: 'Tour date is required' },
        { status: 400 }
      );
    }

    const tourNumber = `TOUR-${new Date().getFullYear()}-${Date.now().toString().slice(-6)}`;

    const tour = await prisma.tour.create({
      data: {
        tourDate: new Date(tourDate),
        tourNumber,
        driverId,
        status: 'PLANNED',
      },
    });

    if (bookingIds && bookingIds.length > 0) {
      await prisma.booking.updateMany({
        where: {
          id: { in: bookingIds },
        },
        data: {
          tourId: tour.id,
          status: 'ASSIGNED',
        },
      });

      // Mark setup windows as selected for bookings with flexible setup times
      for (const bookingId of bookingIds) {
        const booking = await prisma.booking.findUnique({
          where: { id: bookingId },
          include: { setupWindows: true },
        });

        if (booking && booking.setupWindows.length > 0) {
          const tourDateStr = new Date(tourDate).toISOString().split('T')[0];
          const matchingWindow = booking.setupWindows.find((w: any) => {
            const windowDateStr = new Date(w.setupDate).toISOString().split('T')[0];
            return windowDateStr === tourDateStr && !w.selected;
          });

          if (matchingWindow) {
            await prisma.setupWindow.update({
              where: { id: matchingWindow.id },
              data: { selected: true },
            });
          }
        }
      }

      const bookings = await prisma.booking.findMany({
        where: { id: { in: bookingIds } },
        include: { setupWindows: true },
        select: {
          eventAddress: true,
          eventCity: true,
          eventZip: true,
          setupTimeStart: true,
          setupTimeLatest: true,
          setupWindows: true,
        },
      });

      // Create TourStops for each booking
      const fullBookings = await prisma.booking.findMany({
        where: { id: { in: bookingIds } },
        include: { setupWindows: true },
        orderBy: { setupTimeStart: 'asc' },
      });

      try {
        // For route optimization, use the selected setup window time if available
        const stopsWithSetupTimes = bookings.map((booking: any) => {
          const tourDateStr = new Date(tourDate).toISOString().split('T')[0];
          const selectedWindow = booking.setupWindows?.find((w: any) => w.selected);
          
          if (selectedWindow) {
            return {
              eventAddress: booking.eventAddress,
              eventCity: booking.eventCity,
              eventZip: booking.eventZip,
              setupTimeStart: selectedWindow.setupTimeStart,
              setupTimeLatest: selectedWindow.setupTimeEnd,
            };
          }
          
          return {
            eventAddress: booking.eventAddress,
            eventCity: booking.eventCity,
            eventZip: booking.eventZip,
            setupTimeStart: booking.setupTimeStart,
            setupTimeLatest: booking.setupTimeLatest,
          };
        });

        const routeData = optimizationType === 'schedule'
          ? await optimizeRouteBySchedule(stopsWithSetupTimes)
          : await optimizeRoute(stopsWithSetupTimes);
          
        await prisma.tour.update({
          where: { id: tour.id },
          data: {
            routeOptimized: routeData as any,
            totalDistance: routeData.totalDistance,
            estimatedDuration: routeData.totalDuration,
          },
        });

        // Create TourStops based on optimized order
        const optimizedOrder = routeData.optimizedOrder || fullBookings.map((_, i) => i);
        for (let i = 0; i < optimizedOrder.length; i++) {
          const orderIndex = optimizedOrder[i];
          const booking = fullBookings[orderIndex];
          
          await prisma.tourStop.create({
            data: {
              tourId: tour.id,
              bookingId: booking.id,
              stopOrder: i + 1,
              stopType: 'DELIVERY',
              status: 'PENDING',
            },
          });
        }
      } catch (routeError) {
        console.error('Route optimization error:', routeError);
        
        // If route optimization fails, create TourStops in simple order
        for (let i = 0; i < fullBookings.length; i++) {
          await prisma.tourStop.create({
            data: {
              tourId: tour.id,
              bookingId: fullBookings[i].id,
              stopOrder: i + 1,
              stopType: 'DELIVERY',
              status: 'PENDING',
            },
          });
        }
      }
    }

    const updatedTour = await prisma.tour.findUnique({
      where: { id: tour.id },
      include: {
        driver: true,
        bookings: true,
      },
    });

    return NextResponse.json({ tour: updatedTour }, { status: 201 });
  } catch (error: any) {
    console.error('Tour creation error:', error);
    return NextResponse.json(
      { error: error.message || 'Failed to create tour' },
      { status: 500 }
    );
  }
}
