'use client';

import { createContext, useContext, useEffect, useState } from 'react';
import {
    AdCampaignsArraySchema,
    ArtistsListSchema,
    CurrentEventsArraySchema,
    EmailCampaignsArraySchema,
    PhysicalSalesArraySchema,
    ReleasesArraySchema,
    StreamsArraySchema,
} from '../types/schemas';
import artistsData from './artists.json';
import type {
    AdCampaign,
    Artist,
    ArtistMetadata,
    CurrentEvent,
    EmailCampaign,
    PhysicalSales,
    Release,
    StreamData,
} from '../types/schemas';

export interface DataContextValue {
    /** All available artists */
    allArtists: ArtistMetadata[];

    /** Current selected artist with their campaigns and streams */
    artist: Artist | null;

    /** All ad campaigns for the selected artist */
    adCampaigns: AdCampaign[];

    /** All email campaigns for the selected artist */
    emailCampaigns: EmailCampaign[];

    /** Streams data for all markets */
    streamsAllMarkets: StreamData[];

    /** Streams data for US market */
    streamsUs: StreamData[];

    /** Current events for the selected artist */
    currentEvents: CurrentEvent[];

    /** Releases for the selected artist */
    releases: Release[];

    /** Physical sales for the selected artist */
    physicalSales: PhysicalSales[];

    /** Set the selected artist by ID */
    setSelectedArtistId: (id: string) => void;

    /** Loading state */
    isLoading: boolean;

    /** Error state */
    error: string | null;
}

const DataContext = createContext<DataContextValue | null>(null);

