const express = require('express');
const router = express.Router();
const authService = require('../services/authService');
const User = require('../models/user');
// Remove cross-service dependencies - use API calls instead
const serviceClient = require('../services/serviceClient');
const {
  authenticateToken,
  optionalAuth,
  requireAdmin,
  requireUserOrAdmin,
  loginRateLimit,
  registerRateLimit,
  passwordChangeRateLimit,
  validateSession,
  validateOwnership,
  validateRegistration,
  validateLogin,
  logAuthRequests
} = require('../middleware/auth');

// Apply request logging to all auth routes
router.use(logAuthRequests);

// ========================================
// PUBLIC ROUTES (No Authentication Required)
// ========================================

// POST /api/auth/register - Register new user
router.post('/register', registerRateLimit, validateRegistration, async (req, res) => {
  try {
    const { username, email, password, first_name, last_name } = req.body;
    
    console.log(`📝 Registration attempt for: ${email}`);
    
    const user = await authService.register({
      username,
      email,
      password,
      first_name,
      last_name
    });
    
    res.status(201).json({
      success: true,
      data: {
        user: user.toJSON(),
        message: 'User registered successfully. Please check your email to verify your account.'
      },
      message: 'Registration completed successfully'
    });
  } catch (error) {
    console.error('❌ Registration failed:', error.message);
    res.status(400).json({
      success: false,
      error: 'Registration failed',
      message: error.message
    });
  }
});

// GET /api/auth/verify-email - Verify email via token and redirect to login
router.get('/verify-email', async (req, res) => {
  try {
    const { token } = req.query;
    
    if (!token) {
      // Use centralized config instead of environment variables
      let frontendUrl;
      try {
        const urls = require('../../../../config/urls');
        frontendUrl = urls.FRONTEND_URL || 'https://dashboard.codenuk.com';
      } catch (err) {
        frontendUrl = 'https://dashboard.codenuk.com';
      }
      const redirectUrl = `${frontendUrl}/signin?error=${encodeURIComponent('Verification token is required')}`;
      if (req.query.format === 'json') {
        return res.status(400).json({ success: false, message: 'Verification token is required', redirect: redirectUrl });
      }
      return res.redirect(302, redirectUrl);
    }

    await authService.verifyEmailToken(token);

    // Use centralized config instead of environment variables
    let frontendUrl;
    try {
      const urls = require('../../../../config/urls');
      frontendUrl = urls.FRONTEND_URL || 'https://dashboard.codenuk.com';
    } catch (err) {
      frontendUrl = 'https://dashboard.codenuk.com';
    }
    const redirectUrl = `${frontendUrl}/signin?verified=true`;
    
    console.log(`✅ Email verification successful, redirecting to: ${redirectUrl}`);
    
    // Prefer redirect by default; only return JSON if explicitly requested
    if (req.query.format === 'json') {
      return res.json({ 
        success: true, 
        message: 'Email verified successfully', 
        redirect: redirectUrl 
      });
    }
    return res.redirect(302, redirectUrl);
  } catch (error) {
    // Use centralized config instead of environment variables
    let frontendUrl;
    try {
      const urls = require('../../../../config/urls');
      frontendUrl = urls.FRONTEND_URL || 'https://dashboard.codenuk.com';
    } catch (err) {
      frontendUrl = 'https://dashboard.codenuk.com';
    }
    const redirectUrl = `${frontendUrl}/signin?error=${encodeURIComponent(error.message)}`;
    
    console.error(`❌ Email verification failed: ${error.message}, redirecting to: ${redirectUrl}`);
    
    if (req.query.format === 'json') {
      return res.status(400).json({ 
        success: false, 
        message: error.message, 
        redirect: redirectUrl 
      });
    }
    return res.redirect(302, redirectUrl);
  }
});

