import { useCallback, useEffect, useState } from 'react';
import { WizardStep } from './wizard-step';
import { ClinicsRightPane, type ClinicSummary } from './wizard-right-panes';
import {
    ClinicForm,
    clinicCoreToGraphQLInput,
    holidayInputsFromForm,
    requiredDocInputsFromForm,
    emptyClinicFormValues,
    type ClinicFormValues,
} from '@/components/forms/clinic-form';
import { apiClient } from '@/lib/api-client';
import { notify } from '@/lib/toast';
import type { WizardStepComponentProps } from './wizard-step-types';

// Clinic step — presents a single-clinic form. On save the wizard runs
// a three-stage create chain:
//   1. createClinic (main record → get id)
//   2. createHoliday × N (one per holiday entry)
//   3. createClinicRequiredDocument × N (one per required doc type)
//
// This mirrors what the /settings/clinics list page does, minus the
// delete-old-first step (wizard is always creating, never updating).
// Failures inside the chain throw up through onComplete so the user
// sees the error loud, and the wizard stays on the current step.
export const WizardStepClinics = (props: WizardStepComponentProps) => {
    const [values, setValues] = useState<ClinicFormValues>(emptyClinicFormValues);
    const [saving, setSaving] = useState(false);
    const [clinics, setClinics] = useState<ClinicSummary[]>([]);

    const fetchClinics = useCallback(async () => {
        try {
            // Field names match what the platform actually exposes:
            //  - the SDK ADDRESS field is named "address" but the
            //    platform mounts it as `addressCustom` (composite type
            //    with addressCity / addressStreet / etc.)
            //  - the SDK SELECT field labelled "Status" lands as plain
            //    `status: ClinicStatusEnum`, NOT `clinicStatus`
            // Verified via __type introspection — keep this query
            // pinned to the actual schema to avoid silent empty fetches.
            type ClinicNode = {
                id: string;
                clinicName: string | null;
                addressCustom: { addressCity: string | null } | null;
                status: string | null;
            };
            const data = await apiClient.graphql<{
                clinics: { edges: { node: ClinicNode }[] };
            }>(
                `{ clinics(first: 100, orderBy: { createdAt: DescNullsLast }) {
                    edges { node {
                        id clinicName
                        addressCustom { addressCity }
                        status
                    } }
                } }`,
                undefined,
                { silent: true },
            );
            // Flatten into the shape ClinicsRightPane expects.
            setClinics(
                data.clinics.edges.map((e) => ({
                    id: e.node.id,
                    clinicName: e.node.clinicName,
                    addressCity: e.node.addressCustom?.addressCity ?? null,
                    clinicStatus: e.node.status,
                })),
            );
        } catch (err) {
            console.error('[wizard/clinics] fetch failed', err);
        }
    }, []);

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

    const handleSave = async () => {
        if (!values.clinicName.trim()) {
            notify.error('Clinic name is required');
            return;
        }
        setSaving(true);
        try {
            // 1. Core clinic record
            const res = await apiClient.graphql<{ createClinic: { id: string } }>(
                `mutation CreateClinic($data: ClinicCreateInput!) {
                    createClinic(data: $data) { id }
                }`,
                { data: clinicCoreToGraphQLInput(values) },
            );
            const clinicId = res.createClinic.id;

            // 2. Holidays
            if (values.holidays.length > 0) {
                const holidayInputs = holidayInputsFromForm(values, clinicId);
                await Promise.all(
                    holidayInputs.map((data) =>
                        apiClient.graphql(
                            `mutation CreateHoliday($data: HolidayCreateInput!) {
                                createHoliday(data: $data) { id }
                            }`,
                            { data },
                        ),
                    ),
                );
            }

            // 3. Required documents
            if (values.requiredDocumentTypes.length > 0) {
                const docInputs = requiredDocInputsFromForm(values, clinicId);
                await Promise.all(
                    docInputs.map((data) =>
                        apiClient.graphql(
                            `mutation CreateClinicRequiredDocument($data: ClinicRequiredDocumentCreateInput!) {
                                createClinicRequiredDocument(data: $data) { id }
                            }`,
                            { data },
                        ),
                    ),
                );
            }

            notify.success('Clinic added', values.clinicName);
            await fetchClinics();
            // Mark complete on first successful create. Don't auto-advance —
            // admins typically add multiple clinics in one sitting; the
            // Continue button on the wizard nav handles forward motion.
            if (!props.isCompleted) {
                await props.onComplete('clinics');
            }
            setValues(emptyClinicFormValues());
        } catch (err) {
            console.error('[wizard/clinics] save failed', err);
        } finally {
            setSaving(false);
        }
    };

    // Same trick as the Team step: once at least one clinic exists,
    // flip isCompleted=true so the WizardStep renders the "Continue"
    // button as the primary action — the form stays open below for
    // adding more clinics.
    const pretendCompleted = props.isCompleted || clinics.length > 0;

    return (
        <WizardStep
            step="clinics"
            isCompleted={pretendCompleted}
            isLast={props.isLast}
            onPrev={props.onPrev}
            onNext={props.onNext}
            onMarkComplete={handleSave}
            onFinish={props.onFinish}
            saving={saving}
            rightPane={<ClinicsRightPane clinics={clinics} />}
        >
            <ClinicForm value={values} onChange={setValues} />
            <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 clinic'}
                </button>
            </div>
        </WizardStep>
    );
};
