import { useEffect, useState, useMemo, useCallback, useRef } from 'react'
// @ts-ignore - react-big-calendar types not available
import { Calendar, momentLocalizer, Views } from 'react-big-calendar'
// @ts-ignore - react-big-calendar dragAndDrop types not available
import withDragAndDrop from 'react-big-calendar/lib/addons/dragAndDrop'
import { DndProvider } from 'react-dnd'
import { HTML5Backend } from 'react-dnd-html5-backend'
import moment from 'moment'
import type { User, ExperimentPhase, Experiment, ExperimentRepetition, Soaking, Airdrying } from '../services/supabase'
import { availabilityManagement, userManagement, experimentPhaseManagement, experimentManagement, repetitionManagement, phaseManagement, supabase } from '../services/supabase'
import 'react-big-calendar/lib/css/react-big-calendar.css'
import './CalendarStyles.css'

// Type definitions for calendar events
interface CalendarEvent {
    id: number | string
    title: string
    start: Date
    end: Date
    resource?: string
}

interface SchedulingProps {
    user: User
    currentRoute: string
}

type SchedulingView = 'main' | 'view-schedule' | 'indicate-availability' | 'schedule-experiment'

export function Scheduling({ user, currentRoute }: SchedulingProps) {
    // Extract current view from route
    const getCurrentView = (): SchedulingView => {
        if (currentRoute === '/scheduling') {
            return 'main'
        }
        const match = currentRoute.match(/^\/scheduling\/(.+)$/)
        if (match) {
            const subRoute = match[1]
            switch (subRoute) {
                case 'view-schedule':
                    return 'view-schedule'
                case 'indicate-availability':
                    return 'indicate-availability'
                case 'schedule-experiment':
                    return 'schedule-experiment'
                default:
                    return 'main'
            }
        }
        return 'main'
    }

    const currentView = getCurrentView()

    const handleCardClick = (view: SchedulingView) => {
        const newPath = view === 'main' ? '/scheduling' : `/scheduling/${view}`
        window.history.pushState({}, '', newPath)
        // Trigger a popstate event to update the route
        window.dispatchEvent(new PopStateEvent('popstate'))
    }

    const handleBackToMain = () => {
        window.history.pushState({}, '', '/scheduling')
        // Trigger a popstate event to update the route
        window.dispatchEvent(new PopStateEvent('popstate'))
    }

    // Render different views based on currentView
    if (currentView === 'view-schedule') {
        return <ViewSchedule user={user} onBack={handleBackToMain} />
    }

    if (currentView === 'indicate-availability') {
        return <IndicateAvailability user={user} onBack={handleBackToMain} />
    }

    if (currentView === 'schedule-experiment') {
        return <ScheduleExperiment user={user} onBack={handleBackToMain} />
    }

    // Main view with cards
    return (
        <div className="p-6">
            <div className="mb-6">
                <h1 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
                    Scheduling
                </h1>
                <p className="text-gray-600 dark:text-gray-400">
                    This is the scheduling module of the dashboard. Here you can indicate your availability for upcoming experiment runs.
                </p>
            </div>

            {/* Scheduling Cards Grid */}
            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
                {/* View Complete Schedule Card */}
                <div
                    onClick={() => handleCardClick('view-schedule')}
                    className="bg-white dark:bg-gray-800 rounded-lg shadow-md hover:shadow-lg transition-shadow duration-200 cursor-pointer border border-gray-200 dark:border-gray-700 hover:border-blue-300"
                >
                    <div className="p-6">
                        <div className="flex items-center justify-between mb-4">
                            <div className="flex items-center">
                                <div className="w-12 h-12 bg-blue-100 dark:bg-blue-900/20 rounded-lg flex items-center justify-center">
                                    <svg className="w-6 h-6 text-blue-600 dark:text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" />
                                    </svg>
                                </div>
                            </div>
                            <div className="text-right">
                                <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 dark:bg-green-900/20 text-green-800 dark:text-green-400">
                                    Available
                                </span>
                            </div>
                        </div>

                        <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
                            View Complete Schedule
                        </h3>

                        <p className="text-sm text-gray-600 dark:text-gray-400 mb-4 line-clamp-2">
                            View the complete schedule of all upcoming experiment runs and their current status.
                        </p>

                        <div className="flex items-center justify-between text-sm text-gray-500 dark:text-gray-400">
                            <span>All experiments</span>
                            <div className="flex items-center text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300">
                                <span className="mr-1">View Schedule</span>
                                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                                </svg>
                            </div>
                        </div>
                    </div>
                </div>

                {/* Indicate Availability Card */}
                <div
                    onClick={() => handleCardClick('indicate-availability')}
                    className="bg-white dark:bg-gray-800 rounded-lg shadow-md hover:shadow-lg transition-shadow duration-200 cursor-pointer border border-gray-200 dark:border-gray-700 hover:border-blue-300"
                >
                    <div className="p-6">
                        <div className="flex items-center justify-between mb-4">
                            <div className="flex items-center">
                                <div className="w-12 h-12 bg-green-100 dark:bg-green-900/20 rounded-lg flex items-center justify-center">
                                    <svg className="w-6 h-6 text-green-600 dark:text-green-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
                                    </svg>
                                </div>
                            </div>
                            <div className="text-right">
                                <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 dark:bg-blue-900/20 text-blue-800 dark:text-blue-400">
                                    Active
                                </span>
                            </div>
                        </div>

                        <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
                            Indicate Your Availability
                        </h3>

                        <p className="text-sm text-gray-600 dark:text-gray-400 mb-4 line-clamp-2">
                            Set your availability preferences and time slots for upcoming experiment runs.
                        </p>

                        <div className="flex items-center justify-between text-sm text-gray-500 dark:text-gray-400">
                            <span>Personal settings</span>
                            <div className="flex items-center text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300">
                                <span className="mr-1">Set Availability</span>
                                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                                </svg>
                            </div>
                        </div>
                    </div>
                </div>

                {/* Schedule Experiment Card */}
                <div
                    onClick={() => handleCardClick('schedule-experiment')}
                    className="bg-white dark:bg-gray-800 rounded-lg shadow-md hover:shadow-lg transition-shadow duration-200 cursor-pointer border border-gray-200 dark:border-gray-700 hover:border-blue-300"
                >
                    <div className="p-6">
                        <div className="flex items-center justify-between mb-4">
                            <div className="flex items-center">
                                <div className="w-12 h-12 bg-purple-100 dark:bg-purple-900/20 rounded-lg flex items-center justify-center">
                                    <svg className="w-6 h-6 text-purple-600 dark:text-purple-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
                                    </svg>
                                </div>
                            </div>
                            <div className="text-right">
                                <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 dark:bg-yellow-900/20 text-yellow-800 dark:text-yellow-400">
                                    Planning
                                </span>
                            </div>
                        </div>

                        <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
                            Schedule Experiment
                        </h3>

                        <p className="text-sm text-gray-600 dark:text-gray-400 mb-4 line-clamp-2">
                            Schedule specific experiment runs and assign team members to upcoming sessions.
                        </p>

                        <div className="flex items-center justify-between text-sm text-gray-500 dark:text-gray-400">
                            <span>Experiment planning</span>
                            <div className="flex items-center text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300">
                                <span className="mr-1">Schedule Now</span>
                                <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                                </svg>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    )
}

// Placeholder components for the three scheduling features
function ViewSchedule({ user, onBack }: { user: User; onBack: () => void }) {
    // User context available for future features
    return (
        <div className="p-6">
            <div className="mb-6">
                <button
                    onClick={onBack}
                    className="flex items-center text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 mb-4"
                >
                    <svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
                    </svg>
                    Back to Scheduling
                </button>
                <h1 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
                    Complete Schedule
                </h1>
                <p className="text-gray-600 dark:text-gray-400">
                    View all scheduled experiment runs and their current status.
                </p>
            </div>

            <div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-6">
                <div className="text-center py-12">
                    <div className="mx-auto w-16 h-16 bg-blue-100 dark:bg-blue-900/20 rounded-full flex items-center justify-center mb-4">
                        <svg className="w-8 h-8 text-blue-600 dark:text-blue-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5H7a2 2 0 00-2 2v10a2 2 0 002 2h8a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01" />
                        </svg>
                    </div>
                    <h3 className="text-lg font-medium text-gray-900 dark:text-white mb-2">
                        Complete Schedule View
                    </h3>
                    <p className="text-gray-500 dark:text-gray-400 max-w-md mx-auto">
                        This view will show a comprehensive calendar and list of all scheduled experiment runs,
                        including dates, times, assigned team members, and current status.
                    </p>
                </div>
            </div>
        </div>
    )
}

