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

const SESSION_KEY = 'library_management_system_session';

interface SessionState {
  currentUser: { id: string; email: string; fullName: string; role: 'guest' | 'member' | 'librarian' | 'administrator'; memberId?: string; membershipNumber?: string; status?: string } | null;
  selectedBranchId: string | null;
  unreadNotificationCount: number;
  systemConfig: { loanPeriodDays: number; maxRenewals: number; maxConcurrentLoans: number; maxReservations: number; dailyFineRate: number; maxFinePerItem: number; fineThreshold: number; gracePeriodDays: number; pickupExpirationHours: number } | null;
}

const DEFAULT_SESSION: SessionState = {
  currentUser: null,
  selectedBranchId: null,
  unreadNotificationCount: 0,
  systemConfig: 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; email: string; fullName: string; role: 'guest' | 'member' | 'librarian' | 'administrator'; memberId?: string; membershipNumber?: string; status?: string } | null;
  setCurrentUser: (value: { id: string; email: string; fullName: string; role: 'guest' | 'member' | 'librarian' | 'administrator'; memberId?: string; membershipNumber?: string; status?: string } | null) => void;
  selectedBranchId: string | null;
  setSelectedBranchId: (value: string | null) => void;
  unreadNotificationCount: number;
  setUnreadNotificationCount: (value: number) => void;
  systemConfig: { loanPeriodDays: number; maxRenewals: number; maxConcurrentLoans: number; maxReservations: number; dailyFineRate: number; maxFinePerItem: number; fineThreshold: number; gracePeriodDays: number; pickupExpirationHours: number } | null;
  setSystemConfig: (value: { loanPeriodDays: number; maxRenewals: number; maxConcurrentLoans: number; maxReservations: number; dailyFineRate: number; maxFinePerItem: number; fineThreshold: number; gracePeriodDays: number; pickupExpirationHours: number } | 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; email: string; fullName: string; role: 'guest' | 'member' | 'librarian' | 'administrator'; memberId?: string; membershipNumber?: string; status?: string } | null>(() => readSession().currentUser);
  const [selectedBranchId, setSelectedBranchIdRaw] = useState<string | null>(() => readSession().selectedBranchId);
  const [unreadNotificationCount, setUnreadNotificationCountRaw] = useState<number>(() => readSession().unreadNotificationCount);
  const [systemConfig, setSystemConfigRaw] = useState<{ loanPeriodDays: number; maxRenewals: number; maxConcurrentLoans: number; maxReservations: number; dailyFineRate: number; maxFinePerItem: number; fineThreshold: number; gracePeriodDays: number; pickupExpirationHours: number } | null>(() => readSession().systemConfig);

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

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

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

  const setSystemConfig = useCallback((value: { loanPeriodDays: number; maxRenewals: number; maxConcurrentLoans: number; maxReservations: number; dailyFineRate: number; maxFinePerItem: number; fineThreshold: number; gracePeriodDays: number; pickupExpirationHours: number } | null) => {
    setSystemConfigRaw(value);
  }, []);

  useEffect(() => {
    writeSession({ currentUser, selectedBranchId, unreadNotificationCount, systemConfig });
  }, [currentUser, selectedBranchId, unreadNotificationCount, systemConfig]);
  const clearSession = useCallback(() => {
    sessionStorage.removeItem(SESSION_KEY);
    sessionStorage.removeItem('__sid__');
    setCurrentUserRaw(null);
    setSelectedBranchIdRaw(null);
    setUnreadNotificationCountRaw(0);
    setSystemConfigRaw(null);
  }, []);

  return (
    <AppContext.Provider value={{ currentUser, setCurrentUser, selectedBranchId, setSelectedBranchId, unreadNotificationCount, setUnreadNotificationCount, systemConfig, setSystemConfig, 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;
}
