import { useCallback, useEffect, useMemo, useState } from 'react';
import { WizardStep } from './wizard-step';
import { DoctorsRightPane, type DoctorSummary } from './wizard-right-panes';
import {
    DoctorForm,
    doctorCoreToGraphQLInput,
    visitSlotInputsFromForm,
    emptyDoctorFormValues,
    type DoctorFormValues,
} from '@/components/forms/doctor-form';
import { apiClient } from '@/lib/api-client';
import { notify } from '@/lib/toast';
import type { WizardStepComponentProps } from './wizard-step-types';

// Doctor step — mirrors the clinics step but also fetches the clinic list
// for the DoctorForm's clinic dropdown. If there are no clinics yet we let
// the admin know they need to complete step 2 first (the wizard doesn't
// force ordering, but a doctor without a clinic is useless).

type ClinicLite = { id: string; clinicName: string | null };

export const WizardStepDoctors = (props: WizardStepComponentProps) => {
    const [values, setValues] = useState<DoctorFormValues>(emptyDoctorFormValues);
    const [clinics, setClinics] = useState<ClinicLite[]>([]);
    const [doctors, setDoctors] = useState<DoctorSummary[]>([]);
    const [loadingClinics, setLoadingClinics] = useState(true);
    const [saving, setSaving] = useState(false);

    const fetchData = useCallback(async () => {
        try {
            const data = await apiClient.graphql<{
                clinics: { edges: { node: ClinicLite }[] };
                doctors: { edges: { node: DoctorSummary }[] };
            }>(
                `{
                    clinics(first: 100) { edges { node { id clinicName } } }
                    doctors(first: 100, orderBy: { createdAt: DescNullsLast }) {
                        edges { node { id fullName { firstName lastName } department specialty } }
                    }
                }`,
                undefined,
                { silent: true },
            );
            setClinics(data.clinics.edges.map((e) => e.node));
            setDoctors(data.doctors.edges.map((e) => e.node));
        } catch (err) {
            console.error('[wizard/doctors] fetch failed', err);
            setClinics([]);
            setDoctors([]);
        } finally {
            setLoadingClinics(false);
        }
    }, []);

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

    const clinicOptions = useMemo(
        () => clinics.map((c) => ({ id: c.id, label: c.clinicName ?? 'Unnamed clinic' })),
        [clinics],
    );

    const handleSave = async () => {
        if (!values.firstName.trim() || !values.lastName.trim()) {
            notify.error('First and last name are required');
            return;
        }
        setSaving(true);
        try {
            // 1. Core doctor record
            const res = await apiClient.graphql<{ createDoctor: { id: string } }>(
                `mutation CreateDoctor($data: DoctorCreateInput!) {
                    createDoctor(data: $data) { id }
                }`,
                { data: doctorCoreToGraphQLInput(values) },
            );
            const doctorId = res.createDoctor.id;

            // 2. Visit slots (doctor can be at multiple clinics on
            // multiple days with different times each).
            const slotInputs = visitSlotInputsFromForm(values, doctorId);
            if (slotInputs.length > 0) {
                await Promise.all(
                    slotInputs.map((data) =>
                        apiClient.graphql(
                            `mutation CreateDoctorVisitSlot($data: DoctorVisitSlotCreateInput!) {
                                createDoctorVisitSlot(data: $data) { id }
                            }`,
                            { data },
                        ),
                    ),
                );
            }

            notify.success('Doctor added', `Dr. ${values.firstName} ${values.lastName}`);
            await fetchData();
            if (!props.isCompleted) {
                await props.onComplete('doctors');
            }
            setValues(emptyDoctorFormValues());
        } catch (err) {
            console.error('[wizard/doctors] save failed', err);
        } finally {
            setSaving(false);
        }
    };

    const pretendCompleted = props.isCompleted || doctors.length > 0;

    return (
        <WizardStep
            step="doctors"
            isCompleted={pretendCompleted}
            isLast={props.isLast}
            onPrev={props.onPrev}
            onNext={props.onNext}
            onMarkComplete={handleSave}
            onFinish={props.onFinish}
            saving={saving}
            rightPane={<DoctorsRightPane doctors={doctors} />}
        >
            {loadingClinics ? (
                <p className="text-sm text-tertiary">Loading clinics…</p>
            ) : clinics.length === 0 ? (
                <div className="rounded-lg border border-dashed border-warning bg-warning-primary p-4">
                    <p className="text-sm font-semibold text-warning-primary">Add a clinic first</p>
                    <p className="mt-1 text-xs text-tertiary">
                        You need at least one clinic before you can assign doctors. Go back to the{' '}
                        <b>Clinics</b> step and add a branch first.
                    </p>
                </div>
            ) : (
                <>
                    <DoctorForm value={values} onChange={setValues} clinics={clinicOptions} />
                    <div className="mt-6 flex justify-end">
                        <button
                            type="button"
                            disabled={saving}
                            onClick={handleSave}
                            className="inline-flex items-center gap-2 rounded-lg bg-brand-solid px-4 py-2 text-sm font-semibold text-primary_on-brand shadow-xs transition hover:bg-brand-solid_hover disabled:opacity-60"
                        >
                            {saving ? 'Adding…' : 'Add doctor'}
                        </button>
                    </div>
                </>
            )}
        </WizardStep>
    );
};
