import type { ReactNode } from 'react';
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { apiClient } from '@/lib/api-client';
import {
    LEADS_QUERY,
    CAMPAIGNS_QUERY,
    ADS_QUERY,
    FOLLOW_UPS_QUERY,
    LEAD_ACTIVITIES_QUERY,
    CALLS_QUERY,
    APPOINTMENTS_QUERY,
    PATIENTS_QUERY,
} from '@/lib/queries';
import {
    transformLeads,
    transformCampaigns,
    transformAds,
    transformFollowUps,
    transformLeadActivities,
    transformCalls,
    transformAppointments,
    transformPatients,
} from '@/lib/transforms';

import type { Lead, Campaign, Ad, LeadActivity, FollowUp, WhatsAppTemplate, Agent, Call, LeadIngestionSource, Patient, Appointment } from '@/types/entities';

type DataContextType = {
    leads: Lead[];
    campaigns: Campaign[];
    ads: Ad[];
    followUps: FollowUp[];
    leadActivities: LeadActivity[];
    templates: WhatsAppTemplate[];
    agents: Agent[];
    calls: Call[];
    appointments: Appointment[];
    patients: Patient[];
    ingestionSources: LeadIngestionSource[];
    loading: boolean;
    error: string | null;
    updateLead: (id: string, updates: Partial<Lead>) => void;
    addCall: (call: Call) => void;
    refresh: () => void;
};

const DataContext = createContext<DataContextType | undefined>(undefined);

export const useData = (): DataContextType => {
    const context = useContext(DataContext);

    if (context === undefined) {
        throw new Error('useData must be used within a DataProvider');
    }

    return context;
};

interface DataProviderProps {
    children: ReactNode;
}

export const DataProvider = ({ children }: DataProviderProps) => {
    const [leads, setLeads] = useState<Lead[]>([]);
    const [campaigns, setCampaigns] = useState<Campaign[]>([]);
    const [ads, setAds] = useState<Ad[]>([]);
    const [followUps, setFollowUps] = useState<FollowUp[]>([]);
    const [leadActivities, setLeadActivities] = useState<LeadActivity[]>([]);
    const [calls, setCalls] = useState<Call[]>([]);
    const [appointments, setAppointments] = useState<Appointment[]>([]);
    const [patients, setPatients] = useState<Patient[]>([]);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    // These don't have platform entities yet — empty for now
    const [templates] = useState<WhatsAppTemplate[]>([]);
    const [agents] = useState<Agent[]>([]);
    const [ingestionSources] = useState<LeadIngestionSource[]>([]);

    const fetchData = useCallback(async () => {
        if (!apiClient.isAuthenticated()) {
            setLoading(false);
            return;
        }

        setLoading(true);
        setError(null);

        try {
            const gql = <T,>(query: string) => apiClient.graphql<T>(query, undefined, { silent: true }).catch(() => null);

            const [leadsData, campaignsData, adsData, followUpsData, activitiesData, callsData, appointmentsData, patientsData] = await Promise.all([
                gql<any>(LEADS_QUERY),
                gql<any>(CAMPAIGNS_QUERY),
                gql<any>(ADS_QUERY),
                gql<any>(FOLLOW_UPS_QUERY),
                gql<any>(LEAD_ACTIVITIES_QUERY),
                gql<any>(CALLS_QUERY),
                gql<any>(APPOINTMENTS_QUERY),
                gql<any>(PATIENTS_QUERY),
            ]);

            if (leadsData) setLeads(transformLeads(leadsData));
            if (campaignsData) setCampaigns(transformCampaigns(campaignsData));
            if (adsData) setAds(transformAds(adsData));
            if (followUpsData) setFollowUps(transformFollowUps(followUpsData));
            if (activitiesData) setLeadActivities(transformLeadActivities(activitiesData));
            if (callsData) setCalls(transformCalls(callsData));
            if (appointmentsData) setAppointments(transformAppointments(appointmentsData));
            if (patientsData) setPatients(transformPatients(patientsData));
        } catch (err: any) {
            setError(err.message ?? 'Failed to load data');
        } finally {
            setLoading(false);
        }
    }, []);

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

    const updateLead = (id: string, updates: Partial<Lead>) => {
        setLeads((prev) => prev.map((lead) => (lead.id === id ? { ...lead, ...updates } : lead)));
    };

    const addCall = (call: Call) => {
        setCalls((prev) => [call, ...prev]);
    };

    return (
        <DataContext.Provider value={{
            leads, campaigns, ads, followUps, leadActivities, templates, agents, calls, appointments, patients, ingestionSources,
            loading, error,
            updateLead, addCall, refresh: fetchData,
        }}>
            {children}
        </DataContext.Provider>
    );
};
