const passport = require('passport');
const OpenIDConnectStrategy = require('passport-openidconnect').Strategy;
const { userOps } = require('./database');

// Configure OpenID Connect strategy
function configureAuth(app) {
  // Check if OIDC is configured
  const isOIDCConfigured = process.env.OIDC_ISSUER && 
                          process.env.OIDC_CLIENT_ID && 
                          process.env.OIDC_CLIENT_SECRET &&
                          process.env.OIDC_AUTH_URL &&
                          process.env.OIDC_TOKEN_URL &&
                          process.env.OIDC_USERINFO_URL;

  if (!isOIDCConfigured) {
    console.log('OpenID Connect not configured. Authentication features disabled.');
    console.log('To enable authentication, set the following environment variables:');
    console.log('- OIDC_ISSUER');
    console.log('- OIDC_CLIENT_ID');
    console.log('- OIDC_CLIENT_SECRET');
    console.log('- OIDC_AUTH_URL');
    console.log('- OIDC_TOKEN_URL');
    console.log('- OIDC_USERINFO_URL');
    console.log('- OIDC_CALLBACK_URL (optional, defaults to /auth/callback)');
    
    // Add disabled auth routes
    app.get('/auth/login', (req, res) => {
      res.status(501).json({ error: 'Authentication not configured' });
    });
    
    app.get('/auth/user', (req, res) => {
      res.status(401).json({ error: 'Authentication not configured' });
    });
    
    app.post('/auth/logout', (req, res) => {
      res.status(501).json({ error: 'Authentication not configured' });
    });
    
    return;
  }

  // Session configuration
  const session = require('express-session');
  
  app.use(session({
    secret: process.env.SESSION_SECRET || 'your-secret-key-change-in-production',
    resave: false,
    saveUninitialized: false,
    cookie: {
      secure: false, // Set to false for development/HTTP
      httpOnly: true,
      maxAge: 24 * 60 * 60 * 1000, // 24 hours
      sameSite: 'lax'
    }
  }));

  // Initialize Passport
  app.use(passport.initialize());
  app.use(passport.session());

  // Log OIDC configuration for debugging
  console.log('OIDC Configuration:');
  console.log('Issuer:', process.env.OIDC_ISSUER);
  console.log('Auth URL:', process.env.OIDC_AUTH_URL);
  console.log('Token URL:', process.env.OIDC_TOKEN_URL);
  console.log('UserInfo URL:', process.env.OIDC_USERINFO_URL);
  console.log('Client ID:', process.env.OIDC_CLIENT_ID);
  console.log('Callback URL:', process.env.OIDC_CALLBACK_URL || '/auth/callback');

  // Configure OpenID Connect strategy
  passport.use('oidc', new OpenIDConnectStrategy({
    issuer: process.env.OIDC_ISSUER,
    authorizationURL: process.env.OIDC_AUTH_URL,
    tokenURL: process.env.OIDC_TOKEN_URL,
    userInfoURL: process.env.OIDC_USERINFO_URL,
    clientID: process.env.OIDC_CLIENT_ID,
    clientSecret: process.env.OIDC_CLIENT_SECRET,
    callbackURL: process.env.OIDC_CALLBACK_URL || '/auth/callback',
    scope: 'openid email profile',
    skipUserProfile: false
  }, (issuer, sub, profile, accessToken, refreshToken, done) => {
    console.log('OIDC Strategy callback:');
    console.log('Issuer:', issuer);
    console.log('Profile data (sub):', sub);
    
    // Based on debugging: profile is actually the callback function
    const callback = profile;
    console.log('Using profile parameter as callback:', typeof callback);
    
    // Extract user info from sub parameter (which contains the actual profile data)
    const userProfile = {
      sub: sub.id,
      email: sub.emails?.[0]?.value,
      name: sub.displayName || sub.name?.givenName || sub.username
    };

    console.log('Extracted user profile:', userProfile);

    userOps.findOrCreateUser(userProfile, (err, user) => {
      if (err) {
        console.error('Database error in findOrCreateUser:', err);
        return callback(err);
      }
      console.log('User from database:', user);
      callback(null, user);
    });
  }));

  // Serialize user for session
  passport.serializeUser((user, done) => {
    done(null, user.id);
  });

  // Deserialize user from session
  passport.deserializeUser((id, done) => {
    userOps.findById(id, (err, user) => {
      done(err, user);
    });
  });

  // Auth routes
  app.get('/auth/login', passport.authenticate('oidc'));

  app.get('/auth/callback', (req, res, next) => {
    console.log('Auth callback received');
    console.log('Query params:', req.query);
    console.log('Body:', req.body);
    
    passport.authenticate('oidc', (err, user, info) => {
      console.log('Passport authenticate callback:');
      console.log('Error:', err);
      console.log('User:', user);
      console.log('Info:', info);
      
      if (err) {
        console.error('Authentication error:', err);
        return res.redirect('/?error=auth_failed');
      }
      
      if (!user) {
        console.error('No user returned from authentication');
        return res.redirect('/?error=no_user');
      }
      
      req.logIn(user, (err) => {
        if (err) {
          console.error('Login error:', err);
          return res.redirect('/?error=login_failed');
        }
        
        console.log('User successfully logged in:', user);
        res.redirect('/');
      });
    })(req, res, next);
  });

  app.post('/auth/logout', (req, res) => {
    req.logout((err) => {
      if (err) {
        return res.status(500).json({ error: 'Logout failed' });
      }
      req.session.destroy((err) => {
        if (err) {
          return res.status(500).json({ error: 'Session destruction failed' });
        }
        res.json({ message: 'Logged out successfully' });
      });
    });
  });

  // Get current user
  app.get('/auth/user', (req, res) => {
    console.log('Auth check - Session ID:', req.sessionID);
    console.log('Auth check - Is authenticated:', req.isAuthenticated());
    console.log('Auth check - User:', req.user);
    console.log('Auth check - Session:', req.session);
    
    if (req.isAuthenticated()) {
      res.json({
        user: {
          id: req.user.id,
          email: req.user.email,
          name: req.user.name
        }
      });
    } else {
      res.status(401).json({ error: 'Not authenticated' });
    }
  });
}

// Middleware to require authentication
function requireAuth(req, res, next) {
  if (req.isAuthenticated()) {
    return next();
  }
  res.status(401).json({ error: 'Authentication required' });
}

// Middleware to optionally include user info
function optionalAuth(req, res, next) {
  // Always proceed, but user info will be available if authenticated
  next();
}

module.exports = {
  configureAuth,
  requireAuth,
  optionalAuth
};
