import { jsx as _jsx } from "react/jsx-runtime";
import React from 'react';
import { useLocalStorageState } from '../hooks/useLocalStorage';
import { browserStorageAdapter } from '../lib/storageAdapter';
import { useStorageAdapter } from './StorageAdapterContext';
const STORAGE_KEY = 'chat-sessions:index';
const createSessionId = () => `session-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
const createMetadata = (overrides) => {
    const now = Date.now();
    return {
        id: overrides?.id ?? createSessionId(),
        createdAt: overrides?.createdAt ?? now,
        updatedAt: overrides?.updatedAt ?? now,
        archivedAt: overrides?.archivedAt,
        title: overrides?.title,
        lastMessageAt: overrides?.lastMessageAt,
        lastMessagePreview: overrides?.lastMessagePreview,
        messageCount: overrides?.messageCount ?? 0
    };
};
const sortSessions = (activeId, sessions) => {
    if (sessions.length <= 1) {
        return sessions;
    }
    const active = sessions.find((session) => session.id === activeId);
    const rest = sessions.filter((session) => session.id !== activeId);
    rest.sort((a, b) => (b.updatedAt ?? 0) - (a.updatedAt ?? 0));
    return active ? [active, ...rest] : rest;
};
const ensureValidState = (state) => {
    if (!state || !Array.isArray(state.sessions)) {
        const metadata = createMetadata();
        return { activeSessionId: metadata.id, sessions: [metadata] };
    }
    const sessions = state.sessions.filter((session) => typeof session?.id === 'string');
    if (sessions.length === 0) {
        const metadata = createMetadata();
        return { activeSessionId: metadata.id, sessions: [metadata] };
    }
    const active = sessions.find((session) => session.id === state.activeSessionId);
    if (!active) {
        const [first] = sessions;
        const normalized = sortSessions(first.id, sessions);
        return { activeSessionId: first.id, sessions: normalized };
    }
    return {
        activeSessionId: active.id,
        sessions: sortSessions(active.id, sessions)
    };
};
const ChatSessionsContext = React.createContext(undefined);
const useMetadataHydrator = (setState) => {
    return React.useCallback((sessionId, updates) => {
        setState((prev) => {
            const current = ensureValidState(prev);
            const targetIndex = current.sessions.findIndex((session) => session.id === sessionId);
            if (targetIndex === -1) {
                return current;
            }
            const existing = current.sessions[targetIndex];
            const normalized = {
                ...existing,
                updatedAt: updates.updatedAt ?? Date.now()
            };
            if (updates.title !== undefined) {
                normalized.title = updates.title ?? undefined;
            }
            if (updates.messageCount !== undefined) {
                normalized.messageCount = updates.messageCount;
            }
            if (updates.lastMessageAt !== undefined) {
                normalized.lastMessageAt = updates.lastMessageAt ?? undefined;
            }
            if (updates.lastMessagePreview !== undefined) {
                normalized.lastMessagePreview = updates.lastMessagePreview ?? undefined;
            }
            if (updates.archivedAt !== undefined) {
                normalized.archivedAt = updates.archivedAt ?? undefined;
            }
            const nextSessions = [...current.sessions];
            nextSessions[targetIndex] = normalized;
            return {
                activeSessionId: current.activeSessionId,
                sessions: sortSessions(current.activeSessionId, nextSessions)
            };
        });
    }, [setState]);
};
export const ChatSessionsProvider = ({ children }) => {
    const storageAdapter = useStorageAdapter() ?? browserStorageAdapter;
    const initialState = React.useMemo(() => ensureValidState(undefined), []);
    const { value: persistedState, update } = useLocalStorageState(STORAGE_KEY, initialState, storageAdapter);
    const state = React.useMemo(() => ensureValidState(persistedState), [persistedState]);
    const setState = React.useCallback((updater) => {
        update((prev) => {
            const base = ensureValidState(prev);
            return ensureValidState(updater(base));
        });
    }, [update]);
    const updateMetadata = useMetadataHydrator(setState);
    const startNewSession = React.useCallback((options) => {
        const timestamp = Date.now();
        const initialMessages = options?.initialMessages ?? [];
        const lastMessage = initialMessages[initialMessages.length - 1];
        const lastMessageAt = lastMessage?.timestamp ?? (initialMessages.length > 0 ? timestamp : undefined);
        const metadata = createMetadata({
            id: createSessionId(),
            title: options?.title,
            createdAt: timestamp,
            updatedAt: timestamp,
            archivedAt: undefined,
            messageCount: initialMessages.length,
            lastMessageAt,
            lastMessagePreview: lastMessage?.content
        });
        setState((prev) => {
            const current = ensureValidState(prev);
            const sessions = current.sessions.map((session) => {
                if (session.id === current.activeSessionId) {
                    return {
                        ...session,
                        archivedAt: timestamp,
                        updatedAt: timestamp
                    };
                }
                return session;
            });
            const nextSessions = sortSessions(metadata.id, [metadata, ...sessions]);
            return {
                activeSessionId: metadata.id,
                sessions: nextSessions
            };
        });
        return metadata.id;
    }, [setState]);
    const resumeSession = React.useCallback((sessionId) => {
        setState((prev) => {
            const current = ensureValidState(prev);
            if (current.activeSessionId === sessionId) {
                return current;
            }
            const targetIndex = current.sessions.findIndex((session) => session.id === sessionId);
            if (targetIndex === -1) {
                return current;
            }
            const timestamp = Date.now();
            const sessions = current.sessions.map((session) => {
                if (session.id === sessionId) {
                    return {
                        ...session,
                        archivedAt: undefined,
                        updatedAt: timestamp
                    };
                }
                if (session.id === current.activeSessionId) {
                    return {
                        ...session,
                        archivedAt: timestamp,
                        updatedAt: timestamp
                    };
                }
                return session;
            });
            return {
                activeSessionId: sessionId,
                sessions: sortSessions(sessionId, sessions)
            };
        });
    }, [setState]);
    const deleteSession = React.useCallback((sessionId) => {
        setState((prev) => {
            const current = ensureValidState(prev);
            const remaining = current.sessions.filter((session) => session.id !== sessionId);
            if (remaining.length === 0) {
                const metadata = createMetadata();
                return {
                    activeSessionId: metadata.id,
                    sessions: [metadata]
                };
            }
            const timestamp = Date.now();
            const nextActiveId = current.activeSessionId === sessionId ? remaining[0].id : current.activeSessionId;
            const nextSessions = remaining.map((session) => {
                if (session.id === nextActiveId) {
                    return {
                        ...session,
                        archivedAt: undefined,
                        updatedAt: timestamp
                    };
                }
                return session;
            });
            return {
                activeSessionId: nextActiveId,
                sessions: sortSessions(nextActiveId, nextSessions)
            };
        });
        const keys = [
            `chat-session-${sessionId}`,
            `chat-session-${sessionId}-attachments`,
            `chat-session-${sessionId}-pending-run`
        ];
        for (const key of keys) {
            try {
                storageAdapter.removeItem(key);
            }
            catch (error) {
                console.error(`Failed to remove storage for session ${sessionId}`, error);
            }
        }
    }, [setState, storageAdapter]);
    const clearAllSessions = React.useCallback(() => {
        const sessionIds = state.sessions.map((session) => session.id);
        setState(() => ensureValidState(undefined));
        for (const sessionId of sessionIds) {
            const keys = [
                `chat-session-${sessionId}`,
                `chat-session-${sessionId}-attachments`,
                `chat-session-${sessionId}-pending-run`
            ];
            for (const key of keys) {
                try {
                    storageAdapter.removeItem(key);
                }
                catch (error) {
                    console.error(`Failed to remove storage for session ${sessionId}`, error);
                }
            }
        }
    }, [setState, state.sessions, storageAdapter]);
    const getSessionById = React.useCallback((sessionId) => {
        return state.sessions.find((session) => session.id === sessionId);
    }, [state.sessions]);
    const value = React.useMemo(() => {
        const previousSessions = state.sessions.filter((session) => session.id !== state.activeSessionId);
        return {
            activeSessionId: state.activeSessionId,
            sessions: state.sessions,
            previousSessions,
            getSessionById,
            startNewSession,
            resumeSession,
            deleteSession,
            updateSessionMetadata: updateMetadata,
            clearAllSessions
        };
    }, [state, getSessionById, startNewSession, resumeSession, deleteSession, updateMetadata, clearAllSessions]);
    return (_jsx(ChatSessionsContext.Provider, { value: value, children: children }));
};
export const useChatSessions = () => {
    const context = React.useContext(ChatSessionsContext);
    if (!context) {
        throw new Error('useChatSessions must be used within a ChatSessionsProvider');
    }
    return context;
};
