'use client';

import { AsyncCombobox } from '@/components/ui/async-combobox';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import { api } from '@/lib/api';
import { useAuthStore } from '@/lib/auth-store';
import { API_BASE_URL } from '@/lib/constants';
import { useLanguage } from '@/lib/language-context';
import React, { useCallback, useEffect, useState } from 'react';
import { toast } from 'sonner';

interface SubResource {
    _id: string;
    userId: {
        _id: string;
        firstName: string;
        lastName: string;
        email?: string;
    };
    doctorId?: {
        _id?: string;
    } | string;
}

interface TeamDoctorOption {
    value: string;
    label: string;
}

interface TeamMember {
    doctorId?: string | null;
    firstName?: string;
    lastName?: string;
}

interface AppointmentFormProps {
    initialData?: {
        _id?: string;
        patientId?: { _id?: string } | string;
        doctorId?: { _id?: string } | string;
        appointmentDate?: string;
        notes?: string;
        status?: string;
    };
    onSuccess?: () => void;
    onCancel?: () => void;
}

export default function AppointmentForm({ initialData, onSuccess, onCancel }: AppointmentFormProps) {
    const { t } = useLanguage();
    const { token, user } = useAuthStore();
    const [loading, setLoading] = useState(false);

    // Convert a UTC ISO string to local datetime-local input value (YYYY-MM-DDTHH:MM)
    const utcToLocalInput = (utcStr: string) => {
        const date = new Date(utcStr);
        const y = date.getFullYear();
        const m = String(date.getMonth() + 1).padStart(2, '0');
        const d = String(date.getDate()).padStart(2, '0');
        const h = String(date.getHours()).padStart(2, '0');
        const min = String(date.getMinutes()).padStart(2, '0');
        return `${y}-${m}-${d}T${h}:${min}`;
    };

    // Get current local time as datetime-local value for min attribute
    const nowLocalInput = () => utcToLocalInput(new Date().toISOString());

    // Patient Search & Pagination State
    const [patients, setPatients] = useState<SubResource[]>([]);
    const [patientSearch, setPatientSearch] = useState('');
    const [patientPage, setPatientPage] = useState(1);
    const [patientHasMore, setPatientHasMore] = useState(true);
    const [patientLoading, setPatientLoading] = useState(false);
    const [teamDoctorOptions, setTeamDoctorOptions] = useState<TeamDoctorOption[]>([]);

    const [formData, setFormData] = useState({
        patientId: '',
        doctorId: '',
        appointmentDate: '',
        notes: '',
    });
    const isPrimaryDoctor = Boolean(user) && !user?.ownerId;

    const getResourceId = (resource?: { _id?: string } | string) => {
        if (!resource) return '';
        if (typeof resource === 'string') return resource;
        return resource._id || '';
    };

    useEffect(() => {
        if (initialData) {
            setFormData({
                patientId: getResourceId(initialData.patientId),
                doctorId: getResourceId(initialData.doctorId),
                appointmentDate: initialData.appointmentDate ? utcToLocalInput(initialData.appointmentDate) : '',
                notes: initialData.notes || '',
            });

            // If editing, patient list is fetched separately; keep selected ID in form state.
        } else {
            setFormData({
                patientId: '',
                doctorId: '',
                appointmentDate: '',
                notes: '',
            });
        }
    }, [initialData]);

    const fetchPatients = useCallback(async (page: number, search: string, append: boolean = false) => {
        setPatientLoading(true);
        try {
            const res = await api.patients.get({ page, limit: 20, search });
            if (res.success && Array.isArray(res.data)) {
                const validPatients = (res.data as SubResource[]).filter((p) => p.userId != null);

                if (append) {
                    setPatients(prev => {
                        const newPatients = validPatients.filter(vp => !prev.some(p => p._id === vp._id));
                        return [...prev, ...newPatients];
                    });
                } else {
                    setPatients(validPatients);
                }

                // Check if we have more results based on total count or limit
                const total = res.meta?.total || 0;
                const currentCount = (page - 1) * 20 + validPatients.length;
                setPatientHasMore(currentCount < total);
            }
        } catch (error) {
            console.error('Error fetching patients:', error);
        } finally {
            setPatientLoading(false);
        }
    }, []);

    const fetchTeamDoctors = useCallback(async () => {
        if (!token) return;
        try {
            const res = await api.team.get(token);
            if (!res.success || !Array.isArray(res.data)) return;

            const doctorOptions = (res.data as TeamMember[])
                .filter((member): member is TeamMember & { doctorId: string } => Boolean(member.doctorId))
                .map((member) => ({
                    value: String(member.doctorId),
                    label: `${member.firstName || ''} ${member.lastName || ''}`.trim() || t('appointments.unknownDoctor'),
                }))
                .filter((option, index, arr) => arr.findIndex((item) => item.value === option.value) === index);

            setTeamDoctorOptions(doctorOptions);
        } catch (error) {
            console.error('Error fetching team doctors:', error);
        }
    }, [token, t]);

    // Initial fetch for patients
    useEffect(() => {
        fetchPatients(1, '', false);
    }, [fetchPatients]);

    useEffect(() => {
        fetchTeamDoctors();
    }, [fetchTeamDoctors]);

    // Search effect
    useEffect(() => {
        // Reset pagination when search changes
        setPatientPage(1);
        fetchPatients(1, patientSearch, false);
    }, [patientSearch, fetchPatients]);

    const loadMorePatients = () => {
        if (!patientLoading && patientHasMore) {
            const nextPage = patientPage + 1;
            setPatientPage(nextPage);
            fetchPatients(nextPage, patientSearch, true);
        }
    };

    useEffect(() => {
        if (teamDoctorOptions.length === 1 && !formData.doctorId) {
            setFormData((prev) => ({
                ...prev,
                doctorId: teamDoctorOptions[0].value,
            }));
        }
    }, [teamDoctorOptions, formData.doctorId]);

    const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        setFormData({
            ...formData,
            [e.target.name]: e.target.value,
        });
    };

    const handleSelectChange = (name: string, value: string) => {
        if (name === 'patientId') {
            const selectedPatient = patients.find((patient) => patient._id === value);
            const selectedDoctorId = getResourceId(selectedPatient?.doctorId);

            setFormData({
                ...formData,
                patientId: value,
                doctorId: formData.doctorId || selectedDoctorId,
            });
            return;
        }

        setFormData({
            ...formData,
            [name]: value,
        });
    };

    const handleSubmit = async (e: React.SyntheticEvent<HTMLFormElement>) => {
        e.preventDefault();
        setLoading(true);

        try {
            const selectedPatient = patients.find((patient) => patient._id === formData.patientId);
            const resolvedDoctorId =
                formData.doctorId ||
                getResourceId(selectedPatient?.doctorId) ||
                getResourceId(initialData?.doctorId);

            if (!resolvedDoctorId || !formData.patientId) {
                toast.error(t('appointments.selectPatientAndDoctor'));
                setLoading(false);
                return;
            }

            if (!selectedPatient?.userId?.email?.trim()) {
                toast.error(t('appointments.patientEmailRequired'));
                setLoading(false);
                return;
            }

            const url = initialData?._id
                ? `${API_BASE_URL}/api/appointments/${initialData._id}`
                : `${API_BASE_URL}/api/appointments`;

            const method = initialData?._id ? 'PUT' : 'POST';

            // Convert local datetime-local value to UTC ISO string for the server
            const appointmentDateUTC = formData.appointmentDate
                ? new Date(formData.appointmentDate).toISOString()
                : '';

            const response = await fetch(url, {
                method,
                headers: {
                    'Content-Type': 'application/json',
                },
                body: JSON.stringify({
                    ...formData,
                    appointmentDate: appointmentDateUTC,
                    doctorId: resolvedDoctorId,
                    status: initialData?.status || 'Scheduled'
                }),
            });

            if (response.ok) {
                onSuccess?.();
            } else {
                const result = await response.json();
                if (result?.error === 'Patient email is required for appointment notifications') {
                    toast.error(t('appointments.patientEmailRequired'));
                } else {
                    toast.error(result?.error || t('appointments.saveFailed'));
                }
            }
        } catch (error) {
            console.error('Error creating appointment:', error);
            toast.error(t('common.unexpectedError'));
        } finally {
            setLoading(false);
        }
    };

    return (
        <div className="space-y-4">
            {/* Form content directly without redundant card header */}
            <form onSubmit={handleSubmit} className="space-y-6">
                <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <div className="flex flex-col gap-2">
                        <Label htmlFor="patientId">{t('appointments.patient')}</Label>
                        <AsyncCombobox
                            items={patients.map(p => ({
                                value: p._id,
                                label: `${p.userId?.firstName} ${p.userId?.lastName}`
                            }))}
                            value={formData.patientId}
                            onSelect={(value) => handleSelectChange('patientId', value)}
                            placeholder={t('appointments.selectPatient')}
                            searchPlaceholder={t('patients.searchPlaceholder')}
                            emptyMessage={t('common.noResults')}
                            className="w-full h-12"
                            isLoading={patientLoading}
                            hasMore={patientHasMore}
                            onLoadMore={loadMorePatients}
                            onSearch={setPatientSearch}
                        />
                    </div>

                {teamDoctorOptions.length > 1 && (
                    <div className="flex flex-col gap-2">
                        <Label htmlFor="doctorId">{t('appointments.doctor')}</Label>
                        <Select
                                value={formData.doctorId}
                                onValueChange={(value) => handleSelectChange('doctorId', value)}
                            >
                                <SelectTrigger id="doctorId" className="h-12">
                                    <SelectValue placeholder={t('appointments.selectDoctor')} />
                                </SelectTrigger>
                                <SelectContent>
                                    {teamDoctorOptions.map((doctor) => (
                                        <SelectItem key={doctor.value} value={doctor.value}>
                                            {doctor.label}
                                        </SelectItem>
                                    ))}
                                </SelectContent>
                            </Select>
                        </div>
                    )}
                </div>

                <div>
                    <Label htmlFor="appointmentDate">{t('appointments.dateTime')}</Label>
                    <Input
                        id="appointmentDate"
                        name="appointmentDate"
                        type="datetime-local"
                        value={formData.appointmentDate}
                        onChange={handleChange}
                        min={nowLocalInput()}
                        className="h-12"
                        required
                    />
                </div>

                <div>
                    <Label htmlFor="notes">{t('appointments.notes')}</Label>
                    <Textarea
                        id="notes"
                        name="notes"
                        value={formData.notes}
                        onChange={handleChange}
                        placeholder={t('appointments.notesPlaceholder')}
                    />
                </div>

                <div className="flex flex-col-reverse sm:flex-row sm:justify-end gap-2">
                    {onCancel && (
                        <Button type="button" variant="outline" onClick={onCancel} className="h-12 w-full sm:w-auto">
                            {t('common.cancel')}
                        </Button>
                    )}
                    <Button type="submit" disabled={loading} className="h-12 w-full sm:w-auto">
                        {loading ? t('common.saving') : (initialData ? t('appointments.updateAppointment') : t('appointments.bookAppointment'))}
                    </Button>
                </div>
            </form>
        </div>
    );
}