// POST /api/auth/resend-verification - Resend verification email
router.post('/resend-verification', async (req, res) => {
  try {
    const { email } = req.body;
    
    if (!email) {
      return res.status(400).json({
        success: false,
        error: 'Email is required',
        message: 'Please provide an email address'
      });
    }

    // Find user by email
    const user = await User.findByEmail(email);
    if (!user) {
      return res.status(404).json({
        success: false,
        error: 'User not found',
        message: 'No account found with this email address'
      });
    }

    // Check if already verified
    if (user.email_verified) {
      return res.status(400).json({
        success: false,
        error: 'Already verified',
        message: 'This email address is already verified'
      });
    }

    // Send verification email
    await authService.sendVerificationEmail(user);
    
    console.log(`📧 Verification email resent to: ${email}`);
    
    res.json({
      success: true,
      message: 'Verification email sent successfully. Please check your inbox.'
    });
  } catch (error) {
    console.error('❌ Resend verification failed:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to resend verification',
      message: error.message
    });
  }
});

// POST /api/auth/login - User login
router.post('/login', loginRateLimit , validateLogin, async (req, res) => {
  try {
    const { email, password } = req.body;
    console.log('🔑 Login attempt for: ', email, password);
    const sessionInfo = {
      ip_address: req.ip,
      user_agent: req.get('User-Agent'),
      device_info: {
        platform: req.get('X-Platform') || 'web',
        app_version: req.get('X-App-Version') || '1.0.0'
      }
    };
    
    console.log(`🔑 Login attempt for: ${email}`);
    
    const result = await authService.login({ email, password }, sessionInfo);
    
    // Set session cookie (optional)
    res.cookie('sessionToken', result.session.session_token, {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'strict',
      maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days
    });
    
    res.json({
      success: true,
      data: result,
      message: 'Login successful'
    });
  } catch (error) {
    console.error('❌ Login failed:', error.message);
    res.status(401).json({
      success: false,
      error: 'Login failed',
      message: error.message
    });
  }
});

// POST /api/auth/refresh - Refresh access token
router.post('/refresh', async (req, res) => {
  try {
    const { refreshToken } = req.body;
    
    if (!refreshToken) {
      return res.status(400).json({
        success: false,
        error: 'Refresh token required',
        message: 'Please provide a refresh token'
      });
    }
    
    console.log('🔄 Token refresh attempt');
    
    const result = await authService.refreshToken(refreshToken);
    
    res.json({
      success: true,
      data: result,
      message: 'Token refreshed successfully'
    });
  } catch (error) {
    console.error('❌ Token refresh failed:', error.message);
    res.status(401).json({
      success: false,
      error: 'Token refresh failed',
      message: error.message
    });
  }
});

// ========================================
// PROTECTED ROUTES (Authentication Required)
// ========================================

// POST /api/auth/logout - User logout
router.post('/logout', optionalAuth, async (req, res) => {
  try {
    const { refreshToken } = req.body;
    const sessionToken = req.cookies.sessionToken;
    
    console.log(`🚪 Logout attempt for: ${req.user ? req.user.email : 'anonymous'}`);
    
    await authService.logout(refreshToken, sessionToken);
    
    // Clear session cookie
    res.clearCookie('sessionToken');
    
    res.json({
      success: true,
      message: 'Logged out successfully'
    });
  } catch (error) {
    console.error('❌ Logout failed:', error.message);
    res.status(500).json({
      success: false,
      error: 'Logout failed',
      message: error.message
    });
  }
});

// GET /api/auth/me - Get current user profile
router.get('/me', authenticateToken, validateSession, async (req, res) => {
  try {
    const user = req.user;
    const stats = await user.getStats();
    
    res.json({
      success: true,
      data: {
        user: user.toJSON(),
        stats
      },
      message: 'User profile retrieved successfully'
    });
  } catch (error) {
    console.error('❌ Profile fetch failed:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch profile',
      message: error.message
    });
  }
});

