/**
 * Lean auth state for the app shells (login + session bootstrap + RBAC helpers).
 *
 * Talks to the same backend contract as fe0: POST /api/v1/auth/login → { accessToken, user },
 * GET /api/v1/auth/me, token in localStorage. The heavier fe0 `auth-service` (staff-profile
 * machinery) migrates here with the profile pages in a later chunk.
 */
import { createContext, useContext, useEffect, useState, type ReactNode } from 'react';

import { apiClient } from '../api/client';
import { clearAccessToken, getAccessToken, setAccessToken } from '../utils/token';
import { type Permission, type Role, hasPermission as roleHasPermission } from '../lib/permissions';

export interface AuthUser {
  id: string;
  email: string;
  name: string;
  roles: string[];
  phone?: string | null;
  emailVerified?: boolean;
}

interface LoginResponse {
  accessToken: string;
  user: AuthUser;
}

export interface AuthContextValue {
  user: AuthUser | null;
  roles: Role[];
  isAuthenticated: boolean;
  loading: boolean;
  login: (email: string, password: string) => Promise<AuthUser>;
  logout: () => void;
  hasPermission: (permission: Permission) => boolean;
  hasRole: (role: Role) => boolean;
}

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

const KNOWN_ROLES: ReadonlySet<string> = new Set(['admin', 'editor', 'viewer']);

function rolesOf(user: AuthUser | null): Role[] {
  return ((user?.roles ?? []) as string[]).filter((r): r is Role => KNOWN_ROLES.has(r));
}

export function AuthProvider({ children }: { children: ReactNode }) {
  const [user, setUser] = useState<AuthUser | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    let active = true;
    (async () => {
      if (!getAccessToken()) {
        setLoading(false);
        return;
      }
      try {
        const me = await apiClient.get<AuthUser>('/api/v1/auth/me');
        if (active) setUser(me);
      } catch {
        clearAccessToken();
      } finally {
        if (active) setLoading(false);
      }
    })();
    return () => {
      active = false;
    };
  }, []);

  const login = async (email: string, password: string): Promise<AuthUser> => {
    const res = await apiClient.post<LoginResponse>('/api/v1/auth/login', { email, password });
    setAccessToken(res.accessToken);
    setUser(res.user);
    return res.user;
  };

  const logout = (): void => {
    clearAccessToken();
    setUser(null);
  };

  const roles = rolesOf(user);
  const value: AuthContextValue = {
    user,
    roles,
    isAuthenticated: user !== null,
    loading,
    login,
    logout,
    hasPermission: (permission) => roleHasPermission(roles, permission),
    hasRole: (role) => roles.includes(role),
  };

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

export function useAuth(): AuthContextValue {
  const ctx = useContext(AuthContext);
  if (ctx === null) {
    throw new Error('useAuth must be used within an <AuthProvider>');
  }
  return ctx;
}
