'use client';

import { createContext, useContext, useState, useEffect, useCallback, useRef, type ReactNode } from 'react';
import { api } from './api';

export interface SessionUser {
  id: string;
  email: string;
  name: string;
  role: string;
  tier: string;
  companyId: string | null;
  isOwner: boolean;
}

interface SessionContextValue {
  user: SessionUser | null;
  loading: boolean;
  refresh: () => Promise<void>;
}

const SessionContext = createContext<SessionContextValue>({
  user: null,
  loading: true,
  refresh: async () => {},
});

// Refresh 1 minute before the 10-minute access token expires
const PROACTIVE_REFRESH_MS = 9 * 60 * 1000;

export function SessionProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<SessionUser | null>(null);
  const [loading, setLoading] = useState(true);
  const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const lastFocusRefresh = useRef<number>(0);

  const scheduleProactiveRefresh = useCallback(() => {
    if (timerRef.current) clearTimeout(timerRef.current);
    timerRef.current = setTimeout(async () => {
      const ok = await fetch('/api/auth/refresh', { method: 'POST' }).then(r => r.ok).catch(() => false);
      if (ok) {
        scheduleProactiveRefresh();
      } else {
        setUser(null);
      }
    }, PROACTIVE_REFRESH_MS);
  }, []);

  const refresh = useCallback(async () => {
    try {
      const data = await api.getSession();
      if (data?.user) {
        setUser(data.user);
        scheduleProactiveRefresh();
      } else {
        setUser(null);
        if (timerRef.current) clearTimeout(timerRef.current);
      }
    } catch {
      setUser(null);
    } finally {
      setLoading(false);
    }
  }, [scheduleProactiveRefresh]);

  // Initial session check
  useEffect(() => {
    refresh();
    return () => { if (timerRef.current) clearTimeout(timerRef.current); };
  }, [refresh]);

  // Refresh on tab focus if more than 5 minutes since last refresh
  useEffect(() => {
    const onFocus = async () => {
      const now = Date.now();
      if (now - lastFocusRefresh.current < 5 * 60 * 1000) return;
      lastFocusRefresh.current = now;

      const ok = await fetch('/api/auth/refresh', { method: 'POST' }).then(r => r.ok).catch(() => false);
      if (ok) {
        scheduleProactiveRefresh();
      } else {
        // Access token expired and refresh token is gone — load session to confirm
        const data = await api.getSession();
        if (!data?.user) setUser(null);
      }
    };

    window.addEventListener('focus', onFocus);
    return () => window.removeEventListener('focus', onFocus);
  }, [scheduleProactiveRefresh]);

  // Listen for auth-expired events fired by fetchWithAuth in api.ts
  useEffect(() => {
    const onExpired = () => {
      if (timerRef.current) clearTimeout(timerRef.current);
      setUser(null);
    };
    window.addEventListener('scriba:auth-expired', onExpired);
    return () => window.removeEventListener('scriba:auth-expired', onExpired);
  }, []);

  return (
    <SessionContext.Provider value={{ user, loading, refresh }}>
      {children}
    </SessionContext.Provider>
  );
}

export function useSession() {
  return useContext(SessionContext);
}
