/**
 * Resource Scheduler - Vertical agenda view for resource users
 */

import React, { useState, useRef, useMemo, useEffect } from 'react';
import { Appointment, User, Business, Blocker } from '../types';
import { Clock, CheckCircle2, Lock, Plus, X, ChevronLeft, ChevronRight, Ban } from 'lucide-react';
import { useAppointments, useUpdateAppointment } from '../hooks/useAppointments';
import { useResources } from '../hooks/useResources';
import { useServices } from '../hooks/useServices';
import Portal from '../components/Portal';

// Time settings
const START_HOUR = 8;
const END_HOUR = 18;
const PIXELS_PER_MINUTE_VERTICAL = 2;

interface ResourceSchedulerProps {
  user: User;
  business: Business;
}

const ResourceScheduler: React.FC<ResourceSchedulerProps> = ({ user, business }) => {
  const { data: appointments = [] } = useAppointments();
  const { data: resources = [] } = useResources();
  const { data: services = [] } = useServices();
  const updateMutation = useUpdateAppointment();

  const [blockers, setBlockers] = useState<Blocker[]>([]);
  const [viewDate, setViewDate] = useState(new Date());
  const [isBlockTimeModalOpen, setIsBlockTimeModalOpen] = useState(false);
  const [newBlocker, setNewBlocker] = useState({ title: 'Break', startTime: '12:00', durationMinutes: 60 });

  const agendaContainerRef = useRef<HTMLDivElement>(null);
  const scrollContainerRef = useRef<HTMLDivElement>(null);

  // Scroll to current time on mount (centered in view)
  useEffect(() => {
    if (!scrollContainerRef.current) return;

    const now = new Date();
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const viewDay = new Date(viewDate);
    viewDay.setHours(0, 0, 0, 0);

    // Only scroll if viewing today
    if (viewDay.getTime() !== today.getTime()) return;

    const container = scrollContainerRef.current;
    const containerHeight = container.clientHeight;

    // Calculate current time offset in pixels (vertical)
    const startOfDay = new Date(now);
    startOfDay.setHours(START_HOUR, 0, 0, 0);
    const minutesSinceStart = (now.getTime() - startOfDay.getTime()) / (1000 * 60);
    const currentTimeOffset = minutesSinceStart * PIXELS_PER_MINUTE_VERTICAL;

    // Scroll so current time is centered
    const scrollPosition = currentTimeOffset - (containerHeight / 2);
    container.scrollTop = Math.max(0, scrollPosition);
  }, []);

  const isSameDay = (d1: Date, d2: Date) =>
    d1.getFullYear() === d2.getFullYear() &&
    d1.getMonth() === d2.getMonth() &&
    d1.getDate() === d2.getDate();

  const myResource = useMemo(() => resources.find(r => r.userId === user.id), [user.id, resources]);

  const myAppointments = useMemo(
    () => appointments
      .filter(a => a.resourceId === myResource?.id && isSameDay(new Date(a.startTime), viewDate))
      .sort((a, b) => a.startTime.getTime() - b.startTime.getTime()),
    [appointments, myResource, viewDate]
  );

  const myBlockers = useMemo(
    () => blockers
      .filter(b => b.resourceId === myResource?.id && isSameDay(new Date(b.startTime), viewDate))
      .sort((a, b) => a.startTime.getTime() - b.startTime.getTime()),
    [blockers, myResource, viewDate]
  );

  const timeMarkersVertical = Array.from({ length: END_HOUR - START_HOUR }, (_, i) => START_HOUR + i)
    .flatMap(h => [`${h}:00`, `${h}:30`]);

  const handleVerticalDragStart = (e: React.DragEvent, appointment: Appointment) => {
    if (!business.resourcesCanReschedule || appointment.status === 'COMPLETED') {
      return e.preventDefault();
    }
    e.dataTransfer.setData('appointmentId', appointment.id);
  };

  const handleVerticalDrop = (e: React.DragEvent<HTMLDivElement>) => {
    e.preventDefault();
    if (!business.resourcesCanReschedule || !agendaContainerRef.current) return;

    const appointmentId = e.dataTransfer.getData('appointmentId');
    const appointment = myAppointments.find(a => a.id === appointmentId);
    if (!appointment || appointment.status === 'COMPLETED') return;

    const rect = agendaContainerRef.current.getBoundingClientRect();
    const dropY = e.clientY - rect.top;
    const minutesFromStart = dropY / PIXELS_PER_MINUTE_VERTICAL;
    const snappedMinutes = Math.round(minutesFromStart / 15) * 15;
    const newStartTime = new Date(viewDate);
    newStartTime.setHours(START_HOUR, snappedMinutes, 0, 0);

    updateMutation.mutate({
      id: appointmentId,
      updates: { startTime: newStartTime }
    });
  };

  const handleAddBlocker = () => {
    const [hours, minutes] = newBlocker.startTime.split(':').map(Number);
    const startTime = new Date(viewDate);
    startTime.setHours(hours, minutes, 0, 0);

    const newBlock: Blocker = {
      id: `block_${Date.now()}`,
      resourceId: myResource!.id,
      title: newBlocker.title,
      startTime,
      durationMinutes: newBlocker.durationMinutes
    };
    setBlockers(prev => [...prev, newBlock]);
    setIsBlockTimeModalOpen(false);
  };

  const getVerticalOffset = (date: Date) => {
    const startOfDay = new Date(date);
    startOfDay.setHours(START_HOUR, 0, 0, 0);
    const diffMinutes = (date.getTime() - startOfDay.getTime()) / (1000 * 60);
    return diffMinutes * PIXELS_PER_MINUTE_VERTICAL;
  };

  const getStatusColor = (status: Appointment['status'], startTime: Date, endTime: Date) => {
    if (status === 'COMPLETED' || status === 'NO_SHOW')
      return 'bg-gray-100 border-gray-400 text-gray-600 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-400';
    if (status === 'CANCELLED')
      return 'bg-gray-100 border-gray-400 text-gray-500 opacity-75 dark:bg-gray-800 dark:border-gray-600 dark:text-gray-400';
    const now = new Date();
    if (now > endTime)
      return 'bg-red-100 border-red-500 text-red-900 dark:bg-red-900/50 dark:border-red-500 dark:text-red-200';
    if (now >= startTime && now <= endTime)
      return 'bg-yellow-100 border-yellow-500 text-yellow-900 dark:bg-yellow-900/50 dark:border-yellow-500 dark:text-yellow-200';
    return 'bg-blue-100 border-blue-500 text-blue-900 dark:bg-blue-900/50 dark:border-blue-500 dark:text-blue-200';
  };

  return (
    <div className="p-8 max-w-5xl mx-auto">
      <div className="flex items-center justify-between mb-6">
        <div>
          <h2 className="text-2xl font-bold text-gray-900 dark:text-white">Schedule: {myResource?.name}</h2>
          <p className="text-gray-500 dark:text-gray-400">
            Viewing appointments for {viewDate.toLocaleDateString(undefined, {
              weekday: 'long', year: 'numeric', month: 'long', day: 'numeric'
            })}.
          </p>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={() => setIsBlockTimeModalOpen(true)}
            className="flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-white bg-brand-500 rounded-lg hover:bg-brand-600 transition-colors shadow-sm"
          >
            <Plus size={16} /> Block Time
          </button>
          <div className="flex items-center bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm">
            <button
              onClick={() => setViewDate(d => new Date(d.setDate(d.getDate() - 1)))}
              className="p-2 text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-l-md"
            >
              <ChevronLeft size={18} />
            </button>
            <button
              onClick={() => setViewDate(new Date())}
              className="px-3 py-1.5 text-sm font-semibold text-gray-700 dark:text-gray-200 border-x border-gray-200 dark:border-gray-700 hover:bg-gray-100 dark:hover:bg-gray-700"
            >
              Today
            </button>
            <button
              onClick={() => setViewDate(d => new Date(d.setDate(d.getDate() + 1)))}
              className="p-2 text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-r-md"
            >
              <ChevronRight size={18} />
            </button>
          </div>
        </div>
      </div>

      <div ref={scrollContainerRef} className="h-[70vh] overflow-y-auto timeline-scroll bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 shadow-sm flex">
        {/* Time Gutter */}
        <div className="w-20 text-right pr-4 border-r border-gray-100 dark:border-gray-700 shrink-0">
          {timeMarkersVertical.map((time, i) => (
            <div key={i} className="text-xs text-gray-400 relative" style={{ height: 30 * PIXELS_PER_MINUTE_VERTICAL }}>
              {time.endsWith(':00') && <span className="absolute -top-1.5">{time}</span>}
            </div>
          ))}
        </div>

        {/* Agenda */}
        <div
          ref={agendaContainerRef}
          className="flex-1 relative"
          onDragOver={(e) => { if (business.resourcesCanReschedule) e.preventDefault(); }}
          onDrop={handleVerticalDrop}
        >
          <div style={{ height: (END_HOUR - START_HOUR) * 60 * PIXELS_PER_MINUTE_VERTICAL }} className="relative">
            {timeMarkersVertical.map((_, i) => (
              <div
                key={i}
                className={`absolute w-full ${i % 2 === 0 ? 'border-t border-gray-100 dark:border-gray-700' : 'border-t border-dashed border-gray-100 dark:border-gray-800'}`}
                style={{ top: i * 30 * PIXELS_PER_MINUTE_VERTICAL }}
              />
            ))}

            {[...myAppointments, ...myBlockers].map(item => {
              const isAppointment = 'customerName' in item;
              const startTime = new Date(item.startTime);
              const endTime = new Date(startTime.getTime() + item.durationMinutes * 60000);
              const isCompleted = isAppointment && item.status === 'COMPLETED';
              const canDrag = business.resourcesCanReschedule && !isCompleted && isAppointment;

              const colorClass = isAppointment
                ? getStatusColor(item.status, startTime, endTime)
                : 'bg-gray-100 border-gray-300 text-gray-500 dark:bg-gray-700 dark:border-gray-500 dark:text-gray-400';
              const cursorClass = canDrag ? 'cursor-grab active:cursor-grabbing' : 'cursor-default';
              const service = isAppointment ? services.find(s => s.id === (item as Appointment).serviceId) : null;

              return (
                <div
                  key={item.id}
                  draggable={canDrag}
                  onDragStart={(e) => isAppointment && handleVerticalDragStart(e, item as Appointment)}
                  className={`absolute left-2 right-2 rounded p-3 border-l-4 shadow-sm group overflow-hidden transition-all ${colorClass} ${cursorClass}`}
                  style={{
                    top: getVerticalOffset(startTime),
                    height: item.durationMinutes * PIXELS_PER_MINUTE_VERTICAL,
                    zIndex: 10,
                    backgroundImage: !isAppointment ? `linear-gradient(45deg, rgba(0,0,0,0.05) 25%, transparent 25%, transparent 50%, rgba(0,0,0,0.05) 50%, rgba(0,0,0,0.05) 75%, transparent 75%, transparent)` : undefined,
                    backgroundSize: !isAppointment ? '20px 20px' : undefined
                  }}
                >
                  <div className="font-semibold text-sm truncate flex items-center justify-between">
                    <span>{isAppointment ? (item as Appointment).customerName : item.title}</span>
                    {isCompleted && <Lock size={12} className="text-gray-400 shrink-0" />}
                  </div>
                  {isAppointment && <div className="text-xs truncate opacity-80">{service?.name}</div>}
                  <div className="mt-2 flex items-center gap-1 text-xs opacity-75">
                    {isAppointment && (item as Appointment).status === 'COMPLETED' ? (
                      <CheckCircle2 size={12} />
                    ) : isAppointment ? (
                      <Clock size={12} />
                    ) : (
                      <Ban size={12} />
                    )}
                    <span>
                      {startTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} -
                      {endTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
                    </span>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {isBlockTimeModalOpen && (
        <Portal>
          <div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50 backdrop-blur-sm" onClick={() => setIsBlockTimeModalOpen(false)}>
            <div className="w-full max-w-sm bg-white dark:bg-gray-800 rounded-xl shadow-xl border border-gray-200 dark:border-gray-700 overflow-hidden" onClick={e => e.stopPropagation()}>
              <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700">
                <h3 className="text-lg font-semibold text-gray-900 dark:text-white">Add Time Off</h3>
                <button onClick={() => setIsBlockTimeModalOpen(false)} className="p-1 text-gray-400 hover:bg-gray-100 rounded-full">
                  <X size={20} />
                </button>
              </div>
            <div className="p-6 space-y-4">
              <div>
                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Title</label>
                <input
                  type="text"
                  value={newBlocker.title}
                  onChange={e => setNewBlocker(s => ({ ...s, title: e.target.value }))}
                  className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-500 outline-none"
                />
              </div>
              <div className="grid grid-cols-2 gap-4">
                <div>
                  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Start Time</label>
                  <input
                    type="time"
                    value={newBlocker.startTime}
                    onChange={e => setNewBlocker(s => ({ ...s, startTime: e.target.value }))}
                    className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-500 outline-none"
                  />
                </div>
                <div>
                  <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Duration (min)</label>
                  <input
                    type="number"
                    step="15"
                    min="15"
                    value={newBlocker.durationMinutes}
                    onChange={e => setNewBlocker(s => ({ ...s, durationMinutes: parseInt(e.target.value, 10) }))}
                    className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:ring-2 focus:ring-brand-500 outline-none"
                  />
                </div>
              </div>
              <div className="pt-2 flex justify-end gap-3">
                <button
                  onClick={() => setIsBlockTimeModalOpen(false)}
                  className="px-4 py-2 text-sm font-medium rounded-lg"
                >
                  Cancel
                </button>
                <button
                  onClick={handleAddBlocker}
                  className="px-4 py-2 text-sm font-medium text-white bg-brand-600 rounded-lg hover:bg-brand-700"
                >
                  Add Block
                </button>
              </div>
              </div>
            </div>
          </div>
        </Portal>
      )}
    </div>
  );
};

export default ResourceScheduler;
