import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Form, FormControl, FormDescription, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import { Textarea } from "@/components/ui/textarea";
import { ComboboxMulti } from './ComboboxMulti';
import { cn } from "@/lib/utils";
import { format } from "date-fns";
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import * as z from 'zod';
import { Badge } from "@/components/ui/badge";
import { CalendarIcon, Clock, AlertCircle } from "lucide-react";
import { MeetingRoom, Employee, RoomBookingCreateRequest, RoomBooking } from '@/types';
import { userSessionService, roomBookingService } from '@/lib/api';

interface BookingFormProps {
  room?: MeetingRoom;
  employees: Employee[];
  onSuccess?: () => void;
  onCancel?: () => void;
  defaultValues?: {
    startTime?: Date;
    endTime?: Date;
  };
  existingBooking?: RoomBooking;
  isEditing?: boolean;
}

const timeOptions = Array.from({ length: 24 * 4 }, (_, i) => {
  const hour = Math.floor(i / 4);
  const minute = (i % 4) * 15;
  return {
    value: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`,
    label: `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`,
  };
});

const bookingFormSchema = z.object({
  title: z.string().min(3, {
    message: "Title must be at least 3 characters.",
  }),
  date: z.date({
    required_error: "Please select a date.",
  }),
  startTime: z.string({
    required_error: "Please select a start time.",
  }),
  endTime: z.string({
    required_error: "Please select an end time.",
  }),
  attendees: z.array(z.number()).min(1, {
    message: "Please select at least one attendee.",
  }),
  description: z.string().optional(),
  // Status field is not editable by the user, it will be set to 'pending' automatically
}).refine((data) => {
  // Convert times to numbers for comparison
  const start = data.startTime.replace(':', '');
  const end = data.endTime.replace(':', '');
  return start < end;
}, {
  message: "End time must be after start time",
  path: ["endTime"],
});

type FormValues = z.infer<typeof bookingFormSchema>;

const BookingForm: React.FC<BookingFormProps> = ({ 
  room, 
  employees, 
  onSuccess, 
  onCancel,
  defaultValues,
  existingBooking,
  isEditing
}) => {
  const navigate = useNavigate();
  const currentUser = userSessionService.getSession();
  const [isSubmitting, setIsSubmitting] = useState(false);
  
  const form = useForm<FormValues>({
    resolver: zodResolver(bookingFormSchema),
    defaultValues: {
      title: existingBooking?.title || '',
      date: existingBooking?.startTime ? new Date(existingBooking.startTime) : defaultValues?.startTime || new Date(),
      startTime: existingBooking?.startTime 
        ? format(new Date(existingBooking.startTime), 'HH:mm') 
        : defaultValues?.startTime 
        ? format(defaultValues.startTime, 'HH:mm') 
        : format(new Date(), 'HH:mm'),
      endTime: existingBooking?.endTime 
        ? format(new Date(existingBooking.endTime), 'HH:mm') 
        : defaultValues?.endTime 
        ? format(defaultValues.endTime, 'HH:mm') 
        : format(new Date(new Date().getTime() + 60 * 60 * 1000), 'HH:mm'),
      attendees: existingBooking?.attendees || currentUser ? [...(existingBooking?.attendees || []), currentUser?.employeeId] : [],
      description: existingBooking?.description || '',
    },
  });

  // Filter out the current user from attendees options and organize by name
  const attendeeOptions = React.useMemo(() => {
    // Make sure employees is an array
    const safeEmployees = Array.isArray(employees) ? employees : [];
    
    const attendees = safeEmployees
      .filter(emp => emp.id !== currentUser?.employeeId)
      .map(emp => ({
        value: emp.id,
        label: `${emp.firstName} ${emp.lastName}`,
      }));
    
    // Sort alphabetically by label
    return attendees.sort((a, b) => a.label.localeCompare(b.label));
  }, [employees, currentUser]);

  const onSubmit = async (data: FormValues) => {
    if (!room || !currentUser) {
      console.error('Missing room or user data:', { room, currentUser });
      return;
    }
    
    setIsSubmitting(true);
    console.log('Submitting booking form with data:', data);
    
    try {
      // Combine date and time
      const startDate = new Date(data.date);
      const [startHours, startMinutes] = data.startTime.split(':').map(Number);
      startDate.setHours(startHours, startMinutes, 0, 0);
      
      const endDate = new Date(data.date);
      const [endHours, endMinutes] = data.endTime.split(':').map(Number);
      endDate.setHours(endHours, endMinutes, 0, 0);

      // Ensure attendees array is valid
      const attendees = Array.isArray(data.attendees) ? data.attendees : [];
      
      // Ensure current user is included
      if (!attendees.includes(currentUser.employeeId)) {
        attendees.push(currentUser.employeeId);
      }

      if (isEditing && existingBooking) {
        // Update existing booking
        const bookingData = {
          id: existingBooking.id,
          roomId: room.id,
          roomName: room.name,
          title: data.title,
          startTime: startDate.toISOString(),
          endTime: endDate.toISOString(),
          attendees: attendees,
          description: data.description || "",
          // Maintain the current status unless admin is changing it
          status: existingBooking.status,
          employeeId: currentUser.employeeId,
          employeeName: `${currentUser.firstName} ${currentUser.lastName}`
        };
        
        console.log('Updating booking data:', bookingData);
        
        await roomBookingService.updateBooking(bookingData);
        console.log('Booking updated successfully');
        
        alert(`Room "${room.name}" booking updated successfully!`);
      } else {
        // Create new booking
        const bookingData: RoomBookingCreateRequest = {
          roomId: room.id,
          roomName: room.name,
          employeeId: currentUser.employeeId,
          employeeName: `${currentUser.firstName} ${currentUser.lastName}`,
          title: data.title,
          startTime: startDate.toISOString(),
          endTime: endDate.toISOString(),
          attendees: attendees,
          description: data.description || "",
          status: 'pending',
          createdAt: new Date().toISOString(),
          updatedAt: new Date().toISOString(),
        };
        
        console.log('Creating new booking with data:', bookingData);
        
        await roomBookingService.createBooking(bookingData);
        console.log('Booking created successfully');
        
        alert(`Room "${room.name}" booked successfully!\n\nStatus: Pending Approval\n\nYour booking will be reviewed by an administrator.`);
      }
      
      // Use a timeout to ensure the alert has time to be displayed before navigation
      setTimeout(() => {
        if (onSuccess) {
          onSuccess();
        } else {
          // Use relative navigation with hash to ensure page refresh
          const baseUrl = window.location.origin;
          const bookingsPath = "/meeting-room/bookings";
          
          // Create a timestamp to force a page refresh
          const timestamp = new Date().getTime();
          const fullUrl = `${baseUrl}${bookingsPath}#${timestamp}`;
          
          // Use full URL to navigate
          window.location.href = fullUrl;
        }
      }, 500); // Increased timeout to give more time for alert to be seen
    } catch (error) {
      console.error('Failed to process booking:', error);
      alert(`There was an error ${isEditing ? 'updating' : 'creating'} the booking. Please try again.`);
    } finally {
      setIsSubmitting(false);
    }
  };

  return (
    <Card className="w-full max-w-3xl mx-auto">
      <CardHeader>
        <CardTitle>{isEditing ? 'Edit Booking' : 'Book a Meeting Room'}</CardTitle>
        <CardDescription>
          {room ? (
            <div className="flex flex-col gap-1 mt-1">
              <div>Room: <span className="font-medium">{room.name}</span> (Capacity: {room.capacity})</div>
              {!isEditing && (
                <div className="flex items-center gap-2">
                  <span>Booking Status:</span>
                  <Badge variant="outline" className="bg-yellow-50 text-yellow-700 border-yellow-200">
                    <AlertCircle className="mr-1 h-3 w-3" /> Pending Approval
                  </Badge>
                </div>
              )}
              {isEditing && existingBooking && (
                <div className="flex items-center gap-2">
                  <span>Current Status:</span>
                  <Badge 
                    variant={
                      existingBooking.status === 'approved' ? 'default' : 
                      existingBooking.status === 'rejected' ? 'destructive' : 
                      existingBooking.status === 'cancelled' ? 'outline' : 
                      'secondary'
                    }
                    className="capitalize"
                  >
                    {existingBooking.status || 'pending'}
                  </Badge>
                </div>
              )}
            </div>
          ) : (
            'Complete the form to book a meeting room'
          )}
        </CardDescription>
      </CardHeader>
      <CardContent>
        <Form {...form}>
          <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
            <FormField
              control={form.control}
              name="title"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Meeting Title</FormLabel>
                  <FormControl>
                    <Input placeholder="Team standup" {...field} />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            
            <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
              <FormField
                control={form.control}
                name="date"
                render={({ field }) => (
                  <FormItem className="flex flex-col">
                    <FormLabel>Date</FormLabel>
                    <Popover>
                      <PopoverTrigger asChild>
                        <FormControl>
                          <Button
                            variant="outline"
                            className={cn(
                              "w-full pl-3 text-left font-normal",
                              !field.value && "text-muted-foreground"
                            )}
                          >
                            {field.value ? (
                              format(field.value, "PPP")
                            ) : (
                              <span>Pick a date</span>
                            )}
                            <CalendarIcon className="ml-auto h-4 w-4 opacity-50" />
                          </Button>
                        </FormControl>
                      </PopoverTrigger>
                      <PopoverContent className="w-auto p-0" align="start">
                        <Calendar
                          mode="single"
                          selected={field.value}
                          onSelect={field.onChange}
                          disabled={(date) => date < new Date(new Date().setHours(0, 0, 0, 0))}
                          initialFocus
                        />
                      </PopoverContent>
                    </Popover>
                    <FormMessage />
                  </FormItem>
                )}
              />
              
              <div className="grid grid-cols-2 gap-4">
                <FormField
                  control={form.control}
                  name="startTime"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>Start Time</FormLabel>
                      <FormControl>
                        <div className="flex items-center">
                          <Clock className="mr-2 h-4 w-4 text-muted-foreground" />
                          <select
                            className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
                            value={field.value}
                            onChange={field.onChange}
                          >
                            {timeOptions.map((option) => (
                              <option key={option.value} value={option.value}>
                                {option.label}
                              </option>
                            ))}
                          </select>
                        </div>
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />
                
                <FormField
                  control={form.control}
                  name="endTime"
                  render={({ field }) => (
                    <FormItem>
                      <FormLabel>End Time</FormLabel>
                      <FormControl>
                        <div className="flex items-center">
                          <Clock className="mr-2 h-4 w-4 text-muted-foreground" />
                          <select
                            className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
                            value={field.value}
                            onChange={field.onChange}
                          >
                            {timeOptions.map((option) => (
                              <option key={option.value} value={option.value}>
                                {option.label}
                              </option>
                            ))}
                          </select>
                        </div>
                      </FormControl>
                      <FormMessage />
                    </FormItem>
                  )}
                />
              </div>
            </div>
            
            <FormField
              control={form.control}
              name="attendees"
              render={({ field }) => {
                // Make sure we have a valid array for the field value
                const fieldValue = Array.isArray(field.value) ? field.value : [];
                
                // Check if we have any attendee options
                const hasOptions = Array.isArray(attendeeOptions) && attendeeOptions.length > 0;
                
                // Get current user name for display
                const currentUserName = currentUser ? 
                  `${currentUser.firstName} ${currentUser.lastName}` : 
                  'You';
                
                return (
                  <FormItem>
                    <FormLabel>Meeting Attendees</FormLabel>
                    <FormControl>
                      <ComboboxMulti 
                        options={hasOptions ? attendeeOptions : []}
                        selectedValues={fieldValue}
                        onValuesChange={(values) => {
                          try {
                            // Ensure values is an array
                            const safeValues = Array.isArray(values) ? values : [];
                            
                            // Ensure current user is always included
                            if (currentUser && !safeValues.includes(currentUser.employeeId)) {
                              const updatedValues = [currentUser.employeeId, ...safeValues];
                              field.onChange(updatedValues);
                            } else {
                              field.onChange(safeValues);
                            }
                          } catch (error) {
                            console.error("Error updating attendees:", error);
                            // Fallback to empty array if there's an error
                            field.onChange(currentUser ? [currentUser.employeeId] : []);
                          }
                        }}
                        placeholder={hasOptions ? "Select meeting attendees..." : "No other attendees available"}
                        emptyText={hasOptions ? "No matching employees found" : "No other employees available"}
                        label="Attendees"
                      />
                    </FormControl>
                    <FormDescription>
                      {currentUserName} will be automatically added as an attendee. {hasOptions ? 'Search for additional attendees by name.' : ''}
                    </FormDescription>
                    <FormMessage />
                  </FormItem>
                );
              }}
            />
            
            <FormField
              control={form.control}
              name="description"
              render={({ field }) => (
                <FormItem>
                  <FormLabel>Description (Optional)</FormLabel>
                  <FormControl>
                    <Textarea 
                      placeholder="Meeting agenda, preparation details, etc."
                      className="resize-none"
                      {...field}
                    />
                  </FormControl>
                  <FormMessage />
                </FormItem>
              )}
            />
            
            <CardFooter className="flex justify-between px-0 pb-0">
              <Button 
                type="button" 
                variant="outline" 
                onClick={onCancel}
              >
                Cancel
              </Button>
              <Button 
                type="submit" 
                disabled={isSubmitting}
              >
                {isSubmitting 
                  ? (isEditing ? "Updating..." : "Booking...") 
                  : (isEditing ? "Update Booking" : "Book Room")
                }
              </Button>
            </CardFooter>
          </form>
        </Form>
      </CardContent>
    </Card>
  );
};

export default BookingForm; 