import React, { useState, useEffect } from "react";
import { Plus, Trash, User, Truck, MapPin } from "lucide-react";
import { useAuth } from "../contexts/AuthContext";
import { listEscalas, createEscala, deleteEscala, EscalaInput, getFunctions } from "../services/apiService";
import { useData } from "../contexts/DataContext";
import { UserRole } from "../types";

interface EventSchedulerProps {
    agendaId: string;
    dataEvento: string; // YYYY-MM-DD
    allowedProfessionals?: { professional_id?: string; professionalId?: string; status?: string }[] | string[]; // IDs or Objects
    onUpdateStats?: (stats: { studios: number }) => void;
    defaultTime?: string;
}

const timeSlots = [
    "07:00", "08:00", "09:00", "10:00", "11:00", "12:00",
    "13:00", "14:00", "15:00", "16:00", "17:00", "18:00",
    "19:00", "20:00", "21:00", "22:00", "23:00", "00:00"
];

const EventScheduler: React.FC<EventSchedulerProps> = ({ agendaId, dataEvento, allowedProfessionals, onUpdateStats, defaultTime }) => {
    const { token, user } = useAuth();
    const { professionals, events, functions } = useData();
    const [escalas, setEscalas] = useState<any[]>([]);
    const roles = functions;
    const [loading, setLoading] = useState(false);

    // New entry state
    const [selectedProf, setSelectedProf] = useState("");
    const [startTime, setStartTime] = useState(defaultTime || "08:00");
    const [endTime, setEndTime] = useState("12:00"); // Could calculated based on start, but keep simple
    const [role, setRole] = useState("");

    const isEditable = user?.role === UserRole.SUPERADMIN || user?.role === UserRole.BUSINESS_OWNER;
    const canViewSchedule = user?.role !== UserRole.EVENT_OWNER; // EVENT_OWNER can't see schedule details

    // Helper to check availability
    const checkAvailability = (profId: string) => {
        // Parse current request time in minutes
        const [h, m] = startTime.split(':').map(Number);
        const reqStart = h * 60 + m;
        const reqEnd = reqStart + 240; // +4 hours

        // Check if professional is in any other event on the same day with overlap
        const conflict = events.some(e => {
            if (e.id === agendaId) return false; // Ignore current event (allow re-scheduling or moving within same event?) 
            // Actually usually we don't want to double book in same event either unless intention is specific. 
            // But 'escalas' check (Line 115) already handles "already in this scale". 
            // If they are assigned to the *Event Team* (Logistics) but not Scale yet, it doesn't mean they are busy for THIS exact time?
            // Wait, 'events.photographerIds' means they are on the Team.
            // Being on the Team uses generic time?
            // For now, assume busy if in another event team.

            // Fix for Request 2: Only consider BUSY if status is 'Confirmado' in the other event?
            // The frontend 'events' list might generally show all events.
            // But 'events' from 'useData' implies basic info.
            // If we access specific assigned status here, we could filter.
            // The `events` array usually has basic info. If `assigned_professionals` is detailed there, we could check status.
            // Assuming `e.photographerIds` is just IDs.
            // We'll leave backend to strictly enforce, but frontend hint is good.

            // Check if professional is in any other event on the same day with overlap
            // FIX: Only consider BUSY if status is 'ACEITO' (Confirmed)
            const isAssignedConfirmed = (e.assignments || []).some(a => a.professionalId === profId && a.status === 'ACEITO');

            if (e.date === dataEvento && isAssignedConfirmed) {
                const [eh, em] = (e.time || "00:00").split(':').map(Number);
                const evtStart = eh * 60 + em;
                const evtEnd = evtStart + 240; // Assume 4h duration for other events too

                // Overlap check
                return (reqStart < evtEnd && evtStart < reqEnd);
            }
            return false;
        });
        return conflict;
    };

    useEffect(() => {
        if (agendaId && token) {
            fetchEscalas();
            // Functions handled via context
        }
    }, [agendaId, token]);

    // Recalculate stats whenever scales change
    useEffect(() => {
        if (onUpdateStats && escalas.length >= 0) {
            let totalStudios = 0;
            escalas.forEach(item => {
                const prof = professionals.find(p => p.id === item.profissional_id);
                if (prof && prof.qtd_estudio) {
                    totalStudios += prof.qtd_estudio;
                }
            });
            onUpdateStats({ studios: totalStudios });
        }
    }, [escalas, professionals, onUpdateStats]);

    const fetchEscalas = async () => {
        setLoading(true);
        const result = await listEscalas(agendaId, token!);
        if (result.data) {
            setEscalas(result.data);
        }
        setLoading(false);
    };

    const handleAddEscala = async () => {
        if (!selectedProf || !startTime) return;

        // Create Date objects from Local Time
        const localStart = new Date(`${dataEvento}T${startTime}:00`);
        const localEnd = new Date(localStart);
        localEnd.setHours(localEnd.getHours() + 4);

        // Convert to UTC ISO String and format for backend (Space, no ms)
        // toISOString returns YYYY-MM-DDTHH:mm:ss.sssZ
        const startISO = localStart.toISOString().replace('T', ' ').replace(/\.\d{3}Z$/, 'Z');
        const endISO = localEnd.toISOString().replace('T', ' ').replace(/\.\d{3}Z$/, 'Z');

        const input: EscalaInput = {
            agenda_id: agendaId,
            profissional_id: selectedProf,
            data_hora_inicio: startISO,
            data_hora_fim: endISO,
            funcao_especifica: role
        };

        const res = await createEscala(input, token!);
        if (res.data) {
            fetchEscalas();
            setSelectedProf("");
            setRole("");
        } else {
            alert("Erro ao criar escala: " + res.error);
        }
    };

    const handleDelete = async (id: string) => {
        if (confirm("Remover profissional da escala?")) {
            await deleteEscala(id, token!);
            fetchEscalas();
        }
    };

    // 1. Start with all professionals or just the allowed ones
    // FILTER: Only show professionals with a valid role (Function), matching "Equipe" page logic.
    let availableProfs = professionals.filter(p => roles.some(r => r.id === p.funcao_profissional_id));
    const allowedMap = new Map<string, string>(); // ID -> Status
    const assignedRoleMap = new Map<string, string>(); // ID -> Role Name

    if (allowedProfessionals) {
        // Normalize allowed list
        const ids: string[] = [];
        allowedProfessionals.forEach((p: any) => {
            if (typeof p === 'string') {
                ids.push(p);
                allowedMap.set(p, 'Confirmado'); // Default if not detailed
            } else {
                const pid = p.professional_id || p.professionalId;
                const status = p.status || 'Pendente';
                // Filter out Rejected professionals from the available list
                if (pid && status !== 'REJEITADO' && status !== 'Rejeitado') {
                    ids.push(pid);
                    allowedMap.set(pid, status);
                    
                    // Use assigned role ID (handle both casing)
                    const fId = p.funcaoId || p.funcao_id;
                    if (fId) {
                        const r = roles.find(role => role.id === fId);
                        if (r) assignedRoleMap.set(pid, r.nome);
                    }
                }
            }
        });
        availableProfs = availableProfs.filter(p => ids.includes(p.id));
    }

    // 2. Filter out professionals already in schedule to prevent duplicates
    // But keep the currently selected one valid if it was just selected
    availableProfs = availableProfs.filter(p => !escalas.some(e => e.profissional_id === p.id));

    const selectedProfessionalData = professionals.find(p => p.id === selectedProf);

    return (
        <div className="bg-white p-4 rounded-lg shadow space-y-4">
            <h3 className="text-lg font-semibold text-gray-800 flex items-center">
                <MapPin className="w-5 h-5 mr-2 text-indigo-500" />
                Escala de Profissionais
            </h3>

            {/* Warning if restricting and empty */}
            {isEditable && allowedProfessionals && allowedProfessionals.length === 0 && (
                <div className="bg-yellow-50 text-yellow-800 text-sm p-3 rounded border border-yellow-200">
                    Nenhum profissional atribuído a este evento. Adicione membros à equipe antes de criar a escala.
                </div>
            )}

            {/* Add Form - Only for Admins */}
            {isEditable && (
                <div className="bg-gray-50 p-3 rounded-md space-y-3">
                    <div className="flex flex-wrap gap-2 items-end">
                        <div className="flex-1 min-w-[200px]">
                            <label className="text-xs text-gray-500">Profissional</label>
                            <select
                                className="w-full p-2 rounded border bg-white"
                                value={selectedProf}
                                onChange={(e) => setSelectedProf(e.target.value)}
                            >
                                <option value="">Selecione...</option>
                                {availableProfs.map(p => {
                                    const isBusy = checkAvailability(p.id);
                                    const status = allowedMap.get(p.id);
                                    const isPending = status !== 'Confirmado' && status !== 'ACEITO';
                                    const isDisabled = isBusy || isPending;
                                    
                                    const assignedRole = assignedRoleMap.get(p.id);
                                    // Resolve role name from ID if not assigned specifically
                                    const defaultRole = roles.find(r => r.id === p.funcao_profissional_id)?.nome;
                                    const displayRole = assignedRole || defaultRole || (p as any).funcao_nome || p.role || "Profissional";

                                    let label = "";
                                    if (isPending) label = "(Pendente de Aceite)";
                                    else if (isBusy) label = "(Ocupado)";

                                    return (
                                        <option key={p.id} value={p.id} disabled={isDisabled} className={isDisabled ? "text-gray-400" : ""}>
                                            {p.nome} - {displayRole} {label}
                                        </option>
                                    );
                                })}
                            </select>
                        </div>
                        <div className="w-24">
                            <label className="text-xs text-gray-500">Início</label>
                            <input
                                type="time"
                                className="w-full p-2 rounded border bg-white"
                                value={startTime}
                                onChange={(e) => setStartTime(e.target.value)}
                            />
                        </div>

                        <div className="flex-1 min-w-[150px]">
                            <label className="text-xs text-gray-500">Função (Opcional)</label>
                            <input
                                type="text"
                                placeholder="Ex: Palco"
                                className="w-full p-2 rounded border bg-white"
                                value={role}
                                onChange={(e) => setRole(e.target.value)}
                            />
                        </div>
                        <button
                            onClick={handleAddEscala}
                            className="bg-green-600 hover:bg-green-700 text-white p-2 rounded flex items-center"
                        >
                            <Plus size={20} />
                        </button>
                    </div>

                    {/* Equipment Info Preview */}
                    {selectedProfessionalData && (selectedProfessionalData.equipamentos || selectedProfessionalData.qtd_estudio > 0) && (
                        <div className="text-xs text-gray-500 bg-white p-2 rounded border border-dashed border-gray-300">
                            <span className="font-semibold">Equipamentos:</span> {selectedProfessionalData.equipamentos || "Nenhum cadastrado"}
                            {selectedProfessionalData.qtd_estudio > 0 && (
                                <span className="ml-3 text-indigo-600 font-semibold">• Possui {selectedProfessionalData.qtd_estudio} Estúdio(s)</span>
                            )}
                        </div>
                    )}
                </div>
            )}

            {/* Timeline / List */}
            <div className="space-y-2">
                {loading ? <p>Carregando...</p> : escalas.length === 0 ? (
                    <p className="text-gray-500 text-sm italic">Nenhuma escala definida.</p>
                ) : (
                    escalas.map(item => {
                        // Find professional data again to show equipment in list if needed
                        // Ideally backend should return it, but for now we look up in global list if available
                        const profData = professionals.find(p => p.id === item.profissional_id);
                        const assignedRole = assignedRoleMap.get(item.profissional_id);
                        // Resolve role name
                        const defaultProfRole = profData ? roles.find(r => r.id === profData.funcao_profissional_id)?.nome : undefined;
                        const displayRole = assignedRole || item.profissional_role || defaultProfRole || (profData as any)?.funcao_nome || profData?.role;

                        return (
                            <div key={item.id} className="flex flex-col p-2 hover:bg-gray-50 rounded border-b">
                                <div className="flex items-center justify-between">
                                    <div className="flex items-center gap-3">
                                        <div className="w-10 h-10 rounded-full bg-gray-200 overflow-hidden flex-shrink-0">
                                            {item.avatar_url ? (
                                                <img src={item.avatar_url} alt="" className="w-full h-full object-cover" />
                                            ) : (
                                                <User className="w-6 h-6 m-2 text-gray-400" />
                                            )}
                                        </div>
                                        <div>
                                            <p className="font-medium text-gray-800">
                                                {item.profissional_nome}
                                                {displayRole && <span className="ml-1 text-xs text-gray-500 font-normal">({displayRole})</span>}
                                                {item.phone && <span className="ml-2 text-xs text-gray-500 font-normal">({item.phone})</span>}
                                            </p>
                                            <p className="text-xs text-gray-500">
                                                {new Date(item.start).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} -
                                                {new Date(item.end).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
                                                {item.role && <span className="ml-2 bg-blue-100 text-blue-800 px-1 rounded text-[10px]">{item.role}</span>}
                                            </p>
                                        </div>
                                    </div>
                                    {isEditable && (
                                        <button
                                            onClick={() => handleDelete(item.id)}
                                            className="text-red-500 hover:text-red-700 p-1"
                                        >
                                            <Trash size={16} />
                                        </button>
                                    )}
                                </div>
                                {/* Show equipment if available */}
                                {profData && profData.equipamentos && (
                                    <div className="ml-14 mt-1 text-[10px] text-gray-400">
                                        <span className="font-bold">Equip:</span> {profData.equipamentos}
                                    </div>
                                )}
                            </div>
                        );
                    })
                )}
            </div>
        </div>
    );
};

export default EventScheduler;