// PUT /api/auth/me - Update user profile
router.put('/me', authenticateToken, validateSession, async (req, res) => {
  try {
    const { first_name, last_name, username } = req.body;
    const user = req.user;
    
    console.log(`📝 Profile update for: ${user.email}`);
    
    const updatedUser = await user.updateProfile({
      first_name,
      last_name,
      username
    });
    
    res.json({
      success: true,
      data: {
        user: updatedUser.toJSON()
      },
      message: 'Profile updated successfully'
    });
  } catch (error) {
    console.error('❌ Profile update failed:', error.message);
    res.status(400).json({
      success: false,
      error: 'Profile update failed',
      message: error.message
    });
  }
});

// PUT /api/auth/change-password - Change user password
router.put('/change-password', authenticateToken, passwordChangeRateLimit, validateSession, async (req, res) => {
  try {
    const { currentPassword, newPassword } = req.body;
    const userId = req.user.id;
    
    if (!currentPassword || !newPassword) {
      return res.status(400).json({
        success: false,
        error: 'Validation failed',
        message: 'Current password and new password are required'
      });
    }
    
    console.log(`🔒 Password change for: ${req.user.email}`);
    
    await authService.changePassword(userId, currentPassword, newPassword);
    
    res.json({
      success: true,
      message: 'Password changed successfully. Please log in again.'
    });
  } catch (error) {
    console.error('❌ Password change failed:', error.message);
    res.status(400).json({
      success: false,
      error: 'Password change failed',
      message: error.message
    });
  }
});

// ========================================
// USER FEATURE PREFERENCES
// ========================================

// GET /api/auth/preferences/:templateType - Get user's feature preferences for a template
router.get('/preferences/:templateType', authenticateToken, validateSession, async (req, res) => {
  try {
    const { templateType } = req.params;
    const user = req.user;
    
    console.log(`📋 Fetching preferences for ${user.email} - ${templateType}`);
    
    const preferences = await user.getFeaturePreferences(templateType);
    
    res.json({
      success: true,
      data: {
        templateType,
        preferences
      },
      message: 'Feature preferences retrieved successfully'
    });
  } catch (error) {
    console.error('❌ Failed to fetch preferences:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch preferences',
      message: error.message
    });
  }
});

// POST /api/auth/preferences - Set feature preference
router.post('/preferences', authenticateToken, validateSession, async (req, res) => {
  try {
    const { templateType, featureId, preferenceType, customData } = req.body;
    const user = req.user;
    
    if (!templateType || !featureId || !preferenceType) {
      return res.status(400).json({
        success: false,
        error: 'Validation failed',
        message: 'Template type, feature ID, and preference type are required'
      });
    }
    
    console.log(`🎯 Setting preference for ${user.email}: ${preferenceType} ${featureId} in ${templateType}`);
    
    const preference = await user.setFeaturePreference(templateType, featureId, preferenceType, customData);
    
    res.json({
      success: true,
      data: preference,
      message: 'Feature preference set successfully'
    });
  } catch (error) {
    console.error('❌ Failed to set preference:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to set preference',
      message: error.message
    });
  }
});

// DELETE /api/auth/preferences/:templateType/:featureId/:preferenceType - Remove feature preference
router.delete('/preferences/:templateType/:featureId/:preferenceType', authenticateToken, validateSession, async (req, res) => {
  try {
    const { templateType, featureId, preferenceType } = req.params;
    const user = req.user;
    
    console.log(`🗑️ Removing preference for ${user.email}: ${preferenceType} ${featureId} in ${templateType}`);
    
    const removed = await user.removeFeaturePreference(templateType, featureId, preferenceType);
    
    if (removed) {
      res.json({
        success: true,
        message: 'Feature preference removed successfully'
      });
    } else {
      res.status(404).json({
        success: false,
        error: 'Preference not found',
        message: 'The specified preference does not exist'
      });
    }
  } catch (error) {
    console.error('❌ Failed to remove preference:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to remove preference',
      message: error.message
    });
  }
});

