import React, { useState, useEffect } from "react";
import { format, isSameDay, parseISO } from "date-fns";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { TimeLog, timeLogApi, TimeLogCreateRequest } from "@/services/timeLogApi";
import { Task, tasksApi } from "@/services/tasksApi";
import { useAuth } from "@/lib/auth-context";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import { PopoverContent, PopoverTrigger, Popover } from "@/components/ui/popover";
import { Calendar } from "@/components/ui/calendar";
import { cn } from "@/lib/utils";
import { CalendarIcon, Check, Clock, Loader2, X, AlertCircle } from "lucide-react";
import { CustomSelect } from "@/components/ui/custom-select";
import { showToast } from "@/components/toast-utils";
import { CustomDateInput } from "@/components/ui/custom-date-input";
import { Dropdown } from "@/components/ui/dropdown";
import SlateRichTextEditor from "@/components/custom/SlateRichTextEditor";

interface AddTimeLogDialogProps {
  isOpen: boolean;
  onClose: () => void;
  taskId?: number; // Optional taskId - when provided, the task dropdown will be pre-selected and disabled
  onTimeLogAdded?: () => void; // Optional callback after successful creation
  editMode?: boolean; // Whether we're editing an existing time log
  timeLogToEdit?: TimeLog | null; // The time log to edit when in edit mode
}

