import { Request, Response, NextFunction } from 'express';
import admin from 'firebase-admin';
import { logger } from '../utils/logger';

// Initialize Firebase Admin if not already initialized
if (!admin.apps.length) {
  try {
    // For Firebase Functions, use default credentials (recommended approach)
    admin.initializeApp({
      projectId: 'cim-summarizer'
    });
    console.log('✅ Firebase Admin initialized with default credentials');
  } catch (error) {
    const errorMessage = error instanceof Error ? error.message : 'Unknown error';
    console.error('❌ Firebase Admin initialization failed:', errorMessage);
    // Don't reinitialize if already initialized
    if (!admin.apps.length) {
      throw error;
    }
  }
}

export interface FirebaseAuthenticatedRequest extends Request {
  user?: admin.auth.DecodedIdToken;
}

export const verifyFirebaseToken = async (
  req: FirebaseAuthenticatedRequest,
  res: Response,
  next: NextFunction
): Promise<void> => {
  try {
    console.log('🔐 Authentication middleware called for:', req.method, req.url);
    console.log('🔐 Request headers:', Object.keys(req.headers));
    
    // Debug Firebase Admin initialization
    console.log('🔐 Firebase apps available:', admin.apps.length);
    console.log('🔐 Firebase app names:', admin.apps.filter(app => app !== null).map(app => app!.name));
    
    const authHeader = req.headers.authorization;
    console.log('🔐 Auth header present:', !!authHeader);
    console.log('🔐 Auth header starts with Bearer:', authHeader?.startsWith('Bearer '));
    
    if (!authHeader || !authHeader.startsWith('Bearer ')) {
      console.log('❌ No valid authorization header');
      res.status(401).json({ error: 'No valid authorization header' });
      return;
    }

    const idToken = authHeader.split('Bearer ')[1];
    console.log('🔐 Token extracted, length:', idToken?.length);
    
    if (!idToken) {
      console.log('❌ No token provided');
      res.status(401).json({ error: 'No token provided' });
      return;
    }

    console.log('🔐 Attempting to verify Firebase ID token...');
    console.log('🔐 Token preview:', idToken.substring(0, 20) + '...');
    
    // Verify the Firebase ID token
    const decodedToken = await admin.auth().verifyIdToken(idToken, true);
    console.log('✅ Token verified successfully for user:', decodedToken.email);
    console.log('✅ Token UID:', decodedToken.uid);
    console.log('✅ Token issuer:', decodedToken.iss);
    
    // Check if token is expired
    const now = Math.floor(Date.now() / 1000);
    if (decodedToken.exp && decodedToken.exp < now) {
      logger.warn('Token expired for user:', decodedToken.uid);
      res.status(401).json({ error: 'Token expired' });
      return;
    }
    
    req.user = decodedToken;
    
    // Log successful authentication
    logger.info('Authenticated request for user:', decodedToken.email);
    
    next();
  } catch (error: any) {
    logger.error('Firebase token verification failed:', {
      error: error.message,
      code: error.code,
      ip: req.ip,
      userAgent: req.get('User-Agent')
    });
    
    // Try to recover from session if Firebase auth fails
    try {
      const authHeader = req.headers.authorization;
      if (authHeader && authHeader.startsWith('Bearer ')) {
        const idToken = authHeader.split('Bearer ')[1];
        
        if (idToken) {
          // Try to verify without force refresh
          const decodedToken = await admin.auth().verifyIdToken(idToken, false);
          req.user = decodedToken;
          logger.info('Recovered authentication from session for user:', decodedToken.email);
          next();
          return;
        }
      }
    } catch (recoveryError) {
      logger.debug('Session recovery failed:', recoveryError);
    }
    
    // Provide more specific error messages
    if (error.code === 'auth/id-token-expired') {
      res.status(401).json({ error: 'Token expired', code: 'TOKEN_EXPIRED' });
    } else if (error.code === 'auth/id-token-revoked') {
      res.status(401).json({ error: 'Token revoked', code: 'TOKEN_REVOKED' });
    } else if (error.code === 'auth/invalid-id-token') {
      res.status(401).json({ error: 'Invalid token', code: 'INVALID_TOKEN' });
    } else {
      res.status(401).json({ error: 'Invalid token' });
    }
  }
};

export const optionalFirebaseAuth = async (
  req: FirebaseAuthenticatedRequest,
  _res: Response,
  next: NextFunction
): Promise<void> => {
  try {
    const authHeader = req.headers.authorization;
    
    if (authHeader && authHeader.startsWith('Bearer ')) {
      const idToken = authHeader.split('Bearer ')[1];
      if (idToken) {
        const decodedToken = await admin.auth().verifyIdToken(idToken, true);
        req.user = decodedToken;
      }
    }
  } catch (error) {
    // Silently ignore auth errors for optional auth
    logger.debug('Optional auth failed:', error);
  }
  
  next();
};