// ========================================
// USER PROJECTS
// ========================================

// GET /api/auth/projects - Get user's projects
router.get('/projects', authenticateToken, validateSession, async (req, res) => {
  try {
    const limit = parseInt(req.query.limit) || 10;
    const user = req.user;
    
    console.log(`📁 Fetching projects for: ${user.email}`);
    
    const projects = await user.getProjects(limit);
    
    res.json({
      success: true,
      data: {
        projects,
        count: projects.length
      },
      message: 'Projects retrieved successfully'
    });
  } catch (error) {
    console.error('❌ Failed to fetch projects:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch projects',
      message: error.message
    });
  }
});

// POST /api/auth/projects - Save user project
router.post('/projects', authenticateToken, validateSession, async (req, res) => {
  try {
    const projectData = req.body;
    const user = req.user;
    
    if (!projectData.project_name || !projectData.project_type) {
      return res.status(400).json({
        success: false,
        error: 'Validation failed',
        message: 'Project name and type are required'
      });
    }
    
    console.log(`💾 Saving project for ${user.email}: ${projectData.project_name}`);
    
    const project = await user.saveProject(projectData);
    
    res.status(201).json({
      success: true,
      data: project,
      message: 'Project saved successfully'
    });
  } catch (error) {
    console.error('❌ Failed to save project:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to save project',
      message: error.message
    });
  }
});

// ========================================
// ADMIN ROUTES
// ========================================

// GET /api/auth/admin/stats - Get authentication statistics (Admin only)
router.get('/admin/stats', authenticateToken, requireAdmin, async (req, res) => {
  try {
    console.log(`📊 Admin stats requested by: ${req.user.email}`);
    
    const [authStats, userStats] = await Promise.all([
      authService.getStats(),
      User.getUserStats()
    ]);
    
    res.json({
      success: true,
      data: {
        auth: authStats,
        users: userStats
      },
      message: 'Authentication statistics retrieved successfully'
    });
  } catch (error) {
    console.error('❌ Failed to fetch admin stats:', error.message);
    res.status(500).json({
      success: false,
      error: 'Failed to fetch statistics',
      message: error.message
    });
  }
});

// POST /api/auth/admin/cleanup - Run auth cleanup (Admin only)
router.post('/admin/cleanup', authenticateToken, requireAdmin, async (req, res) => {
  try {
    console.log(`🧹 Auth cleanup requested by: ${req.user.email}`);
    
    const result = await authService.cleanup();
    
    res.json({
      success: true,
      data: result,
      message: 'Authentication cleanup completed successfully'
    });
  } catch (error) {
    console.error('❌ Auth cleanup failed:', error.message);
    res.status(500).json({
      success: false,
      error: 'Cleanup failed',
      message: error.message
    });
  }
});

// PUT /api/auth/admin/users/:id/role - Update a user's role (Admin only)
router.put('/admin/users/:id/role', authenticateToken, requireAdmin, async (req, res) => {
  try {
    const { id } = req.params;
    const { role } = req.body;
    const allowed = ['user', 'admin'];
    if (!allowed.includes(role)) {
      return res.status(400).json({
        success: false,
        error: 'Invalid role',
        message: `Role must be one of: ${allowed.join(', ')}`
      });
    }

    const user = await User.findById(id);
    if (!user) {
      return res.status(404).json({ success: false, error: 'User not found' });
    }

    await require('../config/database').query(
      'UPDATE users SET role = $1, updated_at = NOW() WHERE id = $2',
      [role, id]
    );

    const updated = await User.findById(id);
    res.json({ success: true, data: updated.toJSON(), message: 'User role updated' });
  } catch (error) {
    console.error('Failed to update user role:', error.message);
    res.status(500).json({ success: false, error: 'Failed to update role', message: error.message });
  }
});