export default function AddTimeLogDialog({ 
  isOpen, 
  onClose,
  taskId,
  onTimeLogAdded,
  editMode = false,
  timeLogToEdit = null
}: AddTimeLogDialogProps) {
  const { userData } = useAuth();
  const queryClient = useQueryClient();
  
  // Form state
  const [workDate, setWorkDate] = useState<Date>(new Date());
  const [startTime, setStartTime] = useState("9:30 AM");
  const [endTime, setEndTime] = useState("10:00 AM");
  const [timeLogHours, setTimeLogHours] = useState("");
  const [remainingHours, setRemainingHours] = useState("");
  const [timeLogDescription, setTimeLogDescription] = useState("");
  const [selectedTask, setSelectedTask] = useState<number | null>(taskId || null);
  const [timeLogId, setTimeLogId] = useState<number | null>(null);
  
  // Validation state
  const [descriptionError, setDescriptionError] = useState(false);
  
  // Submission prevention state
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [lastSubmissionTime, setLastSubmissionTime] = useState<number>(0);

  // Function to calculate hours between two time strings with AM/PM format
  const calculateHoursSpent = (startTime: string, endTime: string): string => {
    if (!startTime || !endTime) return "";
    
    // Parse start time
    const startParts = startTime.split(' ');
    const [startHourMin, startAmPm] = [startParts[0], startParts[1]];
    let [startHour, startMinute] = startHourMin.split(':').map(Number);
    
    // Convert to 24-hour format for calculation
    if (startAmPm === 'PM' && startHour < 12) startHour += 12;
    if (startAmPm === 'AM' && startHour === 12) startHour = 0;
    
    // Parse end time
    const endParts = endTime.split(' ');
    const [endHourMin, endAmPm] = [endParts[0], endParts[1]];
    let [endHour, endMinute] = endHourMin.split(':').map(Number);
    
    // Convert to 24-hour format for calculation
    if (endAmPm === 'PM' && endHour < 12) endHour += 12;
    if (endAmPm === 'AM' && endHour === 12) endHour = 0;
    
    // Convert to minutes then calculate the difference
    const startMinutes = startHour * 60 + startMinute;
    const endMinutes = endHour * 60 + endMinute;
    
    // Handle case where end time is on the next day
    const diffMinutes = endMinutes >= startMinutes 
      ? endMinutes - startMinutes 
      : (24 * 60 - startMinutes) + endMinutes;
    
    // Convert minutes to hours with two decimal places
    return (diffMinutes / 60).toFixed(2);
  };
  
  // Add function to convert AM/PM time format to 24-hour format
  const convertTo24HourFormat = (timeStr: string): string => {
    if (!timeStr) return "";
    
    const timeParts = timeStr.split(' ');
    const [hourMin, ampm] = [timeParts[0], timeParts[1]];
    let [hour, minute] = hourMin.split(':').map(Number);
    
    // Convert to 24-hour format
    if (ampm === 'PM' && hour < 12) hour += 12;
    if (ampm === 'AM' && hour === 12) hour = 0;
    
    return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
  };
  
  // Reset form when dialog opens or taskId changes, or populate with edit data
  useEffect(() => {
    if (isOpen) {
      if (editMode && timeLogToEdit) {
        // Add debug logging
        console.log('Editing time log:', timeLogToEdit);
        console.log('Original time formats:', { 
          startTime: timeLogToEdit.startTime, 
          endTime: timeLogToEdit.endTime,
          hasAMPM: timeLogToEdit.startTime.includes(' ')
        });
        
        // Populate form with data from the time log being edited
        setTimeLogId(timeLogToEdit.id);
        setWorkDate(new Date(timeLogToEdit.workDate));
        
        // Fix for start and end time format issues:
        // Check if time already has AM/PM format, if not, convert from 24-hour format
        if (timeLogToEdit.startTime && !timeLogToEdit.startTime.includes(' ')) {
          // Convert from 24-hour format to AM/PM
          const convertFrom24Hour = (time24: string): string => {
            const [hour, minute] = time24.split(':').map(Number);
            const period = hour >= 12 ? 'PM' : 'AM';
            const hour12 = hour % 12 || 12; // Convert 0 to 12 for 12 AM
            return `${hour12}:${minute.toString().padStart(2, '0')} ${period}`;
          };
          
          setStartTime(convertFrom24Hour(timeLogToEdit.startTime));
          setEndTime(convertFrom24Hour(timeLogToEdit.endTime));
        } else {
          setStartTime(timeLogToEdit.startTime);
          setEndTime(timeLogToEdit.endTime);
        }
        
        setTimeLogHours(timeLogToEdit.hrsSpent.toString());
        setRemainingHours(timeLogToEdit.remainingHr.toString());
        // Ensure description is properly formatted for the rich text editor
        setTimeLogDescription(timeLogToEdit.comments || "");
        setSelectedTask(timeLogToEdit.taskId);
        setDescriptionError(false);
      } else {
        // Reset form for new time log - default start time to 9:30 AM
        setTimeLogId(null);
        setWorkDate(new Date());
        setStartTime("9:30 AM");
        setEndTime("10:00 AM");
        // Calculate hours spent
        setTimeLogHours(calculateHoursSpent("9:30 AM", "10:00 AM"));
        setTimeLogDescription("");
        setSelectedTask(taskId || null);
        setDescriptionError(false);
        
        // If taskId is provided, also fetch the task to get the remaining hours
        if (taskId) {
          tasksApi.getById(taskId).then(task => {
            if (task?.remainingHr) {
              setRemainingHours(task.remainingHr.toString());
            } else {
              setRemainingHours("");
            }
          }).catch(error => {
            console.error("Error fetching task details:", error);
            setRemainingHours("");
          });
        } else {
          setRemainingHours("");
        }
      }
    }
  }, [isOpen, taskId, editMode, timeLogToEdit]);

  // Fetch tasks for dropdown
  const { 
    data: tasks = [], 
    isLoading: isLoadingTasks,
    error: tasksError 
  } = useQuery({
    queryKey: ["tasks"],
    queryFn: () => tasksApi.getAll(),
  });

  // Create task dropdown options
  const taskOptions = tasks.map(task => ({
    label: `${task.title} (ID: ${task.id})`,
    value: task.id.toString()
  }));

  // Create mutation
  const createMutation = useMutation({
    mutationFn: () => {
      // Convert AM/PM time to 24-hour format for API
      const startTime24 = convertTo24HourFormat(startTime);
      const endTime24 = convertTo24HourFormat(endTime);
      
      return timeLogApi.create({
        workDate: format(workDate, "yyyy-MM-dd"),
        startTime: startTime24, // Using 24-hour format
        endTime: endTime24, // Using 24-hour format
        comments: timeLogDescription, // Rich text HTML content
        createdBy: userData?.userId ? `${userData.userId}` : "",
        updatedBy: userData?.userId ? `${userData.userId}` : "",
        taskId: selectedTask || 0,
        hrsSpent: parseFloat(timeLogHours) || 0,
        remainingHr: parseFloat(remainingHours) || 0,
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["timeLogs"] });
      if (taskId) {
        queryClient.invalidateQueries({ queryKey: ["tasks", taskId] });
      }
      showToast("success", "Time Log Created", "The time log was created successfully.");
      handleClose();
      if (onTimeLogAdded) {
        onTimeLogAdded();
      }
    },
    onError: (error) => {
      showToast("error", "Error", `Failed to create time log: ${error}`);
    },
    onSettled: () => {
      // Reset submitting state regardless of success or error
      setIsSubmitting(false);
    },
  });
  
  // Update mutation
  const updateMutation = useMutation({
    mutationFn: () => {
      if (!timeLogId) throw new Error("No time log ID for update");
      
      // Convert AM/PM time to 24-hour format for API
      const startTime24 = convertTo24HourFormat(startTime);
      const endTime24 = convertTo24HourFormat(endTime);
      
      return timeLogApi.update(timeLogId, {
        id: timeLogId,
        workDate: format(workDate, "yyyy-MM-dd"),
        startTime: startTime24, // Using 24-hour format
        endTime: endTime24, // Using 24-hour format
        comments: timeLogDescription, // Rich text HTML content
        createdBy: timeLogToEdit?.createdBy || (userData?.userId ? `${userData.userId}` : ""),
        updatedBy: userData?.userId ? `${userData.userId}` : "",
        taskId: selectedTask || 0,
        hrsSpent: parseFloat(timeLogHours) || 0,
        remainingHr: parseFloat(remainingHours) || 0,
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ["timeLogs"] });
      if (selectedTask) {
        queryClient.invalidateQueries({ queryKey: ["tasks", selectedTask] });
      }
      showToast("success", "Time Log Updated", "The time log was updated successfully.");
      handleClose();
      if (onTimeLogAdded) {
        onTimeLogAdded();
      }
    },
    onError: (error) => {
      showToast("error", "Error", `Failed to update time log: ${error}`);
    },
    onSettled: () => {
      // Reset submitting state regardless of success or error
      setIsSubmitting(false);
    },
  });

  // Generate time options in half-hour intervals with AM/PM format
  const generateTimeOptions = (): { label: string; value: string }[] => {
    const options: { label: string; value: string }[] = [];
    
    for (let hour = 1; hour <= 12; hour++) {
      // AM options
      options.push({
        label: `${hour}:00 AM`,
        value: `${hour}:00 AM`
      });
      
      options.push({
        label: `${hour}:30 AM`,
        value: `${hour}:30 AM`
      });
    }
    
    for (let hour = 1; hour <= 12; hour++) {
      // PM options
      options.push({
        label: `${hour}:00 PM`,
        value: `${hour}:00 PM`
      });
      
      options.push({
        label: `${hour}:30 PM`,
        value: `${hour}:30 PM`
      });
    }
    
    return options;
  };
  
  const timeOptions = generateTimeOptions();
  
  // Function to get next time slot
  const getNextTimeSlot = (currentTime: string): string => {
    const timeIndex = timeOptions.findIndex(option => option.value === currentTime);
    if (timeIndex !== -1 && timeIndex < timeOptions.length - 1) {
      return timeOptions[timeIndex + 1].value;
    }
    // If current time is the last option, just return it (this is a fallback)
    return currentTime;
  };

  // Initialize timeLogHours on component mount
  useEffect(() => {
    if (startTime && endTime && !timeLogHours) {
      setTimeLogHours(calculateHoursSpent(startTime, endTime));
    }
  }, []);

  // Handle form submission
  const handleSubmit = (e: React.MouseEvent) => {
    e.preventDefault();
    e.stopPropagation();
    
    const currentTime = Date.now();
    
    // Prevent multiple submissions with debounce (2 seconds)
    if (isSubmitting || (currentTime - lastSubmissionTime < 2000)) {
      return; // Already submitting or too soon after last submission
    }
    
    // Reset validation errors
    setDescriptionError(false);
    
    // Validate required fields
    if (!selectedTask) {
      showToast("error", "Error", "Please select a task");
      return;
    }
    
    if (!startTime || !endTime) {
      showToast("error", "Error", "Please select start and end times");
      return;
    }
    
    // Check if the description is empty or only contains HTML tags without text
    const strippedDescription = timeLogDescription.replace(/<[^>]*>/g, '').trim();
    if (!strippedDescription) {
      setDescriptionError(true);
      showToast("error", "Error", "Description is required");
      return;
    }
    
    // Set submitting state
    setIsSubmitting(true);
    setLastSubmissionTime(currentTime);
    
    // If in edit mode, update the time log, otherwise create a new one
    if (editMode && timeLogId) {
      updateMutation.mutate();
    } else {
      createMutation.mutate();
    }
  };

  // Function to get yesterday's date
  const getYesterday = () => {
    const yesterday = new Date();
    yesterday.setDate(yesterday.getDate() - 1);
    return yesterday;
  };
  
  // Handle clean close with reset
  const handleClose = () => {
    setWorkDate(new Date());
    setStartTime("9:30 AM");
    setEndTime("10:00 AM");
    setTimeLogHours(calculateHoursSpent("9:30 AM", "10:00 AM"));
    setRemainingHours("");
    setTimeLogDescription("");
    setSelectedTask(null);
    setTimeLogId(null);
    setDescriptionError(false);
    setIsSubmitting(false); // Reset submitting state
    setLastSubmissionTime(0); // Reset last submission time
    onClose();
  };

  if (!isOpen) return null;

  // Find selected task details if available
  const selectedTaskDetails = tasks.find(t => t.id === selectedTask);
  
  // Determine if the current operation is in progress
  const isPending = isSubmitting || (editMode ? updateMutation.isPending : createMutation.isPending);

  // Helper function to ensure content is HTML formatted
  const ensureHtmlFormat = (content: string): string => {
    if (!content) return '';
    
    // Check if the content already looks like HTML (contains HTML tags)
    const hasHtmlTags = /<[a-z][\s\S]*>/i.test(content);
    
    // If it's already HTML, return as is
    if (hasHtmlTags) {
      return content;
    }
    
    // Otherwise, wrap it in a paragraph tag
    return `<p>${content}</p>`;
  };

  return (
    <div
      className="fixed inset-0 bg-black/50 flex items-center justify-center z-[9999]"
      onClick={() => {
        // Prevent closing while submitting
        if (!isPending) {
          handleClose();
        }
      }}
    >
      <div
        className="bg-background rounded-lg shadow-lg w-full max-w-md p-6 relative"
        onClick={(e) => e.stopPropagation()}
        style={{ zIndex: 10000 }}
      >
        {/* Close button in the corner */}
        <Button
          variant="ghost"
          size="icon"
          className="absolute right-2 top-2"
          disabled={isPending}
          onClick={() => {
            // Prevent closing while submitting
            if (!isPending) {
              handleClose();
            }
          }}
        >
          <X className="h-4 w-4" />
        </Button>

        <h3 className="text-lg font-semibold mb-4">
          {editMode 
            ? "Edit Time Log"
            : selectedTaskDetails 
              ? `Log Time for ${selectedTaskDetails.title}` 
              : "Add New Time Log"}
        </h3>

        <div className="space-y-4">
          <div>
            <Label className="text-sm font-medium mb-1 block">Work Date</Label>
            <div className="grid grid-cols-2 gap-3">
              <div className="grid grid-cols-2 gap-2">
                <Button
                  variant={workDate && isSameDay(workDate, getYesterday()) ? "default" : "outline"}
                  className="w-full justify-center text-xs sm:text-sm"
                  onClick={() => {
                    const yesterday = getYesterday();
                    setWorkDate(yesterday);
                  }}
                  type="button"
                >
                  Yesterday
                </Button>
                <Button
                  variant={workDate && isSameDay(workDate, new Date()) ? "default" : "outline"}
                  className="w-full justify-center text-xs sm:text-sm"
                  onClick={() => {
                    const today = new Date();
                    setWorkDate(today);
                  }}
                  type="button"
                >
                  Today
                </Button>
              </div>
              <Popover>
                <PopoverTrigger asChild>
                  <Button
                    variant="outline"
                    className={cn(
                      "w-full justify-center text-left font-normal",
                      !workDate && "text-muted-foreground"
                    )}
                  >
                    <CalendarIcon className="mr-2 h-4 w-4" />
                    {workDate ? format(workDate, "PPP") : <span>Pick a date</span>}
                  </Button>
                </PopoverTrigger>
                <PopoverContent className="w-auto p-0 z-[10001]">
                  <Calendar
                    mode="single"
                    selected={workDate}
                    onSelect={(date) => date && setWorkDate(date)}
                    initialFocus
                    disabled={(date) => {
                      // Only allow today and yesterday in normal mode
                      // In edit mode, allow the current date from the time log
                      const yesterday = getYesterday();
                      if (editMode && timeLogToEdit) {
                        const timeLogDate = new Date(timeLogToEdit.workDate);
                        // Allow the original date, today and yesterday
                        return date > new Date() || 
                              (date < yesterday && !isSameDay(date, timeLogDate));
                      }
                      return date > new Date() || (date < yesterday);
                    }}
                  />
                </PopoverContent>
              </Popover>
            </div>
          </div>

          {(!taskId || !selectedTaskDetails) && (
            <div className="space-y-2" style={{ zIndex: 50, position: 'relative' }}>
              <Label className="text-sm font-medium mb-1 block">Task*</Label>
              {isLoadingTasks ? (
                <div className="flex items-center space-x-2">
                  <Loader2 className="h-4 w-4 animate-spin" />
                  <span className="text-sm text-muted-foreground">Loading tasks...</span>
                </div>
              ) : (
                <Dropdown
                  options={taskOptions}
                  value={selectedTask?.toString() || ""}
                  onValueChange={(value) => {
                    const taskId = parseInt(value);
                    setSelectedTask(taskId);
                    
                    // Auto-fill remaining hours from the task if available
                    const task = tasks.find(t => t.id === taskId);
                    if (task?.remainingHr) {
                      setRemainingHours(task.remainingHr.toString());
                    }
                  }}
                  placeholder="Select a task"
                  className="w-full"
                  disabled={!!taskId || (editMode && !!timeLogToEdit)}
                />
              )}
            </div>
          )}
          
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2" style={{ zIndex: 45, position: 'relative' }}>
              <Label className="text-sm font-medium mb-1 block">Start Time*</Label>
              <Dropdown
                options={timeOptions}
                value={startTime}
                onValueChange={(value) => {
                  setStartTime(value);
                  // Automatically set end time to next time slot
                  const nextSlot = getNextTimeSlot(value);
                  setEndTime(nextSlot);
                  // Calculate hours spent between start and end
                  const hoursSpent = calculateHoursSpent(value, nextSlot);
                  setTimeLogHours(hoursSpent);
                }}
                placeholder="Select start time"
                className="w-full"
              />
            </div>
            
            <div className="space-y-2" style={{ zIndex: 40, position: 'relative' }}>
              <Label className="text-sm font-medium mb-1 block">End Time*</Label>
              <Dropdown
                options={timeOptions}
                value={endTime}
                onValueChange={(value) => {
                  setEndTime(value);
                  if (startTime) {
                    // Calculate hours spent between start and end
                    const hoursSpent = calculateHoursSpent(startTime, value);
                    setTimeLogHours(hoursSpent);
                  }
                }}
                placeholder="Select end time"
                className="w-full"
              />
            </div>
          </div>
          
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label className="text-sm font-medium mb-1 block">Hours Spent*</Label>
              <Input
                type="number"
                min="0"
                step="0.5"
                value={timeLogHours}
                onChange={(e) => setTimeLogHours(e.target.value)}
                placeholder="Hours worked"
                className="bg-gray-50"
                readOnly
              />
              <p className="text-xs text-muted-foreground">Auto-calculated from time range</p>
            </div>
            
            <div className="space-y-2">
              <Label className="text-sm font-medium mb-1 block">Remaining Hours*</Label>
              <Input
                type="number"
                min="0"
                step="0.5"
                value={remainingHours}
                onChange={(e) => setRemainingHours(e.target.value)}
                placeholder="Hours remaining"
              />
            </div>
          </div>
          
          <div className="space-y-1">
            <div className="flex items-center justify-between">
              <Label className="text-sm font-medium mb-1 block flex items-center">
                Description* <span className="text-rose-500 ml-0.5">*</span>
              </Label>
              {descriptionError && (
                <div className="text-xs font-medium text-rose-500 flex items-center">
                  <AlertCircle className="h-3 w-3 mr-1" />
                  Required field
                </div>
              )}
            </div>
            <SlateRichTextEditor
              key={timeLogId || 'new-time-log'} // Add key to force re-render when time log changes
              initialValue={ensureHtmlFormat(timeLogDescription)}
              onChange={(value) => {
                setTimeLogDescription(value);
                if (value.trim()) {
                  setDescriptionError(false);
                }
              }}
              placeholder="What did you work on? Please provide detailed description of your work."
              minHeight="150px"
              className={cn(
                descriptionError && "border-rose-500 focus-visible:ring-rose-500"
              )}
            />
            <p className="text-xs text-muted-foreground">
              Provide a detailed description of the work completed during this time period.
            </p>
          </div>
          
          <Button 
            className="w-full py-2 px-4 bg-gradient-to-r from-blue-600 to-indigo-600 hover:from-blue-700 hover:to-indigo-700 text-white disabled:opacity-50 disabled:cursor-not-allowed"
            onClick={handleSubmit}
            disabled={isPending}
          >
            {isPending ? (
              <>
                <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                {editMode ? "Updating..." : "Saving..."}
              </>
            ) : editMode ? (
              <>
                <Check className="h-4 w-4 mr-2" /> Update Time Log
              </>
            ) : (
              <>
                <Clock className="h-4 w-4 mr-2" /> Log Time
              </>
            )}
          </Button>
        </div>
      </div>
    </div>
  );
} 