import { createContext, useContext, useEffect, useState, useCallback } from 'react';
import type { FC, ReactNode } from 'react';
import { odooApi, type FrontendUser, type FrontendRole } from '../services/odoo';

const TOKEN_KEY = 'skeen_token';
const USER_KEY = 'skeen_user';

const ROLE_RANK: Record<FrontendRole, number> = {
  lectura: 10,
  medico: 50,
  recepcion: 50,
  admin: 100,
};

// Visibilidad del menú por ruta. Si una ruta no está listada, se muestra a todos los roles.
const MENU_ROLES: Record<string, FrontendRole[]> = {
  '/': ['admin', 'recepcion', 'medico', 'lectura'],
  '/agenda': ['admin', 'recepcion', 'medico'],
  '/pacientes': ['admin', 'recepcion', 'medico', 'lectura'],
  '/pos': ['admin', 'recepcion'],
  '/visitas': ['admin', 'recepcion', 'medico'],
  '/consultas': ['admin', 'recepcion', 'medico'],
  '/expedientes': ['admin', 'recepcion', 'medico'],
  '/medicos': ['admin', 'recepcion'],
  '/servicios': ['admin', 'recepcion', 'medico', 'lectura'],
  '/productos': ['admin', 'recepcion', 'lectura'], // deprecated: redirige a /inventario
  '/ventas': ['admin', 'recepcion'],
  '/pagos': ['admin', 'recepcion'],
  '/monedero': ['admin', 'recepcion', 'lectura'],
  '/inventario': ['admin', 'recepcion', 'lectura'],
  '/cortes': ['admin', 'recepcion'],
  '/reportes': ['admin', 'recepcion', 'lectura'],
  '/reportes?tab=adeudos': ['admin', 'recepcion', 'lectura'],
  '/reportes?tab=comisiones': ['admin', 'recepcion', 'lectura'],
  '/reportes?tab=horas-agenda': ['admin', 'recepcion', 'lectura'],
  '/reportes?tab=paquetes': ['admin', 'recepcion', 'lectura'],
  '/reportes?tab=vendedores': ['admin', 'recepcion', 'lectura'],
  '/reportes?tab=concentrado': ['admin', 'recepcion', 'lectura'],
  '/reportes?tab=recomendaciones': ['admin', 'recepcion', 'lectura'],
  '/reportes?tab=exportar': ['admin', 'recepcion', 'lectura'],
  '/configuracion': ['admin'],
  '/cumpleanos': ['admin', 'recepcion'],
  '/wacrm/messages': ['admin', 'recepcion'],
  '/wacrm/leads': ['admin', 'recepcion'],
};

interface AuthContextValue {
  user: FrontendUser | null;
  token: string | null;
  loading: boolean;
  login: (login: string, password: string) => Promise<FrontendUser>;
  logout: () => Promise<void>;
  hasRole: (min: FrontendRole) => boolean;
  canSee: (href: string) => boolean;
}

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

export const AuthProvider: FC<{ children: ReactNode }> = ({ children }) => {
  const [user, setUser] = useState<FrontendUser | null>(null);
  const [token, setToken] = useState<string | null>(() => localStorage.getItem(TOKEN_KEY));
  const [loading, setLoading] = useState(true);

  const clear = useCallback(() => {
    localStorage.removeItem(TOKEN_KEY);
    localStorage.removeItem(USER_KEY);
    setToken(null);
    setUser(null);
  }, []);

  // Validar token al arrancar
  useEffect(() => {
    let alive = true;
    const t = localStorage.getItem(TOKEN_KEY);
    if (!t) {
      setLoading(false);
      return;
    }
    // Hidratar usuario cacheado para evitar parpadeo
    const cached = localStorage.getItem(USER_KEY);
    if (cached) {
      try { setUser(JSON.parse(cached)); } catch { /* ignore */ }
    }
    odooApi.me()
      .then((res) => {
        if (!alive) return;
        if (res.status === 'success') {
          setUser(res.user);
          localStorage.setItem(USER_KEY, JSON.stringify(res.user));
        } else {
          clear();
        }
      })
      .catch(() => { if (alive) clear(); })
      .finally(() => { if (alive) setLoading(false); });
    return () => { alive = false; };
  }, [clear]);

  const login = async (login: string, password: string): Promise<FrontendUser> => {
    const res = await odooApi.login(login, password);
    if (res.status !== 'success' || !res.token) {
      throw new Error(res.message || 'Credenciales inválidas');
    }
    localStorage.setItem(TOKEN_KEY, res.token);
    localStorage.setItem(USER_KEY, JSON.stringify(res.user));
    setToken(res.token);
    setUser(res.user);
    return res.user;
  };

  const logout = async () => {
    try { await odooApi.logout(); } catch { /* ignore */ }
    clear();
  };

  const hasRole = (min: FrontendRole): boolean => {
    if (!user) return false;
    return (ROLE_RANK[user.role] ?? 0) >= (ROLE_RANK[min] ?? 0);
  };

  const canSee = (href: string): boolean => {
    if (!user) return false;
    // Permisos personalizados: lista no vacía manda sobre los defaults por rol
    if (user.allowed_menus && user.allowed_menus.length > 0) {
      return user.allowed_menus.includes(href);
    }
    const allowed = MENU_ROLES[href];
    if (!allowed) return true;
    return allowed.includes(user.role);
  };

  return (
    <AuthContext.Provider value={{ user, token, loading, login, logout, hasRole, canSee }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = (): AuthContextValue => {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth debe usarse dentro de AuthProvider');
  return ctx;
};

export const ROLE_LABELS: Record<FrontendRole, string> = {
  admin: 'Administrador',
  recepcion: 'Recepción',
  medico: 'Médico',
  lectura: 'Solo lectura',
};
