'use client';

import type {Context, Dispatch, JSX, ReactNode, SetStateAction} from 'react';
import React, {createContext, useCallback, useState} from 'react';
import AlertStack from '@/components/ui/AlertStack';

export type AlertType = 'success' | 'error' | 'info' | 'warning';

export interface Alert {
    id: string;
    type: AlertType;
    message: string;
}

export interface AlertContextProps {
    successMessage: (message: string) => void;
    errorMessage: (message: string) => void;
    infoMessage: (message: string) => void;
    warningMessage: (message: string) => void;
}

interface AlertProviderProps {
    children: ReactNode;
}

export const AlertContext: Context<AlertContextProps> = createContext<AlertContextProps>({
    successMessage: (_message: string): void => {
    },
    errorMessage: (_message: string): void => {
    },
    infoMessage: (_message: string): void => {
    },
    warningMessage: (_message: string): void => {
    },
});

export function AlertProvider({children}: AlertProviderProps): JSX.Element {
    const [alerts, setAlerts]: [Alert[], Dispatch<SetStateAction<Alert[]>>] = useState<Alert[]>([]);
    
    const addAlert: (type: AlertType, message: string) => void = useCallback((type: AlertType, message: unknown): void => {
        const safeMessage: string = typeof message === 'string' ? message : String(message ?? 'Une erreur est survenue');
        const id: string = `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
        const newAlert: Alert = {id, type, message: safeMessage};

        setAlerts((prev: Alert[]): Alert[] => [...prev, newAlert]);
    }, []);
    
    const removeAlert: (id: string) => void = useCallback((id: string): void => {
        setAlerts((prev: Alert[]): Alert[] => prev.filter((alert: Alert): boolean => alert.id !== id));
    }, []);
    
    const successMessage: (message: string) => void = useCallback((message: string): void => {
        addAlert('success', message);
    }, [addAlert]);
    
    const errorMessage: (message: string) => void = useCallback((message: string): void => {
        addAlert('error', message);
    }, [addAlert]);
    
    const infoMessage: (message: string) => void = useCallback((message: string): void => {
        addAlert('info', message);
    }, [addAlert]);
    
    const warningMessage: (message: string) => void = useCallback((message: string): void => {
        addAlert('warning', message);
    }, [addAlert]);
    
    return (
        <AlertContext.Provider
            value={{
                successMessage,
                errorMessage,
                infoMessage,
                warningMessage,
            }}
        >
            {children}
            <AlertStack alerts={alerts} onClose={removeAlert}/>
        </AlertContext.Provider>
    );
}
