"use client"

import { createContext, useContext, useState, useEffect, useCallback, ReactNode } from 'react';
import MessageBus from "@/lib/4nk/MessageBus";
import { iframeUrl } from "@/app/page";
import UserStore from "@/lib/4nk/UserStore";
import { FolderChatData, FolderData } from "@/lib/4nk/models/FolderData";

// Interface enrichie qui inclut maintenant les membres ET les fichiers
export interface EnrichedFolderData extends FolderData {
    processId: string,
}
// ---

type FourNKContextType = {
    isConnected: boolean;
    userPairingId: string | null;
    processes: any;
    myProcesses: string[];
    folderProcesses: any;
    myFolderProcesses: string[];
    folderPrivateData: Record<string, Record<string, any>>;
    folders: EnrichedFolderData[];
    loadingFolders: boolean;
    members: string[];

    setFolderProcesses: React.Dispatch<React.SetStateAction<any>>;
    setMyFolderProcesses: React.Dispatch<React.SetStateAction<string[]>>;
    setFolderPrivateData: React.Dispatch<React.SetStateAction<Record<string, Record<string, any>>>>;
    setMembers: React.Dispatch<React.SetStateAction<string[]>>;
};

const FourNKContext = createContext<FourNKContextType | undefined>(undefined);

export function FourNKProvider({ children }: { children: ReactNode }) {
    const [isConnected, setIsConnected] = useState(false);
    const [userPairingId, setUserPairingId] = useState<string | null>(null);
    const [processes, setProcesses] = useState<any>(null);
    const [members, setMembers] = useState<string[]>([]);;
    const [myProcesses, setMyProcesses] = useState<string[]>([]);
    const [folderProcesses, setFolderProcesses] = useState<any>(null);
    const [myFolderProcesses, setMyFolderProcesses] = useState<string[]>([]);
    const [folderPrivateData, setFolderPrivateData] = useState<Record<string, Record<string, any>>>({});
    const [loadingFolders, setLoadingFolders] = useState(true);
    const [folders, setFolders] = useState<EnrichedFolderData[]>([]);

    const fetchFolderPrivateData = useCallback(async (processId: string, stateId: string) => {
        try {
            const messageBus = MessageBus.getInstance(iframeUrl);
            await messageBus.isReady();
            const data = await messageBus.getData(processId, stateId);
            setFolderPrivateData(prev => ({ ...prev, [stateId]: data }));
            return data;
        } catch (err) {
            console.error('Error fetching folder private data:', err);
            return null;
        }
    }, []);

    const loadFoldersFrom4NK = useCallback(() => {
        if (!folderProcesses || !myFolderProcesses) {
            return;
        }

        const folderData: EnrichedFolderData[] = [];
        let hasAllPrivateData = true;
        let hasFoldersToLoad = false;
        const missingPrivateData: Array<{ processId: string, stateId: string }> = [];
        const EXCLUDED_STATE_ID = "0000000000000000000000000000000000000000000000000000000000000000";

        Object.entries(folderProcesses).forEach(([processId, process]: [string, any]) => {
            if (!myFolderProcesses.includes(processId)) return;
            const validStates = process.states.filter(
                (state: any) => state && state.state_id !== EXCLUDED_STATE_ID
            );
            if (validStates.length === 0) return;
            const referenceState = validStates.find(
                (state: any) => state.pcd_commitment?.folderNumber
            );
            const mainFolderNumber = referenceState?.pcd_commitment.folderNumber;
            if (!mainFolderNumber) {
                return;
            }

            let basePrivateData;
            let mergedMessages: FolderChatData[] = [];
            let mergedMessagesOwner: FolderChatData[] = [];

            validStates.forEach((state: any) => {
                hasFoldersToLoad = true;
                const stateToProcess = state;

                const privateData = folderPrivateData[stateToProcess.state_id];

                // Si on n'a pas les données pour cet état de référence...
                if (!privateData) {
                    hasAllPrivateData = false;
                    missingPrivateData.push({ processId, stateId: stateToProcess.state_id });
                    return; // On quitte ce process, on réessaiera au prochain rendu
                }
                // console.log("Données déchiffrées pour le state:", stateToProcess.state_id, privateData);

                if (privateData.messages_owner instanceof Map) {
                    const messageOwnerObj = Object.fromEntries(privateData.messages_owner);
                    mergedMessagesOwner.push(messageOwnerObj);
                }

                if (privateData.messages instanceof Map) {
                    const messageObj = Object.fromEntries(privateData.messages);
                    mergedMessages.push(messageObj);
                }

                if (privateData.folderNumber) {
                    basePrivateData = privateData;
                }
            });

            if (!basePrivateData) return;
            folderData.push({
                processId: processId,
                folderNumber: mainFolderNumber,
                name: basePrivateData.name || `Dossier ${mainFolderNumber}`,
                description: basePrivateData.description || '',
                created_at: basePrivateData.created_at || new Date().toISOString(),
                updated_at: basePrivateData.updated_at || new Date().toISOString(),
                notes: basePrivateData.notes || [],
                messages: mergedMessages || [],
                messages_owner: mergedMessagesOwner || [],
                attachedFiles: basePrivateData.attachedFiles || [],
            });
        });


        if (hasFoldersToLoad && !hasAllPrivateData) {
            setLoadingFolders(true);
            const firstMissing = missingPrivateData[0];
            if (firstMissing) {
                if (!folderPrivateData[firstMissing.stateId]) {
                    fetchFolderPrivateData(firstMissing.processId, firstMissing.stateId);
                }
            }
        } else {
            setFolders(folderData);
            setLoadingFolders(false);
        }
    }, [folderProcesses, myFolderProcesses, folderPrivateData, fetchFolderPrivateData, setFolders, setLoadingFolders]);

    const loadMembersFrom4NK = useCallback(() => {
        if (!processes || !userPairingId) return;

        const memberList: string[] = [];
        const EXCLUDED_STATE_ID = "0000000000000000000000000000000000000000000000000000000000000000";

        Object.entries(processes).forEach(([processId, process]: [string, any]) => {
            const validStates = process.states.filter(
                (state: any) => state && state.state_id !== EXCLUDED_STATE_ID
            );
            if (validStates.length === 0) return;

            const referenceState = validStates.find(
                (state: any) => state.pcd_commitment?.pairedAddresses
            );
            if (!referenceState) return;

            const userAddress = referenceState.commited_in

            memberList.push(userAddress);
        });

        // Filtrer la liste pour enlever l'ID de l'utilisateur connecté
        const filteredMemberList = memberList.filter(
            member => member !== userPairingId
        );

        // Sauvegarder la liste filtrée dans l'état
        setMembers(filteredMemberList);

    }, [processes, userPairingId]);

    // Chargement initial des données 4NK
    useEffect(() => {
        const userStore = UserStore.getInstance();
        const connected = userStore.isConnected();
        const pairingId = userStore.getUserPairingId();

        setIsConnected(connected);
        setUserPairingId(pairingId);

        const handleConnectionFlow = async () => {
            if (!connected) {
                setLoadingFolders(false);
                return;
            }
            setLoadingFolders(true);
            try {
                const messageBus = MessageBus.getInstance(iframeUrl);
                await messageBus.isReady();

                let pid = pairingId;
                if (!pid) {
                    pid = await messageBus.createUserPairing();
                    if (pid) {
                        userStore.pair(pid);
                        setUserPairingId(pid);
                    }
                }

                const procs = await messageBus.getProcesses();
                const myProcs = await messageBus.getMyProcesses();

                setProcesses(procs);
                setFolderProcesses(procs);
                setMyProcesses(myProcs);
                setMyFolderProcesses(myProcs);

            } catch (err) {
                console.error("❌ Error during global connection flow:", err);
                setLoadingFolders(false);
            }
        };

        handleConnectionFlow();
    }, [isConnected]);

    // Re-calculer les dossiers lorsque les données changent
    useEffect(() => {
        loadFoldersFrom4NK();
    }, [loadFoldersFrom4NK]);

    // Re-calculer les membres lorsque les données changent
    useEffect(() => {
        loadMembersFrom4NK();
    }, [loadMembersFrom4NK]);


    const value = {
        isConnected,
        userPairingId,
        processes,
        myProcesses,
        folderProcesses,
        myFolderProcesses,
        folderPrivateData,
        folders,
        loadingFolders,
        members,
        setFolderProcesses,
        setMyFolderProcesses,
        setFolderPrivateData,
        setMembers,
    };

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

export function use4NK() {
    const context = useContext(FourNKContext);
    if (context === undefined) {
        throw new Error('use4NK must be used within a FourNKProvider');
    }
    return context;
}