import { TokenManager } from '@sentryagent/idp-sdk';

const SESSION_KEY = 'agentidp_credentials';

interface StoredCredentials {
  clientId: string;
  clientSecret: string;
  baseUrl: string;
}

/**
 * Persists user credentials to sessionStorage (cleared on tab close).
 */
export function saveCredentials(creds: StoredCredentials): void {
  sessionStorage.setItem(SESSION_KEY, JSON.stringify(creds));
}

/**
 * Retrieves credentials from sessionStorage.
 * Returns null if not logged in.
 */
export function loadCredentials(): StoredCredentials | null {
  const raw = sessionStorage.getItem(SESSION_KEY);
  if (!raw) return null;
  try {
    return JSON.parse(raw) as StoredCredentials;
  } catch {
    return null;
  }
}

/**
 * Removes credentials from sessionStorage (logout).
 */
export function clearCredentials(): void {
  sessionStorage.removeItem(SESSION_KEY);
}

/**
 * Returns true if the user has stored credentials.
 */
export function isAuthenticated(): boolean {
  return loadCredentials() !== null;
}

/**
 * Validates stored credentials by requesting a token.
 * Returns true if successful; false on auth failure.
 */
export async function validateCredentials(creds: StoredCredentials): Promise<boolean> {
  try {
    const tm = new TokenManager(creds.baseUrl, creds.clientId, creds.clientSecret, 'agents:read agents:write tokens:read audit:read');
    await tm.getToken();
    return true;
  } catch {
    return false;
  }
}

// ── React context ──────────────────────────────────────────────────────────────

import * as React from 'react';
import { useNavigate } from 'react-router-dom';

interface AuthContextValue {
  credentials: StoredCredentials | null;
  login: (creds: StoredCredentials) => Promise<boolean>;
  logout: () => void;
}

const AuthContext = React.createContext<AuthContextValue | null>(null);

/**
 * Provides authentication state to the application.
 * Reads initial state from sessionStorage on mount.
 */
export function AuthProvider({ children }: { children: React.ReactNode }): React.JSX.Element {
  const [credentials, setCredentials] = React.useState<StoredCredentials | null>(loadCredentials);
  const navigate = useNavigate();

  const login = React.useCallback(async (creds: StoredCredentials): Promise<boolean> => {
    const valid = await validateCredentials(creds);
    if (valid) {
      saveCredentials(creds);
      setCredentials(creds);
    }
    return valid;
  }, []);

  const logout = React.useCallback((): void => {
    clearCredentials();
    setCredentials(null);
    navigate('/dashboard/login');
  }, [navigate]);

  const value = React.useMemo(() => ({ credentials, login, logout }), [credentials, login, logout]);

  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}

/**
 * Returns the current authentication context.
 * Must be used inside <AuthProvider>.
 */
export function useAuth(): AuthContextValue {
  const ctx = React.useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within AuthProvider');
  return ctx;
}
