const User = require('../models/User');
const Client = require('../models/Client');
const MasmScheme = require('../models/MasmScheme');
const { generateOTP, sendOTPEmail } = require('../config/email');
const { generateToken } = require('../config/jwt');
const TokenBlacklist = require('../models/TokenBlacklist');
const bcrypt = require('bcryptjs');

const authController = {
    // Validate access token and return decoded user payload
    checkToken: (req, res) => {
        // req.user is set by authenticateToken middleware
        if (!req.user) {
            return res.status(401).json({ valid: false, error: 'Unauthorized' });
        }

        const expiresAt = req.user.exp ? new Date(req.user.exp * 1000).toISOString() : null;

        return res.json({
            valid: true,
            user: {
                id: req.user.id,
                email: req.user.email,
                first_name: req.user.first_name,
                last_name: req.user.last_name,
                phone_number: req.user.phone_number,
                role: req.user.role
            },
            expires_at: expiresAt
        });
    },

    // Logout by blacklisting the current token
    logout: (req, res) => {
        const token = req.token;
        const expSeconds = req.user?.exp;

        if (!token || !req.user) {
            return res.status(401).json({ error: 'Unauthorized', message: 'No token to invalidate' });
        }

        const expiresAt = expSeconds ? new Date(expSeconds * 1000) : null;

        TokenBlacklist.add(token, expiresAt, (err) => {
            if (err) {
                return res.status(500).json({ error: 'Failed to invalidate token', message: err.message });
            }
            return res.json({ message: 'Logged out successfully' });
        });
    },

    // Registration endpoint
    register: (req, res) => {
        const { 
            first_name, 
            last_name, 
            email, 
            password, 
            role,
            // Client-specific fields (optional, only if role is 'client')
            insurance_scheme_id,
            phone_number,
            is_cash_client,
            membership_number,
            suffix,
            address,
            date_of_birth,
            emergency_contact_name,
            emergency_contact_phone
        } = req.body;

        // Validate required fields
        if (!first_name || !last_name || !email || !password || !role) {
            return res.status(400).json({ 
                error: 'Missing required fields: first_name, last_name, email, password, and role are required' 
            });
        }

        // If role is client, validate client-specific fields
        if (role.toLowerCase() === 'client') {
            if (!phone_number) {
                return res.status(400).json({ 
                    error: 'Phone number is required for client registration' 
                });
            }
        }

        // Check if email already exists
        User.findByEmail(email, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            
            if (results.length > 0) {
                return res.status(400).json({ error: 'Email already registered' });
            }

            // If role is client and insurance_scheme_id is provided, validate it exists
            if (role.toLowerCase() === 'client' && insurance_scheme_id) {
                MasmScheme.findById(insurance_scheme_id, (err, schemeResults) => {
                    if (err) {
                        return res.status(500).json({ error: err.message });
                    }
                    
                    if (schemeResults.length === 0) {
                        return res.status(400).json({ error: 'Invalid insurance_scheme_id. Scheme not found.' });
                    }
                    
                    // Continue with registration
                    proceedWithRegistration();
                });
            } else {
                // No insurance scheme validation needed, proceed
                proceedWithRegistration();
            }
        });

        // Helper function to proceed with registration
        function proceedWithRegistration() {
            // Generate OTP
            const otp = generateOTP();

            // Hash the password before storing
            bcrypt.hash(password, 10, (err, hashedPassword) => {
                if (err) {
                    return res.status(500).json({ error: 'Error hashing password' });
                }

                // Auto-verify drivers and admins
                const roleLower = role?.toLowerCase();
                const shouldAutoVerify = roleLower === 'driver' || roleLower === 'admin';
                const isVerified = shouldAutoVerify ? true : false;
                
                // Insert user with hashed password
                User.create({ first_name, last_name, email, phone_number, password: hashedPassword, role, otp, is_verified: isVerified }, (err, userResults) => {
                if (err) {
                    return res.status(500).json({ error: err.message });
                }

                    const userId = userResults.insertId;

                    // If role is client, insert into clients table
                    if (role.toLowerCase() === 'client') {
                        Client.create({
                            user_id: userId,
                            insurance_scheme_id,
                            phone_number,
                            is_cash_client,
                            membership_number,
                            suffix,
                            address,
                            date_of_birth,
                            emergency_contact_name,
                            emergency_contact_phone
                        }, (err, clientResults) => {
                            if (err) {
                                // Rollback: delete user if client insertion fails
                                User.delete(userId, () => {});
                                return res.status(500).json({ error: err.message });
                            }

                            // Send OTP email
                            sendOTPEmail(email, otp)
                                .then(() => {
                                    res.status(201).json({
                                        message: 'Registration successful. OTP sent to your email.',
                                        user_id: userId,
                                        email: email
                                    });
                                })
                                .catch((emailError) => {
                                    console.error('Error sending email:', emailError);
                                    // User created but email failed - still return success but warn
                                    res.status(201).json({
                                        message: 'Registration successful, but failed to send verification email. Please contact support.',
                                        user_id: userId,
                                        email: email,
                                        warning: 'Email delivery failed'
                                    });
                                });
                        });
                    } else {
                        // Non-client user - just send OTP email
                        sendOTPEmail(email, otp)
                            .then(() => {
                                res.status(201).json({
                                    message: 'Registration successful. OTP sent to your email.',
                                    user_id: userId,
                                    email: email
                                });
                            })
                            .catch((emailError) => {
                                console.error('Error sending email:', emailError);
                                res.status(201).json({
                                    message: 'Registration successful, but failed to send verification email. Please contact support.',
                                    user_id: userId,
                                    email: email,
                                    warning: 'Email delivery failed'
                                });
                            });
                    }
                });
            });
        }
    },

    // Verify email endpoint
    verifyEmail: (req, res) => {
        const { email, otp } = req.body;

        if (!email || !otp) {
            return res.status(400).json({ error: 'Email and OTP are required' });
        }

        // Find user by email and check OTP
        User.findByEmail(email, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }

            if (results.length === 0) {
                return res.status(404).json({ error: 'User not found' });
            }

            const user = results[0];

            if (user.is_verified) {
                return res.status(400).json({ error: 'Email already verified' });
            }

            if (!user.OTP || user.OTP !== otp) {
                return res.status(400).json({ error: 'Invalid or expired OTP' });
            }

            // Update user: set is_verified to true and clear OTP
            User.verifyEmail(user.id, (err, updateResults) => {
                if (err) {
                    return res.status(500).json({ error: err.message });
                }

                res.json({
                    message: 'Email verified successfully',
                    user_id: user.id,
                    email: email
                });
            });
        });
    },

    // Resend OTP endpoint
    resendOTP: (req, res) => {
        const { email } = req.body;

        if (!email) {
            return res.status(400).json({ error: 'Email is required' });
        }

        // Find user by email
        User.findByEmail(email, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }

            if (results.length === 0) {
                return res.status(404).json({ error: 'User not found' });
            }

            const user = results[0];

            if (user.is_verified) {
                return res.status(400).json({ error: 'Email already verified. OTP resend is not needed.' });
            }

            // Generate new OTP
            const newOTP = generateOTP();

            // Update user with new OTP
            User.updateOTP(user.id, newOTP, (err, updateResults) => {
                if (err) {
                    return res.status(500).json({ error: err.message });
                }

                // Send new OTP email
                sendOTPEmail(email, newOTP)
                    .then(() => {
                        res.json({
                            message: 'New OTP sent to your email successfully',
                            email: email
                        });
                    })
                    .catch((emailError) => {
                        console.error('Error sending email:', emailError);
                        res.status(500).json({ 
                            error: 'OTP updated but failed to send email. Please try again or contact support.' 
                        });
                    });
            });
        });
    },

    // Login endpoint
    login: (req, res) => {
        const { email, password } = req.body;
        
        if (!email || !password) {
            return res.status(400).json({ error: 'Email and password are required' });
        }

        // Find user by email first
        User.findByEmail(email, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            if (results.length === 0) {
                return res.status(401).json({ message: 'Invalid email or password' });
            }
            
            const user = results[0];

            // Check if email is verified
            if (!user.is_verified) {
                return res.status(403).json({ 
                    error: 'Email not verified. Please verify your email before logging in.',
                    message: 'Please check your email for the verification code or use the resend OTP endpoint.'
                });
            }

            // Compare password with hashed password using bcrypt
            bcrypt.compare(password, user.password, (err, isMatch) => {
                if (err) {
                    return res.status(500).json({ error: 'Error comparing password' });
                }
                
                if (!isMatch) {
                    return res.status(401).json({ message: 'Invalid email or password' });
                }
            
                // Generate JWT token
                const tokenPayload = {
                    id: user.id,
                    email: user.email,
                    first_name: user.first_name,
                    last_name: user.last_name,
                    phone_number: user.phone_number,
                    role: user.role
                };
                const accessToken = generateToken(tokenPayload);
                
                // Return the requested fields: id, first_name, last_name, email, role
                const userData = {
                    id: user.id,
                    first_name: user.first_name,
                    last_name: user.last_name,
                    email: user.email,
                    phone_number: user.phone_number,
                    role: user.role
                };
                
                res.status(200).json({ 
                    message: 'Login successful', 
                    user: userData,
                    accessToken: accessToken,
                    tokenType: 'Bearer'
                });
            });
        });
    },

    // Change password endpoint
    changePassword: (req, res) => {
        const userId = req.user.id; // From authenticated token
        const { current_password, new_password } = req.body;

        if (!current_password || !new_password) {
            return res.status(400).json({ 
                error: 'Current password and new password are required' 
            });
        }

        if (new_password.length < 6) {
            return res.status(400).json({ 
                error: 'New password must be at least 6 characters long' 
            });
        }

        // Get user to verify current password
        User.findById(userId, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            if (results.length === 0) {
                return res.status(404).json({ error: 'User not found' });
            }

            const user = results[0];

            // Verify current password
            bcrypt.compare(current_password, user.password, (err, isMatch) => {
                if (err) {
                    return res.status(500).json({ error: 'Error comparing password' });
                }
                
                if (!isMatch) {
                    return res.status(401).json({ error: 'Current password is incorrect' });
                }

                // Hash new password
                bcrypt.hash(new_password, 10, (err, hashedPassword) => {
                    if (err) {
                        return res.status(500).json({ error: 'Error hashing password' });
                    }

                    // Update password
                    User.update(userId, { password: hashedPassword }, (err, updateResults) => {
                        if (err) {
                            return res.status(500).json({ error: err.message });
                        }

                        res.status(200).json({ 
                            message: 'Password changed successfully' 
                        });
                    });
                });
            });
        });
    }
};

module.exports = authController;