// GET /api/auth/admin/users - List users (Admin only)
router.get('/admin/users', authenticateToken, requireAdmin, async (req, res) => {
  try {
    const limit = parseInt(req.query.limit) || 25;
    const offset = parseInt(req.query.offset) || 0;
    const db = require('../config/database');
    const result = await db.query(
      `SELECT id, username, email, first_name, last_name, role, email_verified, is_active, created_at, updated_at
       FROM users ORDER BY created_at DESC LIMIT $1 OFFSET $2`,
      [limit, offset]
    );
    res.json({ success: true, data: result.rows, count: result.rows.length, message: 'Users retrieved' });
  } catch (error) {
    console.error('Failed to list users:', error.message);
    res.status(500).json({ success: false, error: 'Failed to list users', message: error.message });
  }
});

// GET /api/auth/admin/custom-features - Get all custom features (Admin only)
router.get('/admin/custom-features', authenticateToken, requireAdmin, async (req, res) => {
  try {
    const { status, limit = 50, offset = 0 } = req.query;
    console.log(`📋 Admin fetching custom features - status: ${status || 'all'}`);
    
    // Extract the token from the Authorization header
    const authToken = req.headers.authorization?.replace('Bearer ', '');
    const result = await serviceClient.getCustomFeatures(status, parseInt(limit), parseInt(offset), authToken);
    
    res.json({
      success: true,
      data: result.data,
      message: 'Custom features retrieved successfully'
    });
  } catch (error) {
    console.error('❌ Failed to fetch custom features:', error.message);
    res.status(503).json({
      success: false,
      error: 'Service unavailable',
      message: error.message
    });
  }
});

// POST /api/auth/admin/custom-features/:id/review - Review custom feature (Admin only)
router.post('/admin/custom-features/:id/review', authenticateToken, requireAdmin, async (req, res) => {
  try {
    const { id } = req.params;
    const { status, admin_notes } = req.body;
    
    if (!['approved', 'rejected', 'duplicate'].includes(status)) {
      return res.status(400).json({
        success: false,
        error: 'Invalid status',
        message: 'Status must be approved, rejected, or duplicate'
      });
    }
    
    console.log(`📝 Admin reviewing custom feature ${id} - status: ${status}`);
    
    const reviewData = {
      status,
      admin_notes,
      admin_reviewed_by: req.user.id
    };
    
    // Extract the token from the Authorization header
    const authToken = req.headers.authorization?.replace('Bearer ', '');
    const result = await serviceClient.reviewCustomFeature(id, reviewData, authToken);
    
    res.json({
      success: true,
      data: result.data,
      message: `Custom feature ${status} successfully`
    });
  } catch (error) {
    console.error('❌ Failed to review custom feature:', error.message);
    res.status(503).json({
      success: false,
      error: 'Service unavailable',
      message: error.message
    });
  }
});

// PUT /api/auth/admin/custom-features/:id/review - Review custom feature (Admin only)
router.put('/admin/custom-features/:id/review', authenticateToken, requireAdmin, async (req, res) => {
  try {
    const { id } = req.params;
    const { status, admin_notes } = req.body;
    
    if (!['approved', 'rejected', 'duplicate'].includes(status)) {
      return res.status(400).json({
        success: false,
        error: 'Invalid status',
        message: 'Status must be approved, rejected, or duplicate'
      });
    }
    
    console.log(`📝 (PUT) Admin reviewing custom feature ${id} - status: ${status}`);
    
    const reviewData = {
      status,
      admin_notes,
      admin_reviewed_by: req.user.id
    };
    
    const authToken = req.headers.authorization?.replace('Bearer ', '');
    const result = await serviceClient.reviewCustomFeature(id, reviewData, authToken);
    
    res.json({
      success: true,
      data: result.data,
      message: `Custom feature ${status} successfully`
    });
  } catch (error) {
    console.error('❌ Failed to review custom feature (PUT):', error.message);
    res.status(503).json({
      success: false,
      error: 'Service unavailable',
      message: error.message
    });
  }
});