function IndicateAvailability({ user, onBack }: { user: User; onBack: () => void }) {
    return (
        <div className="p-6">
            <div className="mb-6">
                <button
                    onClick={onBack}
                    className="flex items-center text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 mb-4"
                >
                    <svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
                    </svg>
                    Back to Scheduling
                </button>
                <h1 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
                    Indicate Availability
                </h1>
                <p className="text-gray-600 dark:text-gray-400">
                    Set your availability preferences and time slots for upcoming experiment runs.
                </p>
            </div>

            <div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-6">
                <AvailabilityCalendar user={user} />
            </div>
        </div>
    )
}

function ScheduleExperiment({ user, onBack }: { user: User; onBack: () => void }) {
    const [loading, setLoading] = useState(true)
    const [error, setError] = useState<string | null>(null)

    const [conductors, setConductors] = useState<User[]>([])
    const [conductorIdsWithFutureAvailability, setConductorIdsWithFutureAvailability] = useState<Set<string>>(new Set())
    const [selectedConductorIds, setSelectedConductorIds] = useState<Set<string>>(new Set())

    const [phases, setPhases] = useState<ExperimentPhase[]>([])
    const [expandedPhaseIds, setExpandedPhaseIds] = useState<Set<string>>(new Set())
    const [conductorsExpanded, setConductorsExpanded] = useState<boolean>(true)
    const [experimentsByPhase, setExperimentsByPhase] = useState<Record<string, Experiment[]>>({})
    const [repetitionsByExperiment, setRepetitionsByExperiment] = useState<Record<string, ExperimentRepetition[]>>({})
    const [selectedRepetitionIds, setSelectedRepetitionIds] = useState<Set<string>>(new Set())
    const [creatingRepetitionsFor, setCreatingRepetitionsFor] = useState<Set<string>>(new Set())
    const [soakingByExperiment, setSoakingByExperiment] = useState<Record<string, Soaking | null>>({})
    const [airdryingByExperiment, setAirdryingByExperiment] = useState<Record<string, Airdrying | null>>({})

    // Calendar state for selected conductors' availability
    const localizer = momentLocalizer(moment)
    const DnDCalendar = withDragAndDrop(Calendar)
    const [calendarView, setCalendarView] = useState(Views.WEEK)
    const [currentDate, setCurrentDate] = useState(new Date())
    const [availabilityEvents, setAvailabilityEvents] = useState<CalendarEvent[]>([])

    // Color map per conductor for calendar events
    const [conductorColorMap, setConductorColorMap] = useState<Record<string, string>>({})
    const colorPalette = ['#2563eb', '#059669', '#d97706', '#7c3aed', '#dc2626', '#0ea5e9', '#16a34a', '#f59e0b', '#9333ea', '#ef4444']

    // Repetition scheduling state
    const [scheduledRepetitions, setScheduledRepetitions] = useState<Record<string, {
        repetitionId: string
        experimentId: string
        soakingStart: Date | null
        airdryingStart: Date | null
        crackingStart: Date | null
    }>>({})

    // Track repetitions that have been dropped/moved and should show time points
    const [repetitionsWithTimes, setRepetitionsWithTimes] = useState<Set<string>>(new Set())
    // Track which repetitions are locked (prevent dragging)
    const [lockedSchedules, setLockedSchedules] = useState<Set<string>>(new Set())
    // Track which repetitions are currently being scheduled
    const [schedulingRepetitions, setSchedulingRepetitions] = useState<Set<string>>(new Set())

    // Visual style for repetition markers
    const [markerStyle, setMarkerStyle] = useState<'circles' | 'dots' | 'icons' | 'lines'>('lines')

    // Ref for calendar container to preserve scroll position
    const calendarRef = useRef<HTMLDivElement>(null)
    const scrollPositionRef = useRef<{ scrollTop: number; scrollLeft: number } | null>(null)

    useEffect(() => {
        const load = async () => {
            try {
                setLoading(true)
                setError(null)

                const [allUsers, allPhases] = await Promise.all([
                    userManagement.getAllUsers(),
                    experimentPhaseManagement.getAllExperimentPhases()
                ])

                // Filter conductors
                const conductorsOnly = allUsers.filter(u => u.roles.includes('conductor'))
                setConductors(conductorsOnly)

                // For each conductor, check if they have any availability in the future
                const conductorIds = conductorsOnly.map(c => c.id)
                setConductorIdsWithFutureAvailability(new Set(conductorIds))

                setPhases(allPhases)
            } catch (e: any) {
                setError(e?.message || 'Failed to load scheduling data')
            } finally {
                setLoading(false)
            }
        }
        load()
    }, [])

    const toggleConductor = (id: string) => {
        setSelectedConductorIds(prev => {
            const next = new Set(prev)
            if (next.has(id)) next.delete(id)
            else next.add(id)
            return next
        })
    }

    const toggleAllConductors = () => {
        const availableConductorIds = conductors
            .filter(c => conductorIdsWithFutureAvailability.has(c.id))
            .map(c => c.id)

        setSelectedConductorIds(prev => {
            // If all available conductors are selected, deselect all
            const allSelected = availableConductorIds.every(id => prev.has(id))
            if (allSelected) {
                return new Set()
            } else {
                // Select all available conductors
                return new Set(availableConductorIds)
            }
        })
    }

    // Fetch availability for selected conductors and build calendar events
    useEffect(() => {
        const loadSelectedAvailability = async () => {
            try {
                const selectedIds = Array.from(selectedConductorIds)
                if (selectedIds.length === 0) {
                    setAvailabilityEvents([])
                    return
                }

                // Assign consistent colors per conductor based on their position in the full conductors array
                // This ensures the same conductor always gets the same color, matching the checkbox list
                const newColorMap: Record<string, string> = {}
                conductors.forEach((conductor, index) => {
                    if (selectedIds.includes(conductor.id)) {
                        newColorMap[conductor.id] = colorPalette[index % colorPalette.length]
                    }
                })
                setConductorColorMap(newColorMap)

                // Fetch availability for selected conductors in a single query
                const { data, error } = await supabase
                    .from('conductor_availability')
                    .select('*')
                    .in('user_id', selectedIds)
                    .eq('status', 'active')
                    .gt('available_to', new Date().toISOString())
                    .order('available_from', { ascending: true })

                if (error) throw error

                // Map user_id -> display name
                const idToName: Record<string, string> = {}
                conductors.forEach(c => {
                    const name = [c.first_name, c.last_name].filter(Boolean).join(' ') || c.email
                    idToName[c.id] = name
                })

                const events: CalendarEvent[] = (data || []).map((r: any) => ({
                    id: r.id,
                    title: `${idToName[r.user_id] || 'Conductor'}`,
                    start: new Date(r.available_from),
                    end: new Date(r.available_to),
                    resource: r.user_id // Store conductor ID, not color
                }))

                setAvailabilityEvents(events)
            } catch (e) {
                // Fail silently for calendar, do not break main UI
                setAvailabilityEvents([])
            }
        }

        loadSelectedAvailability()
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [selectedConductorIds, conductors])

    const togglePhaseExpand = async (phaseId: string) => {
        setExpandedPhaseIds(prev => {
            const next = new Set(prev)
            if (next.has(phaseId)) next.delete(phaseId)
            else next.add(phaseId)
            return next
        })

        // Lazy-load experiments for this phase if not loaded
        if (!experimentsByPhase[phaseId]) {
            try {
                const exps = await experimentManagement.getExperimentsByPhaseId(phaseId)
                setExperimentsByPhase(prev => ({ ...prev, [phaseId]: exps }))

                // For each experiment, load repetitions and phase data
                const repsEntries = await Promise.all(
                    exps.map(async (exp) => {
                        const [reps, soaking, airdrying] = await Promise.all([
                            repetitionManagement.getExperimentRepetitions(exp.id),
                            phaseManagement.getSoakingByExperimentId(exp.id),
                            phaseManagement.getAirdryingByExperimentId(exp.id)
                        ])
                        return [exp.id, reps, soaking, airdrying] as const
                    })
                )

                // Update repetitions
                setRepetitionsByExperiment(prev => ({
                    ...prev,
                    ...Object.fromEntries(repsEntries.map(([id, reps]) => [id, reps]))
                }))

                // Update soaking data
                setSoakingByExperiment(prev => ({
                    ...prev,
                    ...Object.fromEntries(repsEntries.map(([id, , soaking]) => [id, soaking]))
                }))

                // Update airdrying data
                setAirdryingByExperiment(prev => ({
                    ...prev,
                    ...Object.fromEntries(repsEntries.map(([id, , , airdrying]) => [id, airdrying]))
                }))
            } catch (e: any) {
                setError(e?.message || 'Failed to load experiments or repetitions')
            }
        }
    }

    const toggleRepetition = (repId: string) => {
        setSelectedRepetitionIds(prev => {
            const next = new Set(prev)
            if (next.has(repId)) {
                next.delete(repId)
                // Remove from scheduled repetitions when unchecked
                setScheduledRepetitions(prevScheduled => {
                    const newScheduled = { ...prevScheduled }
                    delete newScheduled[repId]
                    return newScheduled
                })
                // Clear all related state when unchecked
                setRepetitionsWithTimes(prev => {
                    const next = new Set(prev)
                    next.delete(repId)
                    return next
                })
                setLockedSchedules(prev => {
                    const next = new Set(prev)
                    next.delete(repId)
                    return next
                })
                setSchedulingRepetitions(prev => {
                    const next = new Set(prev)
                    next.delete(repId)
                    return next
                })
                // Re-stagger remaining repetitions
                const remainingIds = Array.from(next).filter(id => id !== repId)
                if (remainingIds.length > 0) {
                    reStaggerRepetitions(remainingIds)
                }
            } else {
                next.add(repId)
                // Auto-spawn when checked - pass the updated set to ensure correct stagger calculation
                spawnSingleRepetition(repId, next)
                // Re-stagger all existing repetitions to prevent overlap
                reStaggerRepetitions([...next, repId])
            }
            return next
        })
    }

    const toggleAllRepetitionsInPhase = (phaseId: string) => {
        const experiments = experimentsByPhase[phaseId] || []
        const allRepetitions = experiments.flatMap(exp => repetitionsByExperiment[exp.id] || [])

        setSelectedRepetitionIds(prev => {
            // Check if all repetitions in this phase are selected
            const allSelected = allRepetitions.every(rep => prev.has(rep.id))

            if (allSelected) {
                // Deselect all repetitions in this phase
                const next = new Set(prev)
                allRepetitions.forEach(rep => {
                    next.delete(rep.id)
                    // Remove from scheduled repetitions
                    setScheduledRepetitions(prevScheduled => {
                        const newScheduled = { ...prevScheduled }
                        delete newScheduled[rep.id]
                        return newScheduled
                    })
                })
                return next
            } else {
                // Select all repetitions in this phase
                const next = new Set(prev)
                allRepetitions.forEach(rep => {
                    next.add(rep.id)
                    // Auto-spawn when checked - pass the updated set to ensure correct stagger calculation
                    spawnSingleRepetition(rep.id, next)
                })
                return next
            }
        })
    }

    const createRepetitionsForExperiment = async (experimentId: string) => {
        try {
            setCreatingRepetitionsFor(prev => new Set(prev).add(experimentId))
            setError(null)

            // Create all repetitions for this experiment
            const newRepetitions = await repetitionManagement.createAllRepetitions(experimentId)

            // Update the repetitions state
            setRepetitionsByExperiment(prev => ({
                ...prev,
                [experimentId]: newRepetitions
            }))
        } catch (e: any) {
            setError(e?.message || 'Failed to create repetitions')
        } finally {
            setCreatingRepetitionsFor(prev => {
                const next = new Set(prev)
                next.delete(experimentId)
                return next
            })
        }
    }

    // Re-stagger all repetitions to prevent overlap
    const reStaggerRepetitions = (repIds: string[]) => {
        const tomorrow = new Date()
        tomorrow.setDate(tomorrow.getDate() + 1)
        tomorrow.setHours(9, 0, 0, 0)

        setScheduledRepetitions(prev => {
            const newScheduled = { ...prev }

            repIds.forEach((repId, index) => {
                if (newScheduled[repId]) {
                    const staggerMinutes = index * 15 // 15 minutes between each repetition
                    const baseTime = new Date(tomorrow.getTime() + (staggerMinutes * 60000))

                    // Find the experiment for this repetition
                    let experimentId = ''
                    for (const [expId, reps] of Object.entries(repetitionsByExperiment)) {
                        if (reps.find(r => r.id === repId)) {
                            experimentId = expId
                            break
                        }
                    }

                    if (experimentId) {
                        const experiment = Object.values(experimentsByPhase).flat().find(e => e.id === experimentId)
                        const soaking = soakingByExperiment[experimentId]
                        const airdrying = airdryingByExperiment[experimentId]

                        if (experiment && soaking && airdrying) {
                            const soakingStart = new Date(baseTime)
                            const airdryingStart = new Date(soakingStart.getTime() + (soaking.soaking_duration_minutes * 60000))
                            const crackingStart = new Date(airdryingStart.getTime() + (airdrying.duration_minutes * 60000))

                            newScheduled[repId] = {
                                ...newScheduled[repId],
                                soakingStart,
                                airdryingStart,
                                crackingStart
                            }
                        }
                    }
                }
            })

            return newScheduled
        })
    }

    // Spawn a single repetition in calendar
    const spawnSingleRepetition = (repId: string, updatedSelectedIds?: Set<string>) => {
        const tomorrow = new Date()
        tomorrow.setDate(tomorrow.getDate() + 1)
        tomorrow.setHours(9, 0, 0, 0) // Default to 9 AM tomorrow

        // Find the experiment for this repetition
        let experimentId = ''
        for (const [expId, reps] of Object.entries(repetitionsByExperiment)) {
            if (reps.find(r => r.id === repId)) {
                experimentId = expId
                break
            }
        }

        if (experimentId) {
            const experiment = Object.values(experimentsByPhase).flat().find(e => e.id === experimentId)
            const soaking = soakingByExperiment[experimentId]
            const airdrying = airdryingByExperiment[experimentId]

            if (experiment && soaking && airdrying) {
                // Stagger the positioning to avoid overlap when multiple repetitions are selected
                // Use the updated set if provided, otherwise use current state (may be stale)
                const selectedReps = updatedSelectedIds ? Array.from(updatedSelectedIds) : Array.from(selectedRepetitionIds)
                const repIndex = selectedReps.indexOf(repId)
                // If repId not found in selectedReps, use the count of scheduled repetitions as fallback
                const staggerMinutes = repIndex >= 0 ? repIndex * 15 : Object.keys(scheduledRepetitions).length * 15

                const soakingStart = new Date(tomorrow.getTime() + (staggerMinutes * 60000))
                const airdryingStart = new Date(soakingStart.getTime() + (soaking.soaking_duration_minutes * 60000))
                const crackingStart = new Date(airdryingStart.getTime() + (airdrying.duration_minutes * 60000))

                setScheduledRepetitions(prev => ({
                    ...prev,
                    [repId]: {
                        repetitionId: repId,
                        experimentId,
                        soakingStart,
                        airdryingStart,
                        crackingStart
                    }
                }))
            }
        }
    }

    // Update phase timing when a marker is moved
    const updatePhaseTiming = (repId: string, phase: 'soaking' | 'airdrying' | 'cracking', newTime: Date) => {
        setScheduledRepetitions(prev => {
            const current = prev[repId]
            if (!current) return prev

            const experimentId = current.experimentId
            const soaking = soakingByExperiment[experimentId]
            const airdrying = airdryingByExperiment[experimentId]

            if (!soaking || !airdrying) return prev

            let newScheduled = { ...prev }

            const clampToReasonableHours = (d: Date) => {
                const min = new Date(d)
                min.setHours(5, 0, 0, 0)
                const max = new Date(d)
                max.setHours(23, 0, 0, 0)
                const t = d.getTime()
                return new Date(Math.min(Math.max(t, min.getTime()), max.getTime()))
            }

            if (phase === 'soaking') {
                const soakingStart = clampToReasonableHours(newTime)
                const airdryingStart = clampToReasonableHours(new Date(soakingStart.getTime() + (soaking.soaking_duration_minutes * 60000)))
                const crackingStart = clampToReasonableHours(new Date(airdryingStart.getTime() + (airdrying.duration_minutes * 60000)))

                newScheduled[repId] = {
                    ...current,
                    soakingStart,
                    airdryingStart,
                    crackingStart
                }
            } else if (phase === 'airdrying') {
                const airdryingStart = clampToReasonableHours(newTime)
                const soakingStart = clampToReasonableHours(new Date(airdryingStart.getTime() - (soaking.soaking_duration_minutes * 60000)))
                const crackingStart = clampToReasonableHours(new Date(airdryingStart.getTime() + (airdrying.duration_minutes * 60000)))

                newScheduled[repId] = {
                    ...current,
                    soakingStart,
                    airdryingStart,
                    crackingStart
                }
            } else if (phase === 'cracking') {
                const crackingStart = clampToReasonableHours(newTime)
                const airdryingStart = clampToReasonableHours(new Date(crackingStart.getTime() - (airdrying.duration_minutes * 60000)))
                const soakingStart = clampToReasonableHours(new Date(airdryingStart.getTime() - (soaking.soaking_duration_minutes * 60000)))

                newScheduled[repId] = {
                    ...current,
                    soakingStart,
                    airdryingStart,
                    crackingStart
                }
            }

            return newScheduled
        })
    }

    // Generate calendar events for scheduled repetitions (memoized)
    const generateRepetitionEvents = useCallback((): CalendarEvent[] => {
        const events: CalendarEvent[] = []

        Object.values(scheduledRepetitions).forEach(scheduled => {
            const experiment = Object.values(experimentsByPhase).flat().find(e => e.id === scheduled.experimentId)
            const repetition = repetitionsByExperiment[scheduled.experimentId]?.find(r => r.id === scheduled.repetitionId)

            if (experiment && repetition && scheduled.soakingStart) {
                // Soaking marker
                events.push({
                    id: `${scheduled.repetitionId}-soaking`,
                    title: `💧 Soaking - Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
                    start: scheduled.soakingStart,
                    end: new Date(scheduled.soakingStart.getTime() + 15 * 60000), // 15 minute duration for better visibility
                    resource: 'soaking'
                })

                // Airdrying marker
                if (scheduled.airdryingStart) {
                    events.push({
                        id: `${scheduled.repetitionId}-airdrying`,
                        title: `🌬️ Airdrying - Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
                        start: scheduled.airdryingStart,
                        end: new Date(scheduled.airdryingStart.getTime() + 15 * 60000), // 15 minute duration for better visibility
                        resource: 'airdrying'
                    })
                }

                // Cracking marker
                if (scheduled.crackingStart) {
                    events.push({
                        id: `${scheduled.repetitionId}-cracking`,
                        title: `⚡ Cracking - Exp ${experiment.experiment_number} Rep ${repetition.repetition_number}`,
                        start: scheduled.crackingStart,
                        end: new Date(scheduled.crackingStart.getTime() + 15 * 60000), // 15 minute duration for better visibility
                        resource: 'cracking'
                    })
                }
            }
        })

        return events
    }, [scheduledRepetitions, experimentsByPhase, repetitionsByExperiment])

    // Memoize the calendar events to prevent unnecessary re-renders
    const calendarEvents = useMemo(() => generateRepetitionEvents(), [generateRepetitionEvents])

    // Functions to preserve and restore scroll position
    const preserveScrollPosition = useCallback(() => {
        if (calendarRef.current) {
            const scrollContainer = calendarRef.current.querySelector('.rbc-time-content') as HTMLElement
            if (scrollContainer) {
                scrollPositionRef.current = {
                    scrollTop: scrollContainer.scrollTop,
                    scrollLeft: scrollContainer.scrollLeft
                }
            }
        }
    }, [])

    const restoreScrollPosition = useCallback(() => {
        if (calendarRef.current && scrollPositionRef.current) {
            const scrollContainer = calendarRef.current.querySelector('.rbc-time-content') as HTMLElement
            if (scrollContainer) {
                scrollContainer.scrollTop = scrollPositionRef.current.scrollTop
                scrollContainer.scrollLeft = scrollPositionRef.current.scrollLeft
            }
        }
    }, [])

    // Helper functions for scheduling
    const formatTime = (date: Date | null) => {
        if (!date) return 'Not set'
        return moment(date).format('MMM D, h:mm A')
    }

    const toggleScheduleLock = (repId: string) => {
        setLockedSchedules(prev => {
            const next = new Set(prev)
            if (next.has(repId)) {
                next.delete(repId)
            } else {
                next.add(repId)
            }
            return next
        })
    }

    const draggableAccessor = useCallback((event: any) => {
        // Only make repetition markers draggable, not availability events
        const resource = event.resource as string
        if (resource === 'soaking' || resource === 'airdrying' || resource === 'cracking') {
            // Check if the repetition is locked
            const eventId = event.id as string
            const repId = eventId.split('-')[0]
            const isLocked = lockedSchedules.has(repId)
            return !isLocked
        }
        return false
    }, [lockedSchedules])

    const eventPropGetter = useCallback((event: any) => {
        const resource = event.resource as string

        // Styling for repetition markers (foreground events)
        if (resource === 'soaking' || resource === 'airdrying' || resource === 'cracking') {
            const eventId = event.id as string
            const repId = eventId.split('-')[0]
            const isLocked = lockedSchedules.has(repId)

            const colors = {
                soaking: '#3b82f6', // blue
                airdrying: '#10b981', // green  
                cracking: '#f59e0b'  // orange
            }
            const color = colors[resource as keyof typeof colors] || '#6b7280'

            return {
                style: {
                    backgroundColor: isLocked ? '#9ca3af' : color, // gray if locked
                    borderColor: isLocked ? color : color, // border takes original color when locked
                    color: 'white',
                    borderRadius: '8px',
                    border: '2px solid',
                    height: '40px',
                    minHeight: '40px',
                    fontSize: '12px',
                    padding: '8px 12px',
                    display: 'flex',
                    flexDirection: 'row',
                    alignItems: 'center',
                    justifyContent: 'flex-start',
                    fontWeight: 'bold',
                    zIndex: 10,
                    position: 'relative',
                    lineHeight: '1.4',
                    textShadow: '1px 1px 2px rgba(0,0,0,0.7)',
                    gap: '8px',
                    overflow: 'hidden',
                    textOverflow: 'ellipsis',
                    whiteSpace: 'nowrap',
                    cursor: isLocked ? 'not-allowed' : 'grab',
                    boxShadow: isLocked ? '0 1px 2px rgba(0,0,0,0.1)' : '0 2px 4px rgba(0,0,0,0.2)',
                    transition: 'all 0.2s ease',
                    opacity: isLocked ? 0.7 : 1
                }
            }
        }

        // Default styling for other events
        return {}
    }, [lockedSchedules])

    const scheduleRepetition = async (repId: string, experimentId: string) => {
        setSchedulingRepetitions(prev => new Set(prev).add(repId))

        try {
            const scheduled = scheduledRepetitions[repId]
            if (!scheduled) throw new Error('No scheduled times found')

            const { soakingStart, airdryingStart, crackingStart } = scheduled
            if (!soakingStart || !airdryingStart || !crackingStart) {
                throw new Error('All time points must be set')
            }

            const soaking = soakingByExperiment[experimentId]
            const airdrying = airdryingByExperiment[experimentId]

            if (!soaking || !airdrying) throw new Error('Phase data not found')

            // Update repetition scheduled_date (earliest time point)
            await repetitionManagement.updateRepetition(repId, {
                scheduled_date: soakingStart.toISOString()
            })

            // Create/update soaking record with repetition_id
            await phaseManagement.createSoaking({
                repetition_id: repId,
                scheduled_start_time: soakingStart.toISOString(),
                soaking_duration_minutes: soaking.soaking_duration_minutes
            })

            // Create/update airdrying record with repetition_id
            await phaseManagement.createAirdrying({
                repetition_id: repId,
                scheduled_start_time: airdryingStart.toISOString(),
                duration_minutes: airdrying.duration_minutes
            })

            // Create/update cracking record with repetition_id
            // Note: cracking requires machine_type_id - need to get from experiment phase
            const experiment = Object.values(experimentsByPhase).flat().find(e => e.id === experimentId)
            const phase = phases.find(p => p.id === experiment?.phase_id)

            if (phase?.cracking_machine_type_id) {
                await phaseManagement.createCracking({
                    repetition_id: repId,
                    machine_type_id: phase.cracking_machine_type_id,
                    scheduled_start_time: crackingStart.toISOString()
                })
            }

            // Update local state to reflect scheduling
            setRepetitionsByExperiment(prev => ({
                ...prev,
                [experimentId]: prev[experimentId]?.map(r =>
                    r.id === repId
                        ? { ...r, scheduled_date: soakingStart.toISOString() }
                        : r
                ) || []
            }))

        } catch (error: any) {
            setError(error?.message || 'Failed to schedule repetition')
        } finally {
            setSchedulingRepetitions(prev => {
                const next = new Set(prev)
                next.delete(repId)
                return next
            })
        }
    }

    // Restore scroll position after scheduledRepetitions changes
    useEffect(() => {
        if (scrollPositionRef.current) {
            // Use a longer delay to ensure the calendar has fully re-rendered
            const timeoutId = setTimeout(() => {
                restoreScrollPosition()
            }, 50)

            return () => clearTimeout(timeoutId)
        }
    }, [scheduledRepetitions, restoreScrollPosition])


    return (
        <div className="h-full flex flex-col overflow-hidden -m-4 md:-m-6">
            <div className="p-6 flex-shrink-0">
                <button
                    onClick={onBack}
                    className="flex items-center text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 mb-4"
                >
                    <svg className="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                        <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
                    </svg>
                    Back to Scheduling
                </button>
                <h1 className="text-2xl font-bold text-gray-900 dark:text-white mb-2">
                    Schedule Experiment
                </h1>
                <p className="text-gray-600 dark:text-gray-400">
                    Schedule specific experiment runs and assign team members to upcoming sessions.
                </p>
            </div>

            <div className="px-6 pb-6 flex-1 min-h-0 overflow-hidden">
                <div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-6 h-full flex flex-col min-h-0 overflow-hidden">
                {error && (
                    <div className="mb-4 text-sm text-red-600 dark:text-red-400">{error}</div>
                )}
                {loading ? (
                    <div className="text-center py-12">
                        <div className="mx-auto w-16 h-16 bg-purple-100 dark:bg-purple-900/20 rounded-full flex items-center justify-center mb-4">
                            <svg className="w-8 h-8 text-purple-600 dark:text-purple-400 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 12a8 8 0 018-8" />
                            </svg>
                        </div>
                        <h3 className="text-lg font-medium text-gray-900 dark:text-white mb-2">Loading…</h3>
                        <p className="text-gray-500 dark:text-gray-400 max-w-md mx-auto">Fetching conductors, phases, and experiments.</p>
                    </div>
                ) : (
                    <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 flex-shrink-0">
                        {/* Left: Conductors with future availability */}
                        <div>
                            <div className="flex items-center justify-between mb-3">
                                <h2 className="text-lg font-semibold text-gray-900 dark:text-white">Conductors</h2>
                                <span className="text-xs text-gray-500 dark:text-gray-400">Select to consider for scheduling</span>
                            </div>
                            <div className="border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-200 dark:divide-gray-700">
                                {conductors.length === 0 ? (
                                    <div className="p-4 text-sm text-gray-500 dark:text-gray-400">No conductors found.</div>
                                ) : (
                                    <div>
                                        <button
                                            className="w-full flex items-center justify-between p-3 hover:bg-gray-50 dark:hover:bg-gray-700/50"
                                            onClick={() => setConductorsExpanded(!conductorsExpanded)}
                                        >
                                            <span className="text-sm font-medium text-gray-900 dark:text-white">All Conductors</span>
                                            <svg className={`w-4 h-4 text-gray-500 transition-transform ${conductorsExpanded ? 'rotate-180' : ''}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                                            </svg>
                                        </button>
                                        {conductorsExpanded && (
                                            <div className="bg-gray-50 dark:bg-gray-800/50 max-h-[420px] overflow-y-auto">
                                                {/* Select All checkbox */}
                                                <div className="p-3 border-b border-gray-200 dark:border-gray-600">
                                                    <label className="flex items-center gap-2">
                                                        <input
                                                            type="checkbox"
                                                            className="h-4 w-4 text-blue-600 border-gray-300 rounded"
                                                            checked={conductors.filter(c => conductorIdsWithFutureAvailability.has(c.id)).every(c => selectedConductorIds.has(c.id)) && conductors.filter(c => conductorIdsWithFutureAvailability.has(c.id)).length > 0}
                                                            onChange={toggleAllConductors}
                                                        />
                                                        <span className="text-sm font-medium text-gray-700 dark:text-gray-300">Select All Available Conductors</span>
                                                    </label>
                                                </div>
                                                {/* Conductors list */}
                                                <div className="divide-y divide-gray-200 dark:divide-gray-700">
                                                    {conductors.map((c, index) => {
                                                        const name = [c.first_name, c.last_name].filter(Boolean).join(' ') || c.email
                                                        const hasFuture = conductorIdsWithFutureAvailability.has(c.id)
                                                        const checked = selectedConductorIds.has(c.id)
                                                        // Use the same color mapping as the calendar (from conductorColorMap)
                                                        const conductorColor = checked ? (conductorColorMap[c.id] || colorPalette[index % colorPalette.length]) : null

                                                        return (
                                                            <label
                                                                key={c.id}
                                                                className={`flex items-center justify-between p-3 ${!hasFuture ? 'opacity-50' : ''} ${checked ? 'border-l-4' : ''} hover:bg-gray-100 dark:hover:bg-gray-700/30`}
                                                                style={checked && conductorColor ? { borderLeftColor: conductorColor + '60' } : {}}
                                                            >
                                                                <div className="flex items-center gap-3">
                                                                    <input
                                                                        type="checkbox"
                                                                        className="h-4 w-4 text-blue-600 border-gray-300 rounded"
                                                                        checked={checked}
                                                                        onChange={() => toggleConductor(c.id)}
                                                                        disabled={!hasFuture}
                                                                    />
                                                                    <div>
                                                                        <div className="text-sm font-medium text-gray-900 dark:text-white">{name}</div>
                                                                        <div className="text-xs text-gray-500 dark:text-gray-400">{c.email}</div>
                                                                    </div>
                                                                </div>
                                                                <span className={`text-xs ${hasFuture ? 'text-green-600 dark:text-green-400' : 'text-gray-400'}`}>{hasFuture ? 'Available' : 'No availability'}</span>
                                                            </label>
                                                        )
                                                    })}
                                                </div>
                                            </div>
                                        )}
                                    </div>
                                )}
                            </div>
                        </div>

                        {/* Right: Phases -> Experiments -> Repetitions */}
                        <div>
                            <div className="flex items-center justify-between mb-3">
                                <h2 className="text-lg font-semibold text-gray-900 dark:text-white">Experiment Phases</h2>
                                <span className="text-xs text-gray-500 dark:text-gray-400">Expand and select repetitions</span>
                            </div>
                            <div className="border border-gray-200 dark:border-gray-700 rounded-md divide-y divide-gray-200 dark:divide-gray-700">
                                {phases.length === 0 && (
                                    <div className="p-4 text-sm text-gray-500 dark:text-gray-400">No phases defined.</div>
                                )}
                                {phases.map(phase => {
                                    const expanded = expandedPhaseIds.has(phase.id)
                                    const experiments = experimentsByPhase[phase.id] || []
                                    return (
                                        <div key={phase.id}>
                                            <button
                                                className="w-full flex items-center justify-between p-3 hover:bg-gray-50 dark:hover:bg-gray-700/50"
                                                onClick={() => togglePhaseExpand(phase.id)}
                                            >
                                                <span className="text-sm font-medium text-gray-900 dark:text-white">{phase.name}</span>
                                                <svg className={`w-4 h-4 text-gray-500 transition-transform ${expanded ? 'rotate-180' : ''}`} fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                                    <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
                                                </svg>
                                            </button>
                                            {expanded && (
                                                <div className="bg-gray-50 dark:bg-gray-800/50 max-h-96 overflow-y-auto">
                                                    {/* Select All checkbox for this phase */}
                                                    {experiments.length > 0 && (
                                                        <div className="p-3 border-b border-gray-200 dark:border-gray-600">
                                                            <label className="flex items-center gap-2">
                                                                <input
                                                                    type="checkbox"
                                                                    className="h-4 w-4 text-blue-600 border-gray-300 rounded"
                                                                    checked={experiments.flatMap(exp => repetitionsByExperiment[exp.id] || []).every(rep => selectedRepetitionIds.has(rep.id)) && experiments.flatMap(exp => repetitionsByExperiment[exp.id] || []).length > 0}
                                                                    onChange={() => toggleAllRepetitionsInPhase(phase.id)}
                                                                />
                                                                <span className="text-sm font-medium text-gray-700 dark:text-gray-300">Select All Repetitions in {phase.name}</span>
                                                            </label>
                                                        </div>
                                                    )}
                                                    {experiments.length === 0 && (
                                                        <div className="p-3 text-xs text-gray-500 dark:text-gray-400">No experiments in this phase.</div>
                                                    )}
                                                    {experiments.map(exp => {
                                                        const reps = repetitionsByExperiment[exp.id] || []
                                                        const isCreating = creatingRepetitionsFor.has(exp.id)
                                                        const allRepsCreated = reps.length >= exp.reps_required
                                                        const soaking = soakingByExperiment[exp.id]
                                                        const airdrying = airdryingByExperiment[exp.id]

                                                        const getSoakDisplay = () => {
                                                            if (soaking) return `${soaking.soaking_duration_minutes}min`
                                                            return '—'
                                                        }

                                                        const getAirdryDisplay = () => {
                                                            if (airdrying) return `${airdrying.duration_minutes}min`
                                                            return '—'
                                                        }

                                                        return (
                                                            <div key={exp.id} className="border-t border-gray-200 dark:border-gray-700">
                                                                <div className="px-3 py-2 flex items-center justify-between">
                                                                    <div className="text-sm text-gray-900 dark:text-white">
                                                                        <span className="font-medium">Exp #{exp.experiment_number}</span>
                                                                        <span className="mx-2 text-gray-400">•</span>
                                                                        <span className="text-xs text-gray-600 dark:text-gray-300">Soak: {getSoakDisplay()}</span>
                                                                        <span className="mx-2 text-gray-400">/</span>
                                                                        <span className="text-xs text-gray-600 dark:text-gray-300">Air-dry: {getAirdryDisplay()}</span>
                                                                    </div>
                                                                    {!allRepsCreated && (
                                                                        <button
                                                                            onClick={() => createRepetitionsForExperiment(exp.id)}
                                                                            disabled={isCreating}
                                                                            className="text-xs bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400 text-white px-2 py-1 rounded transition-colors"
                                                                        >
                                                                            {isCreating ? 'Creating...' : 'Add Repetition'}
                                                                        </button>
                                                                    )}
                                                                </div>
                                                                <div className="px-3 pb-2 space-y-2">
                                                                    {reps.map(rep => {
                                                                        const checked = selectedRepetitionIds.has(rep.id)
                                                                        const hasTimes = repetitionsWithTimes.has(rep.id)
                                                                        const scheduled = scheduledRepetitions[rep.id]
                                                                        const isLocked = lockedSchedules.has(rep.id)
                                                                        const isScheduling = schedulingRepetitions.has(rep.id)

                                                                        return (
                                                                            <div key={rep.id} className="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded p-3">
                                                                                {/* Checkbox row */}
                                                                                <label className="flex items-center gap-2">
                                                                                    <input
                                                                                        type="checkbox"
                                                                                        className="h-4 w-4 text-blue-600 border-gray-300 rounded"
                                                                                        checked={checked}
                                                                                        onChange={() => toggleRepetition(rep.id)}
                                                                                    />
                                                                                    <span className="text-sm font-medium text-gray-700 dark:text-gray-300">Rep {rep.repetition_number}</span>
                                                                                </label>

                                                                                {/* Time points (shown only if has been dropped/moved) */}
                                                                                {hasTimes && scheduled && (
                                                                                    <div className="mt-2 ml-6 text-xs space-y-1">
                                                                                        <div className="flex items-center gap-2">
                                                                                            <span>💧</span>
                                                                                            <span>Soaking: {formatTime(scheduled.soakingStart)}</span>
                                                                                        </div>
                                                                                        <div className="flex items-center gap-2">
                                                                                            <span>🌬️</span>
                                                                                            <span>Airdrying: {formatTime(scheduled.airdryingStart)}</span>
                                                                                        </div>
                                                                                        <div className="flex items-center gap-2">
                                                                                            <span>⚡</span>
                                                                                            <span>Cracking: {formatTime(scheduled.crackingStart)}</span>
                                                                                        </div>

                                                                                        {/* Lock checkbox and Schedule button */}
                                                                                        <div className="flex items-center gap-3 mt-3 pt-2 border-t border-gray-200 dark:border-gray-600">
                                                                                            <label className="flex items-center gap-2">
                                                                                                <input
                                                                                                    type="checkbox"
                                                                                                    className="h-3 w-3 text-blue-600 border-gray-300 rounded"
                                                                                                    checked={isLocked}
                                                                                                    onChange={() => toggleScheduleLock(rep.id)}
                                                                                                />
                                                                                                <span className="text-xs text-gray-600 dark:text-gray-400">Lock</span>
                                                                                            </label>
                                                                                            <button
                                                                                                onClick={() => scheduleRepetition(rep.id, exp.id)}
                                                                                                disabled={isScheduling || !isLocked}
                                                                                                className="px-3 py-1 bg-green-600 hover:bg-green-700 disabled:bg-gray-400 text-white rounded text-xs transition-colors"
                                                                                            >
                                                                                                {isScheduling ? 'Scheduling...' : 'Schedule'}
                                                                                            </button>
                                                                                        </div>
                                                                                    </div>
                                                                                )}
                                                                            </div>
                                                                        )
                                                                    })}
                                                                    {reps.length === 0 && !isCreating && (
                                                                        <div className="text-xs text-gray-500 dark:text-gray-400 col-span-full">No repetitions created. Click "Create Reps" to generate them.</div>
                                                                    )}
                                                                    {isCreating && (
                                                                        <div className="text-xs text-blue-600 dark:text-blue-400 col-span-full flex items-center gap-2">
                                                                            <svg className="w-3 h-3 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                                                                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 12a8 8 0 018-8" />
                                                                            </svg>
                                                                            Creating {exp.reps_required} repetitions...
                                                                        </div>
                                                                    )}
                                                                </div>
                                                            </div>
                                                        )
                                                    })}
                                                </div>
                                            )}
                                        </div>
                                    )
                                })}
                            </div>
                        </div>
                    </div>
                )}
                {/* Week Calendar for selected conductors' availability */}
                <div className="mt-6 flex flex-col flex-1 min-h-0 overflow-hidden">
                    <div className="flex justify-between items-center mb-3 flex-shrink-0">
                        <h3 className="text-lg font-semibold text-gray-900 dark:text-white">Selected Conductors' Availability & Experiment Scheduling</h3>
                        <div className="flex gap-2 items-center">
                            {/* Day-by-day navigation buttons (only show in week view) */}
                            {calendarView === Views.WEEK && (
                                <div className="flex items-center gap-1 mr-2">
                                    <button
                                        onClick={() => {
                                            const newDate = new Date(currentDate)
                                            newDate.setDate(newDate.getDate() - 1)
                                            setCurrentDate(newDate)
                                        }}
                                        className="px-2 py-1 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded border border-gray-300 dark:border-gray-600"
                                        title="Previous day"
                                    >
                                        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
                                        </svg>
                                    </button>
                                    <button
                                        onClick={() => {
                                            const newDate = new Date(currentDate)
                                            newDate.setDate(newDate.getDate() + 1)
                                            setCurrentDate(newDate)
                                        }}
                                        className="px-2 py-1 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 rounded border border-gray-300 dark:border-gray-600"
                                        title="Next day"
                                    >
                                        <svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                                            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
                                        </svg>
                                    </button>
                                    <span className="text-xs text-gray-500 dark:text-gray-400 ml-1">Day</span>
                                </div>
                            )}
                            <span className="text-sm text-gray-600 dark:text-gray-400">Marker Style:</span>
                            <button
                                onClick={() => setMarkerStyle('lines')}
                                className={`px-3 py-1 text-xs rounded ${markerStyle === 'lines'
                                    ? 'bg-blue-500 text-white'
                                    : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
                                    }`}
                            >
                                Lines
                            </button>
                            <button
                                onClick={() => setMarkerStyle('circles')}
                                className={`px-3 py-1 text-xs rounded ${markerStyle === 'circles'
                                    ? 'bg-blue-500 text-white'
                                    : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
                                    }`}
                            >
                                Circles
                            </button>
                            <button
                                onClick={() => setMarkerStyle('dots')}
                                className={`px-3 py-1 text-xs rounded ${markerStyle === 'dots'
                                    ? 'bg-blue-500 text-white'
                                    : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
                                    }`}
                            >
                                Dots
                            </button>
                            <button
                                onClick={() => setMarkerStyle('icons')}
                                className={`px-3 py-1 text-xs rounded ${markerStyle === 'icons'
                                    ? 'bg-blue-500 text-white'
                                    : 'bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300'
                                    }`}
                            >
                                Icons
                            </button>
                        </div>
                    </div>
                    <div ref={calendarRef} className="flex-1 min-h-0 border border-gray-200 dark:border-gray-700 rounded-md overflow-hidden relative">
                        <DndProvider backend={HTML5Backend}>
                            <DnDCalendar
                                localizer={localizer}
                                events={calendarEvents}
                                backgroundEvents={availabilityEvents}
                                startAccessor="start"
                                endAccessor="end"
                                titleAccessor="title"
                                style={{ height: '100%' }}
                                view={calendarView}
                                onView={setCalendarView}
                                date={currentDate}
                                onNavigate={setCurrentDate}
                                views={[Views.WEEK, Views.DAY]}
                                dayLayoutAlgorithm="no-overlap"
                                draggableAccessor={draggableAccessor}
                                onEventDrop={({ event, start }: { event: any, start: Date }) => {
                                    // Preserve scroll position before updating
                                    preserveScrollPosition()

                                    // Handle dragging repetition markers
                                    const eventId = event.id as string
                                    // Clamp to reasonable working hours (5AM to 11PM) to prevent extreme times
                                    const clampToReasonableHours = (d: Date) => {
                                        const min = new Date(d)
                                        min.setHours(5, 0, 0, 0)
                                        const max = new Date(d)
                                        max.setHours(23, 0, 0, 0)
                                        const t = d.getTime()
                                        return new Date(Math.min(Math.max(t, min.getTime()), max.getTime()))
                                    }
                                    const clampedStart = clampToReasonableHours(start)

                                    let repId = ''
                                    if (eventId.includes('-soaking')) {
                                        repId = eventId.replace('-soaking', '')
                                        updatePhaseTiming(repId, 'soaking', clampedStart)
                                    } else if (eventId.includes('-airdrying')) {
                                        repId = eventId.replace('-airdrying', '')
                                        updatePhaseTiming(repId, 'airdrying', clampedStart)
                                    } else if (eventId.includes('-cracking')) {
                                        repId = eventId.replace('-cracking', '')
                                        updatePhaseTiming(repId, 'cracking', clampedStart)
                                    }

                                    // Add repetition to show time points
                                    if (repId) {
                                        setRepetitionsWithTimes(prev => new Set(prev).add(repId))
                                    }

                                    // Restore scroll position after a brief delay to allow for re-render
                                    setTimeout(() => {
                                        restoreScrollPosition()
                                    }, 10)
                                }}
                                eventPropGetter={eventPropGetter}
                                backgroundEventPropGetter={(event: any) => {
                                    // Styling for background events (conductor availability)
                                    const conductorId = event.resource
                                    const color = conductorColorMap[conductorId] || '#2563eb'
                                    return {
                                        style: {
                                            backgroundColor: color + '40', // ~25% transparency for background
                                            borderColor: color,
                                            borderWidth: '1px',
                                            borderStyle: 'solid',
                                            color: 'transparent',
                                            borderRadius: '4px',
                                            opacity: 0.6,
                                            height: 'auto',
                                            minHeight: '20px',
                                            fontSize: '0px',
                                            padding: '0px',
                                            overflow: 'hidden',
                                            textOverflow: 'ellipsis',
                                            whiteSpace: 'nowrap'
                                        }
                                    }
                                }}
                                popup
                                showMultiDayTimes
                                doShowMore={true}
                                step={30}
                                timeslots={2}
                            />
                        </DndProvider>
                    </div>

                </div>
                </div>
            </div>
        </div>
    )
}

// Availability Calendar Component
function AvailabilityCalendar({ user }: { user: User }) {
    // User context available for future features like saving preferences
    const localizer = momentLocalizer(moment)
    const [events, setEvents] = useState<CalendarEvent[]>([])

    const [selectedDate, setSelectedDate] = useState<Date | null>(null)
    const [showTimeSlotForm, setShowTimeSlotForm] = useState(false)
    const [newTimeSlot, setNewTimeSlot] = useState({
        startTime: '09:00',
        endTime: '17:00'
    })
    const [currentView, setCurrentView] = useState(Views.MONTH)
    const [currentDate, setCurrentDate] = useState(new Date())

    // Load availability from DB on mount
    useEffect(() => {
        const loadAvailability = async () => {
            try {
                const records = await availabilityManagement.getMyAvailability()
                const mapped: CalendarEvent[] = records.map(r => ({
                    id: r.id,
                    title: 'Available',
                    start: new Date(r.available_from),
                    end: new Date(r.available_to),
                    resource: 'available'
                }))
                setEvents(mapped)
            } catch (e) {
                console.error('Failed to load availability', e)
            }
        }
        loadAvailability()
    }, [])

    const eventStyleGetter = (event: CalendarEvent) => {
        return {
            style: {
                backgroundColor: '#10b981', // green-500 for available
                borderColor: '#10b981',
                color: 'white',
                borderRadius: '4px',
                border: 'none',
                display: 'block'
            }
        }
    }

    const handleSelectSlot = ({ start, end }: { start: Date; end: Date }) => {
        // Set the selected date and show the time slot form
        setSelectedDate(start)
        setShowTimeSlotForm(true)

        // Pre-fill the form with the selected time range
        const startTime = moment(start).format('HH:mm')
        const endTime = moment(end).format('HH:mm')
        setNewTimeSlot({
            startTime,
            endTime
        })
    }

    const handleSelectEvent = async (event: CalendarEvent) => {
        if (!window.confirm('Do you want to remove this availability?')) {
            return
        }
        try {
            if (typeof event.id === 'string') {
                await availabilityManagement.deleteAvailability(event.id)
            }
            setEvents(events.filter(e => e.id !== event.id))
        } catch (e: any) {
            alert(e?.message || 'Failed to delete availability.')
            console.error('Failed to delete availability', e)
        }
    }

    const handleAddTimeSlot = async () => {
        if (!selectedDate) return

        const [startHour, startMinute] = newTimeSlot.startTime.split(':').map(Number)
        const [endHour, endMinute] = newTimeSlot.endTime.split(':').map(Number)

        const startDateTime = new Date(selectedDate)
        startDateTime.setHours(startHour, startMinute, 0, 0)

        const endDateTime = new Date(selectedDate)
        endDateTime.setHours(endHour, endMinute, 0, 0)

        // Check for overlapping events
        const hasOverlap = events.some(event => {
            const eventStart = new Date(event.start)
            const eventEnd = new Date(event.end)
            return (
                eventStart.toDateString() === selectedDate.toDateString() &&
                ((startDateTime >= eventStart && startDateTime < eventEnd) ||
                    (endDateTime > eventStart && endDateTime <= eventEnd) ||
                    (startDateTime <= eventStart && endDateTime >= eventEnd))
            )
        })

        if (hasOverlap) {
            alert('This time slot overlaps with an existing availability. Please choose a different time.')
            return
        }

        try {
            // Persist to DB first to get real ID and server validation
            const created = await availabilityManagement.createAvailability({
                available_from: startDateTime.toISOString(),
                available_to: endDateTime.toISOString()
            })

            const newEvent: CalendarEvent = {
                id: created.id,
                title: 'Available',
                start: new Date(created.available_from),
                end: new Date(created.available_to),
                resource: 'available'
            }

            setEvents([...events, newEvent])
            setShowTimeSlotForm(false)
            setSelectedDate(null)
        } catch (e: any) {
            alert(e?.message || 'Failed to save availability. Please try again.')
            console.error('Failed to create availability', e)
        }
    }

    const handleCancelTimeSlot = () => {
        setShowTimeSlotForm(false)
        setSelectedDate(null)
    }

    const getEventsForDate = (date: Date) => {
        return events.filter(event => {
            const eventDate = new Date(event.start)
            return eventDate.toDateString() === date.toDateString()
        })
    }

    return (
        <div className="space-y-6">
            {/* Calendar Header */}
            <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between">
                <div>
                    <h2 className="text-xl font-semibold text-gray-900 dark:text-white">
                        Availability Calendar
                    </h2>
                    <p className="text-sm text-gray-600 dark:text-gray-400 mt-1">
                        Click and drag to add availability slots, or click on existing events to remove them. You can add multiple time slots per day.
                    </p>
                </div>

                {/* Legend */}
                <div className="flex items-center space-x-4 mt-4 sm:mt-0">
                    <div className="flex items-center">
                        <div className="w-3 h-3 bg-green-500 rounded mr-2"></div>
                        <span className="text-sm text-gray-600 dark:text-gray-400">Available</span>
                    </div>
                </div>
            </div>

            {/* Time Slot Form Modal */}
            {showTimeSlotForm && selectedDate && (
                <div className="fixed inset-0 flex items-center justify-center overflow-y-auto modal z-999999">
                    <div
                        className="fixed inset-0 h-full w-full bg-gray-400/50 backdrop-blur-[2px]"
                        onClick={handleCancelTimeSlot}
                    />
                    <div className="relative w-full rounded-2xl bg-white shadow-theme-xl dark:bg-gray-900 max-w-md mx-auto p-4" onClick={(e) => e.stopPropagation()}>
                        {/* Close Button */}
                        <button
                            onClick={handleCancelTimeSlot}
                            className="absolute right-3 top-3 z-999 flex h-9.5 w-9.5 items-center justify-center rounded-full bg-gray-100 text-gray-400 transition-colors hover:bg-gray-200 hover:text-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white sm:right-6 sm:top-6 sm:h-11 sm:w-11"
                        >
                            <svg
                                width="24"
                                height="24"
                                viewBox="0 0 24 24"
                                fill="none"
                                xmlns="http://www.w3.org/2000/svg"
                            >
                                <path
                                    fillRule="evenodd"
                                    clipRule="evenodd"
                                    d="M6.04289 16.5413C5.65237 16.9318 5.65237 17.565 6.04289 17.9555C6.43342 18.346 7.06658 18.346 7.45711 17.9555L11.9987 13.4139L16.5408 17.956C16.9313 18.3466 17.5645 18.3466 17.955 17.956C18.3455 17.5655 18.3455 16.9323 17.955 16.5418L13.4129 11.9997L17.955 7.4576C18.3455 7.06707 18.3455 6.43391 17.955 6.04338C17.5645 5.65286 16.9313 5.65286 16.5408 6.04338L11.9987 10.5855L7.45711 6.0439C7.06658 5.65338 6.43342 5.65338 6.04289 6.0439C5.65237 6.43442 5.65237 7.06759 6.04289 7.45811L10.5845 11.9997L6.04289 16.5413Z"
                                    fill="currentColor"
                                />
                            </svg>
                        </button>

                        <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
                            Add Availability for {moment(selectedDate).format('MMMM D, YYYY')}
                        </h3>

                        <div className="space-y-4">
                            <div>
                                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                                    Start Time
                                </label>
                                <input
                                    type="time"
                                    value={newTimeSlot.startTime}
                                    onChange={(e) => setNewTimeSlot({ ...newTimeSlot, startTime: e.target.value })}
                                    className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
                                />
                            </div>

                            <div>
                                <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                                    End Time
                                </label>
                                <input
                                    type="time"
                                    value={newTimeSlot.endTime}
                                    onChange={(e) => setNewTimeSlot({ ...newTimeSlot, endTime: e.target.value })}
                                    className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-700 dark:text-white"
                                />
                            </div>

                        </div>

                        {/* Show existing time slots for this date */}
                        {getEventsForDate(selectedDate).length > 0 && (
                            <div className="mt-4">
                                <h4 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
                                    Existing time slots:
                                </h4>
                                <div className="space-y-1">
                                    {getEventsForDate(selectedDate).map(event => (
                                        <div key={event.id} className="text-sm text-gray-600 dark:text-gray-400">
                                            {moment(event.start).format('HH:mm')} - {moment(event.end).format('HH:mm')} ({event.title})
                                        </div>
                                    ))}
                                </div>
                            </div>
                        )}

                        <div className="flex justify-end space-x-3 mt-6">
                            <button
                                onClick={handleCancelTimeSlot}
                                className="px-4 py-2 text-gray-600 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 transition-colors"
                            >
                                Cancel
                            </button>
                            <button
                                onClick={handleAddTimeSlot}
                                className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
                            >
                                Add Time Slot
                            </button>
                        </div>
                    </div>
                </div>
            )}

            {/* Calendar */}
            <div className="h-[600px]">
                <Calendar
                    localizer={localizer}
                    events={events}
                    startAccessor="start"
                    endAccessor="end"
                    style={{ height: '100%' }}
                    view={currentView}
                    onView={setCurrentView}
                    date={currentDate}
                    onNavigate={setCurrentDate}
                    views={[Views.MONTH, Views.WEEK, Views.DAY]}
                    selectable
                    onSelectSlot={handleSelectSlot}
                    onSelectEvent={handleSelectEvent}
                    eventPropGetter={eventStyleGetter}
                    popup
                    showMultiDayTimes
                    step={30}
                    timeslots={2}
                    min={new Date(2024, 0, 1, 6, 0)} // 6:00 AM
                    max={new Date(2024, 0, 1, 22, 0)} // 10:00 PM
                />
            </div>

        </div>
    )
}

