import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import api from '../core/api';
import {
  clearAuthSession,
  getAuthAccountFeatures,
  getAuthLoginPortal,
  getAuthPermissions,
  getAuthPlatformFeatures,
  getAuthToken,
  getAuthUserName,
  getAuthUserRoles,
  initAuthFromStorage,
  persistLoginSession,
  saveSessionFromMe,
} from '../core/authSession';
import { getAuthSubscriptionRestricted } from '../core/authSession';
import { homeRouteWhenRestricted } from '../core/subscriptionAccess';
import { firstEnabledRoute, navItemsForRole, type NavItem } from '../core/roleAccess';

type AuthContextValue = {
  ready: boolean;
  isLoggedIn: boolean;
  userName: string;
  portal: string;
  permissions: string[];
  roles: string[];
  accountFeatures: Record<string, boolean>;
  platformFeatures: Record<string, boolean>;
  subscriptionRestricted: boolean;
  navItems: NavItem[];
  homeRoute: string;
  refreshSession: () => Promise<void>;
  login: (payload: Record<string, unknown>, portal: string) => Promise<string | null>;
  logout: () => Promise<void>;
};

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

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [ready, setReady] = useState(false);
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  const [userName, setUserName] = useState('User');
  const [portal, setPortal] = useState('');
  const [permissions, setPermissions] = useState<string[]>([]);
  const [roles, setRoles] = useState<string[]>([]);
  const [accountFeatures, setAccountFeatures] = useState<Record<string, boolean>>({});
  const [platformFeatures, setPlatformFeatures] = useState<Record<string, boolean>>({});
  const [subscriptionRestricted, setSubscriptionRestricted] = useState(false);

  const loadFromStorage = useCallback(async () => {
    await initAuthFromStorage();
    const token = getAuthToken();
    setIsLoggedIn(Boolean(token));
    setUserName(await getAuthUserName());
    setPortal(await getAuthLoginPortal());
    setPermissions(await getAuthPermissions());
    setRoles(await getAuthUserRoles());
    setAccountFeatures(await getAuthAccountFeatures());
    setPlatformFeatures(await getAuthPlatformFeatures());
    setSubscriptionRestricted(await getAuthSubscriptionRestricted());
  }, []);

  const refreshSession = useCallback(async () => {
    if (!getAuthToken()) return;
    try {
      const { data } = await api.get('/me');
      await saveSessionFromMe(data);
      await loadFromStorage();
    } catch {
      /* keep cached session */
    }
  }, [loadFromStorage]);

  useEffect(() => {
    (async () => {
      await loadFromStorage();
      if (getAuthToken()) await refreshSession();
      setReady(true);
    })();
  }, [loadFromStorage, refreshSession]);

  const login = useCallback(async (payload: Record<string, unknown>, fallbackPortal: string) => {
    const token = await persistLoginSession(payload, fallbackPortal);
    if (!token) return null;
    await loadFromStorage();
    await refreshSession();
    setIsLoggedIn(true);
    return token;
  }, [loadFromStorage, refreshSession]);

  const logout = useCallback(async () => {
    try {
      if (getAuthToken()) await api.post('/logout');
    } catch {
      /* ignore */
    }
    await clearAuthSession();
    setIsLoggedIn(false);
    setPortal('');
    setPermissions([]);
    setRoles([]);
  }, []);

  const navItems = useMemo(
    () => navItemsForRole(portal, permissions, roles, accountFeatures, platformFeatures),
    [portal, permissions, roles, accountFeatures, platformFeatures],
  );

  const homeRoute = useMemo(() => {
    if (subscriptionRestricted && !['superadmin', 'admin', 'support'].includes(portal)) {
      return homeRouteWhenRestricted(portal);
    }
    return firstEnabledRoute(accountFeatures, portal, permissions, false);
  }, [accountFeatures, portal, permissions, subscriptionRestricted]);

  const value = useMemo(
    () => ({
      ready,
      isLoggedIn,
      userName,
      portal,
      permissions,
      roles,
      accountFeatures,
      platformFeatures,
      subscriptionRestricted,
      navItems,
      homeRoute,
      refreshSession,
      login,
      logout,
    }),
    [
      ready,
      isLoggedIn,
      userName,
      portal,
      permissions,
      roles,
      accountFeatures,
      platformFeatures,
      subscriptionRestricted,
      navItems,
      homeRoute,
      refreshSession,
      login,
      logout,
    ],
  );

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

export function useAuth() {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within AuthProvider');
  return ctx;
}