// GET /api/auth/admin/custom-templates - Get all custom templates (Admin only)
router.get('/admin/custom-templates', authenticateToken, requireAdmin, async (req, res) => {
  try {
    const { status, limit = 50, offset = 0 } = req.query;
    console.log(`📋 Admin fetching custom templates - status: ${status || 'all'}`);
    
    // Extract the token from the Authorization header
    const authToken = req.headers.authorization?.replace('Bearer ', '');
    const result = await serviceClient.getCustomTemplates(status, parseInt(limit), parseInt(offset), authToken);
    
    res.json({
      success: true,
      data: result.data,
      message: 'Custom templates retrieved successfully'
    });
  } catch (error) {
    console.error('❌ Failed to fetch custom templates:', error.message);
    res.status(503).json({
      success: false,
      error: 'Service unavailable',
      message: error.message
    });
  }
});

// POST /api/auth/admin/custom-templates/:id/review - Review custom template (Admin only)
router.post('/admin/custom-templates/:id/review', authenticateToken, requireAdmin, async (req, res) => {
  try {
    const { id } = req.params;
    const { status, admin_notes } = req.body;
    
    if (!['approved', 'rejected', 'duplicate'].includes(status)) {
      return res.status(400).json({
        success: false,
        error: 'Invalid status',
        message: 'Status must be approved, rejected, or duplicate'
      });
    }
    
    console.log(`📝 Admin reviewing custom template ${id} - status: ${status}`);
    
    const reviewData = {
      status,
      admin_notes,
      admin_reviewed_by: req.user.id
    };
    
    // Extract the token from the Authorization header
    const authToken = req.headers.authorization?.replace('Bearer ', '');
    const result = await serviceClient.reviewCustomTemplate(id, reviewData, authToken);
    
    res.json({
      success: true,
      data: result.data,
      message: `Custom template ${status} successfully`
    });
  } catch (error) {
    console.error('❌ Failed to review custom template:', error.message);
    res.status(503).json({
      success: false,
      error: 'Service unavailable',
      message: error.message
    });
  }
});

// PUT /api/auth/admin/custom-templates/:id/review - Review custom template (Admin only)
router.put('/admin/custom-templates/:id/review', authenticateToken, requireAdmin, async (req, res) => {
  try {
    const { id } = req.params;
    const { status, admin_notes } = req.body;
    
    if (!['approved', 'rejected', 'duplicate'].includes(status)) {
      return res.status(400).json({
        success: false,
        error: 'Invalid status',
        message: 'Status must be approved, rejected, or duplicate'
      });
    }
    
    console.log(`📝 (PUT) Admin reviewing custom template ${id} - status: ${status}`);
    
    const reviewData = {
      status,
      admin_notes,
      admin_reviewed_by: req.user.id
    };
    
    const authToken = req.headers.authorization?.replace('Bearer ', '');
    const result = await serviceClient.reviewCustomTemplate(id, reviewData, authToken);
    
    res.json({
      success: true,
      data: result.data,
      message: `Custom template ${status} successfully`
    });
  } catch (error) {
    console.error('❌ Failed to review custom template (PUT):', error.message);
    res.status(503).json({
      success: false,
      error: 'Service unavailable',
      message: error.message
    });
  }
});

// ========================================
// TOKEN VERIFICATION (For internal service checks)
// ========================================

// GET /api/auth/verify - Verify access token and return user info
router.get('/verify', authenticateToken, async (req, res) => {
  try {
    const user = req.user;
    const payload = user && user.toJSON ? user.toJSON() : user;
    return res.json({ success: true, data: { user: payload }, message: 'Token verified' });
  } catch (error) {
    console.error('❌ Token verification error:', error.message);
    return res.status(401).json({ success: false, error: 'Token verification failed', message: error.message });
  }
});

module.exports = router;