export const DataProvider: React.FC<{
    children: React.ReactNode;
    defaultArtistId?: string; // Optional: specify which artist to load initially
}> = ({ children, defaultArtistId }) => {
    const [allArtists, setAllArtists] = useState<ArtistMetadata[]>([]);
    const [selectedArtistId, setSelectedArtistId] = useState<string | null>(
        null
    );
    const [artist, setArtist] = useState<Artist | null>(null);
    const [adCampaigns, setAdCampaigns] = useState<AdCampaign[]>([]);
    const [emailCampaigns, setEmailCampaigns] = useState<EmailCampaign[]>([]);
    const [streamsAllMarkets, setStreamsAllMarkets] = useState<StreamData[]>(
        []
    );
    const [streamsUs, setStreamsUs] = useState<StreamData[]>([]);
    const [currentEvents, setCurrentEvents] = useState<CurrentEvent[]>([]);
    const [releases, setReleases] = useState<Release[]>([]);
    const [physicalSales, setPhysicalSales] = useState<PhysicalSales[]>([]);
    const [isLoading, setIsLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    // Load all artists on mount
    useEffect(() => {
        try {
            // Parse and validate artists.json
            const artistsResult = ArtistsListSchema.safeParse(artistsData);

            if (!artistsResult.success) {
                console.error(
                    'Failed to parse artists data:',
                    artistsResult.error
                );
                throw new Error('Invalid artists data structure');
            }

            setAllArtists(artistsResult.data.artists);

            // Set initial selected artist
            const initialArtistId =
                defaultArtistId || artistsResult.data.artists[0]?.id;
            if (initialArtistId) {
                setSelectedArtistId(initialArtistId);
            }
        } catch (err) {
            const errorMessage =
                err instanceof Error
                    ? err.message
                    : 'Unknown error loading artists';
            console.error('Error loading artists data:', err);
            setError(errorMessage);
        }
    }, [defaultArtistId]);

    // Load artist data when selectedArtistId changes
    useEffect(() => {
        if (!selectedArtistId) {
            setIsLoading(false);
            return;
        }

        const loadArtistData = async () => {
            try {
                setIsLoading(true);
                setError(null);

                const artistMetadata = allArtists.find(
                    a => a.id === selectedArtistId
                );

                if (!artistMetadata) {
                    throw new Error(`Artist not found: ${selectedArtistId}`);
                }

                let loadedAdCampaigns: AdCampaign[] = [];
                let loadedEmailCampaigns: EmailCampaign[] = [];
                let loadedStreamsAllMarkets: StreamData[] = [];
                let loadedStreamsUs: StreamData[] = [];
                let loadedCurrentEvents: CurrentEvent[] = [];
                let loadedReleases: Release[] = [];
                let loadedPhysicalSales: PhysicalSales[] = [];

                // Load ad campaigns if available
                if (artistMetadata.adCampaigns) {
                    try {
                        const campaignsModule = await import(
                            `./${artistMetadata.adCampaigns}`
                        );
                        const campaignsData = campaignsModule.default;
                        const campaignsResult =
                            AdCampaignsArraySchema.safeParse(campaignsData);

                        if (campaignsResult.success) {
                            loadedAdCampaigns = campaignsResult.data;
                        } else {
                            console.error(
                                'Failed to parse ad campaigns data:',
                                campaignsResult.error
                            );
                        }
                    } catch (err) {
                        console.warn(
                            'No ad campaigns data available for artist:',
                            err
                        );
                    }
                }

                // Load email campaigns if available
                if (artistMetadata.emailCampaigns) {
                    try {
                        const emailCampaignsModule = await import(
                            `./${artistMetadata.emailCampaigns}`
                        );
                        const emailCampaignsData = emailCampaignsModule.default;
                        const emailCampaignsResult =
                            EmailCampaignsArraySchema.safeParse(
                                emailCampaignsData
                            );

                        if (emailCampaignsResult.success) {
                            loadedEmailCampaigns = emailCampaignsResult.data;
                        } else {
                            console.error(
                                'Failed to parse email campaigns data:',
                                emailCampaignsResult.error
                            );
                        }
                    } catch (err) {
                        console.warn(
                            'No email campaigns data available for artist:',
                            err
                        );
                    }
                }

                // Load streams (all markets) if available
                if (artistMetadata.streamsAllMarkets) {
                    try {
                        const streamsModule = await import(
                            `./${artistMetadata.streamsAllMarkets}`
                        );
                        const streamsData = streamsModule.default;
                        const streamsResult =
                            StreamsArraySchema.safeParse(streamsData);

                        if (streamsResult.success) {
                            loadedStreamsAllMarkets = streamsResult.data;
                        } else {
                            console.error(
                                'Failed to parse streams (all markets) data:',
                                streamsResult.error
                            );
                        }
                    } catch (err) {
                        console.warn(
                            'No streams (all markets) data available for artist:',
                            err
                        );
                    }
                }

                // Load streams (US) if available
                if (artistMetadata.streamsUs) {
                    try {
                        const streamsModule = await import(
                            `./${artistMetadata.streamsUs}`
                        );
                        const streamsData = streamsModule.default;
                        const streamsResult =
                            StreamsArraySchema.safeParse(streamsData);

                        if (streamsResult.success) {
                            loadedStreamsUs = streamsResult.data;
                        } else {
                            console.error(
                                'Failed to parse streams (US) data:',
                                streamsResult.error
                            );
                        }
                    } catch (err) {
                        console.warn(
                            'No streams (US) data available for artist:',
                            err
                        );
                    }
                }

                // Load current events if available
                if (artistMetadata.currentEvents) {
                    try {
                        const currentEventsModule = await import(
                            `./${artistMetadata.currentEvents}`
                        );
                        const currentEventsData = currentEventsModule.default;
                        const currentEventsResult =
                            CurrentEventsArraySchema.safeParse(
                                currentEventsData
                            );

                        if (currentEventsResult.success) {
                            loadedCurrentEvents = currentEventsResult.data;
                        } else {
                            console.error(
                                'Failed to parse current events data:',
                                currentEventsResult.error
                            );
                        }
                    } catch (err) {
                        console.warn(
                            'No current events data available for artist:',
                            err
                        );
                    }
                }

                // Load releases if available
                if (artistMetadata.releases) {
                    try {
                        const releasesModule = await import(
                            `./${artistMetadata.releases}`
                        );
                        const releasesData = releasesModule.default;
                        const releasesResult =
                            ReleasesArraySchema.safeParse(releasesData);

                        if (releasesResult.success) {
                            loadedReleases = releasesResult.data;
                        } else {
                            console.error(
                                'Failed to parse releases data:',
                                releasesResult.error
                            );
                        }
                    } catch (err) {
                        console.warn(
                            'No releases data available for artist:',
                            err
                        );
                    }
                }

                // Load physical sales if available
                if (artistMetadata.physicalSales) {
                    try {
                        const physicalSalesModule = await import(
                            `./${artistMetadata.physicalSales}`
                        );
                        const physicalSalesData = physicalSalesModule.default;
                        const physicalSalesResult =
                            PhysicalSalesArraySchema.safeParse(
                                physicalSalesData
                            );

                        if (physicalSalesResult.success) {
                            loadedPhysicalSales = physicalSalesResult.data;
                        } else {
                            console.error(
                                'Failed to parse physical sales data:',
                                physicalSalesResult.error
                            );
                        }
                    } catch (err) {
                        console.warn(
                            'No physical sales data available for artist:',
                            err
                        );
                    }
                }

                // Create artist object with loaded data
                const loadedArtist: Artist = {
                    id: artistMetadata.id,
                    name: artistMetadata.name,
                    adCampaigns: loadedAdCampaigns,
                    emailCampaigns: loadedEmailCampaigns,
                    streamsAllMarkets: loadedStreamsAllMarkets,
                    streamsUs: loadedStreamsUs,
                    currentEvents: loadedCurrentEvents,
                    releases: loadedReleases,
                    physicalSales: loadedPhysicalSales,
                };

                setArtist(loadedArtist);
                setAdCampaigns(loadedAdCampaigns);
                setEmailCampaigns(loadedEmailCampaigns);
                setStreamsAllMarkets(loadedStreamsAllMarkets);
                setStreamsUs(loadedStreamsUs);
                setCurrentEvents(loadedCurrentEvents);
                setReleases(loadedReleases);
                setPhysicalSales(loadedPhysicalSales);
            } catch (err) {
                const errorMessage =
                    err instanceof Error
                        ? err.message
                        : 'Unknown error loading data';
                console.error('Error loading artist data:', err);
                setError(errorMessage);
            } finally {
                setIsLoading(false);
            }
        };

        loadArtistData();
    }, [selectedArtistId, allArtists]);

    const value: DataContextValue = {
        allArtists,
        artist,
        adCampaigns,
        emailCampaigns,
        streamsAllMarkets,
        streamsUs,
        currentEvents,
        releases,
        physicalSales,
        setSelectedArtistId,
        isLoading,
        error,
    };

    return (
        <DataContext.Provider value={value}>{children}</DataContext.Provider>
    );
};

export const useData = (): DataContextValue => {
    const context = useContext(DataContext);
    if (!context) {
        throw new Error('useData must be used within a DataProvider');
    }
    return context;
};
