import { Request, Response, NextFunction } from 'express';
import { createRemoteJWKSet, jwtVerify } from 'jose';
import { supabase, findOneGpi } from '../config/supabase.js';
import { IAppUser } from './authMiddleware.js';

const LOGTO_URL = process.env.LOGTO_URL || 'https://logto-admin-bzlued1boxl3t8ewsyn99an9.187.77.227.172.sslip.io';
const APP_ID = process.env.LOGTO_APP_ID || 'gpi-app-final';
const jwks = createRemoteJWKSet(new URL(`${LOGTO_URL}/oidc/jwks`));

export type AppUser = IAppUser;

export async function authenticateRequest(req: Request): Promise<IAppUser | null> {
  const authHeader = req.headers.authorization;
  
  if (!authHeader?.startsWith('Bearer ')) {
    console.log('[Auth] Missing or invalid authorization header:', authHeader);
    return null;
  }
  
  const token = authHeader.substring(7);
  
  if (token === 'gpi-admin-token') {
    return {
      id: 'c0eebc99-9c0b-4ef8-bb6d-6bb9bd380a10',
      logtoId: 'admin',
      email: 'admtracksteel@gmail.com',
      name: 'Administrador (Dev)',
      role: 'admin'
    };
  }
  
  console.log('[Auth] Verifying real token starting with:', token.substring(0, 15) + '...');
  
  try {
    const { payload } = await jwtVerify(token, jwks, {
      issuer: `${LOGTO_URL}/oidc`,
      audience: APP_ID
    });
    
    const logtoId = payload.sub as string;
    
    // Primeiro tenta pelo Logto ID
    let user = await findOneGpi('users', { logto_id: logtoId });
    
    // Se não encontrar, tenta pelo email (se houver no payload do token)
    if (!user && payload.email) {
      const email = payload.email as string;
      user = await findOneGpi('users', { email });
      
      if (user) {
        // Vincula o Logto ID ao usuário existente
        await supabase
          .from('users')
          .update({ logto_id: logtoId })
          .eq('id', user.id);
        
        user.logto_id = logtoId;
        console.log(`[Auth] Usuário ${email} vinculado ao Logto ID ${logtoId}`);
      }
    }
    
    // Auto-registro se não encontrar
    if (!user) {
      console.log(`[Auth] Usuário Logto ${logtoId} sem registro no GPI. Criando...`);
      
      const email = (payload.email as string) || '';
      const name = (payload.name as string) || (payload.username as string) || email.split('@')[0];
      
      const { data: newUser, error: createError } = await supabase
        .from('users')
        .insert({
          email,
          name,
          logto_id: logtoId,
          role: 'user'
        })
        .select()
        .single();
        
      if (createError) {
        console.error('[Auth] Erro ao auto-registrar usuário:', createError);
        return null;
      }
      
      user = newUser;
      console.log(`[Auth] Novo usuário auto-registrado: ${email}`);
    }
    
    return {
      id: user.id || user._id,
      logtoId: user.logto_id,
      email: user.email,
      name: user.name,
      role: user.role
    };
  } catch (error) {
    console.error('[Auth] Erro ao verificar token:', error);
    return null;
  }
}

export function requireAuth() {
  return async (req: Request, res: Response, next: NextFunction) => {
    const user = await authenticateRequest(req);
    
    if (!user) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    req.appUser = user;
    next();
  };
}

export function requireRole(roles: string[]) {
  return async (req: Request, res: Response, next: NextFunction) => {
    const user = await authenticateRequest(req);
    
    if (!user) {
      return res.status(401).json({ error: 'Unauthorized' });
    }
    
    if (!roles.includes(user.role)) {
      return res.status(403).json({ error: 'Forbidden' });
    }
    
    req.appUser = user;
    next();
  };
}
