import { createContext, useCallback, useContext, useEffect, useState } from 'react';

const SESSION_KEY = 'library_management_system_session';

interface SessionState {
  currentUser: { id: string; name: string; email: string; role: 'administrator' | 'librarian' | 'member' | 'guest'; memberId?: string; } | null;
  authToken: string | null;
  unreadNotificationCount: number;
  librarySettings: { loanPeriodDays: number; maxRenewals: number; maxLoans: number; maxReservations: number; dailyFineRate: number; maxFineCap: number; suspensionThreshold: number; holdPeriodDays: number; libraryName: string; } | null;
}

const DEFAULT_SESSION: SessionState = {
  currentUser: null,
  authToken: null,
  unreadNotificationCount: 0,
  librarySettings: null,
};

function readSession(): SessionState {
  try {
    const raw = sessionStorage.getItem(SESSION_KEY);
    if (!raw) return DEFAULT_SESSION;
    return { ...DEFAULT_SESSION, ...JSON.parse(raw) } as SessionState;
  } catch {
    return DEFAULT_SESSION;
  }
}

function writeSession(state: Partial<SessionState>): void {
  try {
    const prev = readSession();
    sessionStorage.setItem(SESSION_KEY, JSON.stringify({ ...prev, ...state }));
  } catch { /* quota exceeded or SSR */ }
}
function getOrCreateSessionId(): string {
  let id = sessionStorage.getItem('__sid__');
  if (!id) {
    id = crypto.randomUUID();
    sessionStorage.setItem('__sid__', id);
  }
  return id;
}

interface AppContextType {
  currentUser: { id: string; name: string; email: string; role: 'administrator' | 'librarian' | 'member' | 'guest'; memberId?: string; } | null;
  setCurrentUser: (value: { id: string; name: string; email: string; role: 'administrator' | 'librarian' | 'member' | 'guest'; memberId?: string; } | null) => void;
  authToken: string | null;
  setAuthToken: (value: string | null) => void;
  unreadNotificationCount: number;
  setUnreadNotificationCount: (value: number) => void;
  librarySettings: { loanPeriodDays: number; maxRenewals: number; maxLoans: number; maxReservations: number; dailyFineRate: number; maxFineCap: number; suspensionThreshold: number; holdPeriodDays: number; libraryName: string; } | null;
  setLibrarySettings: (value: { loanPeriodDays: number; maxRenewals: number; maxLoans: number; maxReservations: number; dailyFineRate: number; maxFineCap: number; suspensionThreshold: number; holdPeriodDays: number; libraryName: string; } | null) => void;
  sessionId: string;
  clearSession: () => void;
}

const AppContext = createContext<AppContextType | null>(null);

export function AppProvider({ children }: { children: React.ReactNode }) {
  const [sessionId] = useState<string>(getOrCreateSessionId);
  const [currentUser, setCurrentUserRaw] = useState<{ id: string; name: string; email: string; role: 'administrator' | 'librarian' | 'member' | 'guest'; memberId?: string; } | null>(() => readSession().currentUser);
  const [authToken, setAuthTokenRaw] = useState<string | null>(() => readSession().authToken);
  const [unreadNotificationCount, setUnreadNotificationCountRaw] = useState<number>(() => readSession().unreadNotificationCount);
  const [librarySettings, setLibrarySettingsRaw] = useState<{ loanPeriodDays: number; maxRenewals: number; maxLoans: number; maxReservations: number; dailyFineRate: number; maxFineCap: number; suspensionThreshold: number; holdPeriodDays: number; libraryName: string; } | null>(() => readSession().librarySettings);

  const setCurrentUser = useCallback((value: { id: string; name: string; email: string; role: 'administrator' | 'librarian' | 'member' | 'guest'; memberId?: string; } | null) => {
    setCurrentUserRaw(value);
  }, []);

  const setAuthToken = useCallback((value: string | null) => {
    setAuthTokenRaw(value);
  }, []);

  const setUnreadNotificationCount = useCallback((value: number) => {
    setUnreadNotificationCountRaw(value);
  }, []);

  const setLibrarySettings = useCallback((value: { loanPeriodDays: number; maxRenewals: number; maxLoans: number; maxReservations: number; dailyFineRate: number; maxFineCap: number; suspensionThreshold: number; holdPeriodDays: number; libraryName: string; } | null) => {
    setLibrarySettingsRaw(value);
  }, []);

  useEffect(() => {
    writeSession({ currentUser, authToken, unreadNotificationCount, librarySettings });
  }, [currentUser, authToken, unreadNotificationCount, librarySettings]);
  const clearSession = useCallback(() => {
    sessionStorage.removeItem(SESSION_KEY);
    sessionStorage.removeItem('__sid__');
    setCurrentUserRaw(null);
    setAuthTokenRaw(null);
    setUnreadNotificationCountRaw(0);
    setLibrarySettingsRaw(null);
  }, []);

  return (
    <AppContext.Provider value={{ currentUser, setCurrentUser, authToken, setAuthToken, unreadNotificationCount, setUnreadNotificationCount, librarySettings, setLibrarySettings, sessionId, clearSession }}>
      {children}
    </AppContext.Provider>
  );
}

export function useAppContext(): AppContextType {
  const ctx = useContext(AppContext);
  if (!ctx) throw new Error('useAppContext must be used within AppProvider');
  return ctx;
}
