/**
 * User Profile Store - Platform-aware user profile management
 * Uses Firebase abstraction layer for cross-platform support
 */
import { create } from 'zustand';
import { doc } from '../firebase';
import type { UserProfile } from '../services/authServices';

export interface ProfileCacheEntry {
    profile: UserProfile | null;
    loading: boolean;
    error: string | null;
    lastFetched?: number;
}

interface UserProfileStoreState {
    profiles: Record<string, ProfileCacheEntry>;
    subscriptions: Record<string, () => void>;
    ensureSubscription: (uid: string) => void;
    refreshProfile: (uid: string) => Promise<UserProfile | null>;
    invalidateProfile: (uid: string) => Promise<UserProfile | null>;
    removeProfile: (uid: string) => void;
    clearAll: () => void;
}

const buildEntry = (
    existing: ProfileCacheEntry | undefined,
    overrides: Partial<ProfileCacheEntry>
): ProfileCacheEntry => ({
    profile: existing?.profile ?? null,
    loading: existing?.loading ?? false,
    error: existing?.error ?? null,
    lastFetched: existing?.lastFetched,
    ...overrides,
});

const snapshotExists = (docSnap: any): boolean => {
    const existsValue = docSnap?.exists;
    if (typeof existsValue === 'function') {
        try {
            return !!existsValue.call(docSnap);
        } catch {
            return false;
        }
    }
    return !!existsValue;
};

export const useUserProfileStore = create<UserProfileStoreState>((set, get) => ({
    profiles: {},
    subscriptions: {},

    ensureSubscription: (uid: string) => {
        if (!uid) {
            return;
        }

        // If already subscribed, don't create another subscription
        if (get().subscriptions[uid]) {
            return;
        }

        const existing = get().profiles[uid];
        if (existing?.loading) {
            return;
        }

        // If we have cached data, set up a real-time listener
        if (existing?.lastFetched) {
            const userDocRef = doc('users', uid);
            const unsubscribe = userDocRef.onSnapshot(
                (docSnap: any) => {
                    const profile = snapshotExists(docSnap) ? (docSnap.data() as UserProfile) : null;
                    set((state) => ({
                        profiles: {
                            ...state.profiles,
                            [uid]: buildEntry(state.profiles[uid], {
                                profile,
                                loading: false,
                                error: profile ? null : 'Profile not found',
                                lastFetched: Date.now(),
                            }),
                        },
                    }));
                },
                (error: any) => {
                    set((state) => ({
                        profiles: {
                            ...state.profiles,
                            [uid]: buildEntry(state.profiles[uid], {
                                loading: false,
                                error: error.message || 'Failed to fetch profile',
                            }),
                        },
                    }));
                }
            );

            set((state) => ({
                subscriptions: {
                    ...state.subscriptions,
                    [uid]: unsubscribe,
                },
            }));
            return;
        }

        // Initial fetch
        void get().refreshProfile(uid).catch((error) => {
            set((state) => ({
                profiles: {
                    ...state.profiles,
                    [uid]: buildEntry(state.profiles[uid], {
                        loading: false,
                        error: error instanceof Error ? error.message : 'Failed to fetch profile',
                    }),
                },
            }));
        });
    },

    refreshProfile: async (uid: string) => {
        if (!uid) {
            return null;
        }

        set((state) => ({
            profiles: {
                ...state.profiles,
                [uid]: buildEntry(state.profiles[uid], {
                    loading: true,
                    error: null,
                }),
            },
        }));

        try {
            const userDocRef = doc('users', uid);
            const docSnap = await userDocRef.get();
            const profile = snapshotExists(docSnap) ? (docSnap.data() as UserProfile) : null;

            set((state) => ({
                profiles: {
                    ...state.profiles,
                    [uid]: buildEntry(state.profiles[uid], {
                        profile,
                        loading: false,
                        error: profile ? null : 'Profile not found',
                        lastFetched: Date.now(),
                    }),
                },
            }));

            // Set up real-time listener after initial fetch if not already subscribed
            if (!get().subscriptions[uid] && profile) {
                const unsubscribe = userDocRef.onSnapshot(
                    (docSnap: any) => {
                        const updatedProfile = snapshotExists(docSnap) ? (docSnap.data() as UserProfile) : null;
                        set((state) => ({
                            profiles: {
                                ...state.profiles,
                                [uid]: buildEntry(state.profiles[uid], {
                                    profile: updatedProfile,
                                    loading: false,
                                    error: updatedProfile ? null : 'Profile not found',
                                    lastFetched: Date.now(),
                                }),
                            },
                        }));
                    },
                    (error: any) => {
                        set((state) => ({
                            profiles: {
                                ...state.profiles,
                                [uid]: buildEntry(state.profiles[uid], {
                                    loading: false,
                                    error: error.message || 'Failed to fetch profile',
                                }),
                            },
                        }));
                    }
                );

                set((state) => ({
                    subscriptions: {
                        ...state.subscriptions,
                        [uid]: unsubscribe,
                    },
                }));
            }

            return profile;
        } catch (error) {
            set((state) => ({
                profiles: {
                    ...state.profiles,
                    [uid]: buildEntry(state.profiles[uid], {
                        loading: false,
                        error: error instanceof Error ? error.message : 'Failed to fetch profile',
                    }),
                },
            }));
            throw error;
        }
    },

    invalidateProfile: async (uid: string) => {
        if (!uid) {
            return null;
        }

        set((state) => ({
            profiles: {
                ...state.profiles,
                [uid]: buildEntry(state.profiles[uid], {
                    loading: true,
                    error: null,
                    lastFetched: undefined,
                }),
            },
        }));

        return get().refreshProfile(uid);
    },

    removeProfile: (uid: string) => {
        // Unsubscribe from listener if exists
        const unsubscribe = get().subscriptions[uid];
        if (unsubscribe) {
            unsubscribe();
        }

        set((state) => {
            const { [uid]: _removedProfile, ...restProfiles } = state.profiles;
            const { [uid]: _removedSub, ...restSubs } = state.subscriptions;
            return {
                profiles: restProfiles,
                subscriptions: restSubs,
            };
        });
    },

    clearAll: () => {
        // Unsubscribe from all listeners
        const subscriptions = get().subscriptions;
        Object.values(subscriptions).forEach((unsubscribe) => {
            unsubscribe();
        });
        set({ profiles: {}, subscriptions: {} });
    },
}));

export const getUserProfileFromCache = (uid: string): UserProfile | null => {
    if (!uid) {
        return null;
    }
    return useUserProfileStore.getState().profiles[uid]?.profile ?? null;
};
