import React, { useMemo, useState, useEffect, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {
  DndContext,
  DragEndEvent,
  useSensor,
  useSensors,
  PointerSensor,
  DragOverlay,
} from '@dnd-kit/core';
import {
  format,
  startOfDay,
  endOfDay,
  addDays,
  subDays,
  differenceInMinutes,
  addMinutes,
  isSameDay,
  isToday,
  parseISO,
} from 'date-fns';
import {
  ChevronLeft,
  ChevronRight,
  Calendar,
  Clock,
  User,
  GripVertical,
} from 'lucide-react';
import apiClient from '../api/client';
import { User as UserType } from '../types';
import toast from 'react-hot-toast';

interface StaffScheduleProps {
  user: UserType;
}

interface Job {
  id: number;
  title: string;
  start_time: string;
  end_time: string;
  status: string;
  notes?: string;
  customer_name?: string;
  service_name?: string;
}

const HOUR_HEIGHT = 60; // pixels per hour
const START_HOUR = 0; // 12:00 AM
const END_HOUR = 24; // 11:59 PM

const StaffSchedule: React.FC<StaffScheduleProps> = ({ user }) => {
  const { t } = useTranslation();
  const queryClient = useQueryClient();
  const [currentDate, setCurrentDate] = useState(new Date());
  const [draggedJob, setDraggedJob] = useState<Job | null>(null);
  const [currentTime, setCurrentTime] = useState(new Date());
  const timelineContainerRef = useRef<HTMLDivElement>(null);
  const hasScrolledToCurrentTime = useRef(false);

  const canEditSchedule = user.can_edit_schedule ?? false;

  // Update current time every minute
  useEffect(() => {
    const interval = setInterval(() => {
      setCurrentTime(new Date());
    }, 60000); // Update every minute

    return () => clearInterval(interval);
  }, []);

  // Scroll to current time on initial load (only for today)
  useEffect(() => {
    if (
      timelineContainerRef.current &&
      isToday(currentDate) &&
      !hasScrolledToCurrentTime.current
    ) {
      const now = new Date();
      const currentHour = now.getHours() + now.getMinutes() / 60;
      const scrollPosition = (currentHour - START_HOUR) * HOUR_HEIGHT;
      const containerHeight = timelineContainerRef.current.clientHeight;

      // Center the current time in the viewport
      timelineContainerRef.current.scrollTop = scrollPosition - containerHeight / 2;
      hasScrolledToCurrentTime.current = true;
    }
  }, [currentDate]);

  // Reset scroll flag when date changes
  useEffect(() => {
    hasScrolledToCurrentTime.current = false;
  }, [currentDate]);

  // Get the resource ID and name linked to this user (from the user object)
  const userResourceId = user.linked_resource_id ?? null;
  const userResourceName = user.linked_resource_name ?? null;

  // Fetch appointments for the current staff member's resource
  const { data: jobs = [], isLoading } = useQuery({
    queryKey: ['staff-jobs', format(currentDate, 'yyyy-MM-dd'), userResourceId],
    queryFn: async () => {
      if (!userResourceId) return [];

      const start = startOfDay(currentDate).toISOString();
      const end = endOfDay(currentDate).toISOString();
      const response = await apiClient.get('/appointments/', {
        params: {
          resource: userResourceId,
          start_date: start,
          end_date: end,
        },
      });

      // Transform to Job format
      return response.data.map((apt: any) => ({
        id: apt.id,
        title: apt.title || apt.service_name || 'Appointment',
        start_time: apt.start_time,
        end_time: apt.end_time,
        status: apt.status,
        notes: apt.notes,
        customer_name: apt.customer_name,
        service_name: apt.service_name,
      }));
    },
    enabled: !!userResourceId,
  });

  // Mutation for rescheduling
  const rescheduleMutation = useMutation({
    mutationFn: async ({ jobId, newStart }: { jobId: number; newStart: Date }) => {
      const job = jobs.find((j) => j.id === jobId);
      if (!job) throw new Error('Job not found');

      const duration = differenceInMinutes(parseISO(job.end_time), parseISO(job.start_time));
      const newEnd = addMinutes(newStart, duration);

      await apiClient.patch(`/appointments/${jobId}/`, {
        start_time: newStart.toISOString(),
        end_time: newEnd.toISOString(),
      });
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['staff-jobs'] });
      queryClient.invalidateQueries({ queryKey: ['appointments'] });
      toast.success(t('staff.jobRescheduled', 'Job rescheduled successfully'));
    },
    onError: () => {
      toast.error(t('staff.rescheduleError', 'Failed to reschedule job'));
    },
  });

  const sensors = useSensors(
    useSensor(PointerSensor, {
      activationConstraint: {
        distance: 5,
      },
    })
  );

  // Generate time slots (12 AM to 11 PM = hours 0-23)
  const timeSlots = useMemo(() => {
    const slots = [];
    for (let hour = START_HOUR; hour < END_HOUR; hour++) {
      slots.push({
        hour,
        label: format(new Date().setHours(hour, 0, 0, 0), 'h a'),
      });
    }
    return slots;
  }, []);

  // Calculate job positions
  const jobsWithPositions = useMemo(() => {
    return jobs
      .filter((job) => {
        const jobDate = parseISO(job.start_time);
        return isSameDay(jobDate, currentDate);
      })
      .map((job) => {
        const startTime = parseISO(job.start_time);
        const endTime = parseISO(job.end_time);
        const startHour = startTime.getHours() + startTime.getMinutes() / 60;
        const endHour = endTime.getHours() + endTime.getMinutes() / 60;

        const top = (startHour - START_HOUR) * HOUR_HEIGHT;
        const height = (endHour - startHour) * HOUR_HEIGHT;

        return {
          ...job,
          top: Math.max(0, top),
          height: Math.max(30, height),
        };
      });
  }, [jobs, currentDate]);

  // Calculate current time indicator position (only show for today)
  const currentTimeIndicator = useMemo(() => {
    if (!isToday(currentDate)) return null;

    const hours = currentTime.getHours() + currentTime.getMinutes() / 60;
    const top = (hours - START_HOUR) * HOUR_HEIGHT;

    return {
      top,
      label: format(currentTime, 'h:mm a'),
    };
  }, [currentDate, currentTime]);

  const handleDragStart = (event: any) => {
    const jobId = parseInt(event.active.id.toString().replace('job-', ''));
    const job = jobs.find((j) => j.id === jobId);
    setDraggedJob(job || null);
  };

  const handleDragEnd = (event: DragEndEvent) => {
    setDraggedJob(null);

    if (!canEditSchedule) return;

    const { active, delta } = event;
    if (!active || Math.abs(delta.y) < 10) return;

    const jobId = parseInt(active.id.toString().replace('job-', ''));
    const job = jobs.find((j) => j.id === jobId);
    if (!job) return;

    // Calculate new time based on drag delta
    const minutesDelta = Math.round((delta.y / HOUR_HEIGHT) * 60);
    const snappedMinutes = Math.round(minutesDelta / 15) * 15; // Snap to 15-minute intervals

    const originalStart = parseISO(job.start_time);
    const newStart = addMinutes(originalStart, snappedMinutes);

    // Validate new time is within bounds
    const newHour = newStart.getHours();
    if (newHour < START_HOUR || newHour >= END_HOUR) {
      toast.error(t('staff.timeOutOfBounds', 'Cannot schedule outside business hours'));
      return;
    }

    rescheduleMutation.mutate({ jobId, newStart });
  };

  const getStatusColor = (status: string) => {
    switch (status.toUpperCase()) {
      case 'SCHEDULED':
      case 'CONFIRMED':
        return 'bg-blue-100 border-blue-500 text-blue-800 dark:bg-blue-900/30 dark:border-blue-400 dark:text-blue-300';
      case 'IN_PROGRESS':
        return 'bg-yellow-100 border-yellow-500 text-yellow-800 dark:bg-yellow-900/30 dark:border-yellow-400 dark:text-yellow-300';
      case 'COMPLETED':
        return 'bg-green-100 border-green-500 text-green-800 dark:bg-green-900/30 dark:border-green-400 dark:text-green-300';
      case 'CANCELLED':
      case 'NO_SHOW':
        return 'bg-red-100 border-red-500 text-red-800 dark:bg-red-900/30 dark:border-red-400 dark:text-red-300';
      default:
        return 'bg-gray-100 border-gray-500 text-gray-800 dark:bg-gray-700 dark:border-gray-500 dark:text-gray-300';
    }
  };

  const navigateDate = (direction: 'prev' | 'next') => {
    setCurrentDate((d) => (direction === 'prev' ? subDays(d, 1) : addDays(d, 1)));
  };

  const goToToday = () => {
    setCurrentDate(new Date());
  };

  // Show message if no resource is linked
  if (!userResourceId) {
    return (
      <div className="flex flex-col h-full bg-gray-50 dark:bg-gray-900">
        <div className="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 px-6 py-4">
          <h1 className="text-2xl font-bold text-gray-900 dark:text-white">
            {t('staff.mySchedule', 'My Schedule')}
          </h1>
        </div>
        <div className="flex-1 flex items-center justify-center p-6">
          <div className="text-center max-w-md">
            <Calendar size={48} className="mx-auto text-gray-300 dark:text-gray-600 mb-4" />
            <h3 className="text-lg font-medium text-gray-900 dark:text-white mb-2">
              {t('staff.noResourceLinked', 'No Schedule Available')}
            </h3>
            <p className="text-sm text-gray-500 dark:text-gray-400">
              {t(
                'staff.noResourceLinkedDesc',
                'Your account is not linked to a resource yet. Please contact your manager to set up your schedule.'
              )}
            </p>
          </div>
        </div>
      </div>
    );
  }

  return (
    <div className="flex flex-col h-full bg-gray-50 dark:bg-gray-900">
      {/* Header */}
      <div className="bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700 px-6 py-4">
        <div className="flex items-center justify-between">
          <div>
            <h1 className="text-2xl font-bold text-gray-900 dark:text-white">
              {t('staff.mySchedule', 'My Schedule')}
            </h1>
            <p className="text-sm text-gray-500 dark:text-gray-400">
              {canEditSchedule
                ? t('staff.dragToReschedule', 'Drag jobs to reschedule them')
                : t('staff.viewOnlySchedule', 'View your scheduled jobs for the day')}
            </p>
            {/* Resource Badge - Makes it clear which resource this schedule is for */}
            {userResourceName && (
              <div className="mt-2 inline-flex items-center gap-2 px-3 py-1 bg-brand-50 dark:bg-brand-900/20 text-brand-700 dark:text-brand-300 rounded-lg text-sm">
                <User size={14} />
                <span>{t('staff.scheduleFor', 'Schedule for:')}</span>
                <span className="font-semibold">{userResourceName}</span>
              </div>
            )}
          </div>
          <div className="flex items-center gap-3">
            <button
              onClick={() => navigateDate('prev')}
              className="p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
            >
              <ChevronLeft size={20} />
            </button>
            <button
              onClick={goToToday}
              className="px-3 py-1.5 text-sm font-medium text-gray-700 dark:text-gray-300 bg-gray-100 dark:bg-gray-700 rounded-lg hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors"
            >
              {t('common.today', 'Today')}
            </button>
            <div className="flex items-center gap-2 px-4 py-2 bg-gray-100 dark:bg-gray-700 rounded-lg">
              <Calendar size={16} className="text-gray-500 dark:text-gray-400" />
              <span className="font-medium text-gray-900 dark:text-white">
                {format(currentDate, 'EEEE, MMMM d, yyyy')}
              </span>
            </div>
            <button
              onClick={() => navigateDate('next')}
              className="p-2 text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
            >
              <ChevronRight size={20} />
            </button>
          </div>
        </div>
      </div>

      {/* Timeline Content */}
      <div ref={timelineContainerRef} className="flex-1 overflow-auto p-6">
        {isLoading ? (
          <div className="flex items-center justify-center h-64">
            <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
          </div>
        ) : (
          <DndContext
            sensors={sensors}
            onDragStart={handleDragStart}
            onDragEnd={handleDragEnd}
          >
            <div className="bg-white dark:bg-gray-800 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden">
              <div className="flex">
                {/* Time Column */}
                <div className="w-20 flex-shrink-0 border-r border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/50">
                  {timeSlots.map((slot) => (
                    <div
                      key={slot.hour}
                      className="border-b border-gray-100 dark:border-gray-700/50 text-right pr-3 py-1 text-xs font-medium text-gray-500 dark:text-gray-400"
                      style={{ height: HOUR_HEIGHT }}
                    >
                      {slot.label}
                    </div>
                  ))}
                </div>

                {/* Events Column */}
                <div
                  className="flex-1 relative"
                  style={{ height: (END_HOUR - START_HOUR) * HOUR_HEIGHT }}
                >
                  {/* Hour Grid Lines */}
                  {timeSlots.map((slot) => (
                    <div
                      key={slot.hour}
                      className="absolute left-0 right-0 border-b border-gray-100 dark:border-gray-700/50"
                      style={{ top: (slot.hour - START_HOUR) * HOUR_HEIGHT, height: HOUR_HEIGHT }}
                    />
                  ))}

                  {/* Current Time Indicator - Real-time updates */}
                  {currentTimeIndicator && (
                    <div
                      className="absolute left-0 right-0 z-20 pointer-events-none"
                      style={{ top: currentTimeIndicator.top }}
                    >
                      {/* Time Label */}
                      <div className="absolute -left-20 -top-2.5 w-16 text-right pr-2">
                        <span className="text-xs font-semibold text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/30 px-1.5 py-0.5 rounded">
                          {currentTimeIndicator.label}
                        </span>
                      </div>
                      {/* Line with circle */}
                      <div className="border-t-2 border-red-500">
                        <div className="absolute -left-1 -top-1.5 w-3 h-3 bg-red-500 rounded-full shadow-sm" />
                      </div>
                    </div>
                  )}

                  {/* Jobs */}
                  {jobsWithPositions.map((job) => (
                    <div
                      key={job.id}
                      id={`job-${job.id}`}
                      className={`absolute left-2 right-2 rounded-lg border-l-4 p-3 transition-shadow ${getStatusColor(job.status)} ${
                        canEditSchedule ? 'cursor-grab active:cursor-grabbing hover:shadow-lg' : ''
                      }`}
                      style={{
                        top: job.top,
                        height: job.height,
                        minHeight: 60,
                      }}
                      draggable={canEditSchedule}
                    >
                      <div className="flex items-start justify-between h-full">
                        <div className="flex-1 min-w-0">
                          <div className="flex items-center gap-2 mb-1">
                            {canEditSchedule && (
                              <GripVertical
                                size={14}
                                className="text-gray-400 flex-shrink-0"
                              />
                            )}
                            <h3 className="font-semibold text-sm truncate">
                              {job.title || job.service_name || 'Appointment'}
                            </h3>
                          </div>

                          <div className="space-y-1">
                            <div className="flex items-center gap-1.5 text-xs opacity-80">
                              <Clock size={12} />
                              <span>
                                {format(parseISO(job.start_time), 'h:mm a')} -{' '}
                                {format(parseISO(job.end_time), 'h:mm a')}
                              </span>
                            </div>

                            {job.customer_name && (
                              <div className="flex items-center gap-1.5 text-xs opacity-80">
                                <User size={12} />
                                <span className="truncate">{job.customer_name}</span>
                              </div>
                            )}
                          </div>
                        </div>

                        <span
                          className={`text-xs px-2 py-0.5 rounded-full font-medium ${
                            job.status === 'IN_PROGRESS'
                              ? 'bg-yellow-200 text-yellow-800'
                              : 'bg-white/50 dark:bg-gray-900/30'
                          }`}
                        >
                          {job.status.replace('_', ' ')}
                        </span>
                      </div>
                    </div>
                  ))}

                  {/* Empty State */}
                  {jobsWithPositions.length === 0 && (
                    <div className="absolute inset-0 flex items-center justify-center">
                      <div className="text-center">
                        <Calendar
                          size={48}
                          className="mx-auto text-gray-300 dark:text-gray-600 mb-4"
                        />
                        <h3 className="text-lg font-medium text-gray-900 dark:text-white mb-1">
                          {t('staff.noJobsToday', 'No jobs scheduled')}
                        </h3>
                        <p className="text-sm text-gray-500 dark:text-gray-400">
                          {t(
                            'staff.noJobsDescription',
                            'You have no jobs scheduled for this day'
                          )}
                        </p>
                      </div>
                    </div>
                  )}
                </div>
              </div>
            </div>

            {/* Drag Overlay */}
            <DragOverlay>
              {draggedJob ? (
                <div className="p-3 bg-white dark:bg-gray-700 border-l-4 border-blue-500 rounded-lg shadow-xl opacity-90 w-64">
                  <div className="font-semibold text-sm text-gray-900 dark:text-white">
                    {draggedJob.title || draggedJob.service_name || 'Appointment'}
                  </div>
                  <div className="flex items-center gap-1 text-xs text-gray-500 dark:text-gray-400 mt-1">
                    <Clock size={12} />
                    <span>
                      {format(parseISO(draggedJob.start_time), 'h:mm a')} -{' '}
                      {format(parseISO(draggedJob.end_time), 'h:mm a')}
                    </span>
                  </div>
                </div>
              ) : null}
            </DragOverlay>
          </DndContext>
        )}
      </div>
    </div>
  );
};

export default StaffSchedule;
