const Client = require('../models/Client');
const AmbulanceRequest = require('../models/AmbulanceRequest');
const User = require('../models/User');
const bcrypt = require('bcryptjs');

const clientController = {
    // Get all clients with user data
    getAll: (req, res) => {
        Client.findAllWithUsers((err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            res.json(results);
        });
    },

    // Get client by ID
    getById: (req, res) => {
        const clientId = req.params.id;
        Client.findById(clientId, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            if (results.length === 0) {
                return res.status(404).json({ message: 'Client not found' });
            }
            res.json(results[0]);
        });
    },

    // Get client with all ambulance requests
    getByIdWithRequests: (req, res) => {
        const clientId = req.params.id;
        Client.findByIdWithRequests(clientId, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            if (results.length === 0) {
                return res.status(404).json({ message: 'Client not found' });
            }
            
            const clientData = results[0];
            // Parse JSON requests if it's a string, otherwise use as is
            if (typeof clientData.requests === 'string') {
                try {
                    clientData.requests = JSON.parse(clientData.requests);
                } catch (e) {
                    clientData.requests = [];
                }
            }
            
            res.json(clientData);
        });
    },

    // Create new client
    create: (req, res) => {
        const {
            user_id,
            insurance_scheme_id,
            phone_number,
            is_cash_client,
            membership_number,
            suffix,
            address,
            date_of_birth,
            emergency_contact_name,
            emergency_contact_phone
        } = req.body;

        if (!user_id || !phone_number) {
            return res.status(400).json({ 
                error: 'User ID and phone number are required' 
            });
        }

        Client.create({
            user_id,
            insurance_scheme_id,
            phone_number,
            is_cash_client,
            membership_number,
            suffix,
            address,
            date_of_birth,
            emergency_contact_name,
            emergency_contact_phone
        }, (err, results) => {
            if (err) {
                if (err.code === 'ER_DUP_ENTRY') {
                    return res.status(400).json({ error: 'User already has a client record' });
                }
                if (err.code === 'ER_NO_REFERENCED_ROW_2') {
                    return res.status(400).json({ error: 'Invalid user ID or insurance scheme ID' });
                }
                return res.status(500).json({ error: err.message });
            }

            // Return created client with user data
            Client.findById(results.insertId, (err, newClient) => {
                if (err) {
                    return res.status(500).json({ error: err.message });
                }
                res.status(201).json({
                    message: 'Client created successfully',
                    client: newClient[0]
                });
            });
        });
    },

    // Update client
    update: (req, res) => {
        const clientId = req.params.id;
        const {
            insurance_scheme_id,
            phone_number,
            is_cash_client,
            membership_number,
            suffix,
            address,
            date_of_birth,
            emergency_contact_name,
            emergency_contact_phone
        } = req.body;

        // Check if client exists
        Client.findById(clientId, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            if (results.length === 0) {
                return res.status(404).json({ message: 'Client not found' });
            }

            Client.update(clientId, {
                insurance_scheme_id,
                phone_number,
                is_cash_client,
                membership_number,
                suffix,
                address,
                date_of_birth,
                emergency_contact_name,
                emergency_contact_phone
            }, (err, updateResults) => {
                if (err) {
                    if (err.code === 'ER_NO_REFERENCED_ROW_2') {
                        return res.status(400).json({ error: 'Invalid insurance scheme ID' });
                    }
                    return res.status(500).json({ error: err.message });
                }

                // Return updated client data
                Client.findById(clientId, (err, updatedClient) => {
                    if (err) {
                        return res.status(500).json({ error: err.message });
                    }
                    res.json({
                        message: 'Client updated successfully',
                        client: updatedClient[0]
                    });
                });
            });
        });
    },

    // Delete client
    delete: (req, res) => {
        const clientId = req.params.id;
        
        // Check if client exists
        Client.findById(clientId, (err, results) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            if (results.length === 0) {
                return res.status(404).json({ message: 'Client not found' });
            }

            Client.delete(clientId, (err, deleteResults) => {
                if (err) {
                    return res.status(500).json({ error: err.message });
                }
                res.json({ message: 'Client deleted successfully' });
            });
        });
    },

    // Update client's own details (name, phone, emergency details only)
    updateMyDetails: (req, res) => {
        const userId = req.user.id; // From authenticated token
        const { 
            first_name, 
            last_name, 
            phone_number, 
            emergency_contact_name, 
            emergency_contact_phone 
        } = req.body;

        // Validate that at least one field is provided
        if (!first_name && !last_name && !phone_number && !emergency_contact_name && !emergency_contact_phone) {
            return res.status(400).json({ 
                error: 'At least one field must be provided for update' 
            });
        }

        // Find client by user_id
        Client.findByUserId(userId, (err, clientResults) => {
            if (err) {
                return res.status(500).json({ error: err.message });
            }
            if (clientResults.length === 0) {
                return res.status(404).json({ error: 'Client record not found' });
            }

            const client = clientResults[0];
            const clientId = client.id;

            // Prepare updates for user table (name and phone)
            const userUpdates = {};
            if (first_name !== undefined) userUpdates.first_name = first_name;
            if (last_name !== undefined) userUpdates.last_name = last_name;
            if (phone_number !== undefined) userUpdates.phone_number = phone_number;

            // Prepare updates for client table (phone and emergency details)
            const clientUpdates = {};
            if (phone_number !== undefined) clientUpdates.phone_number = phone_number;
            if (emergency_contact_name !== undefined) clientUpdates.emergency_contact_name = emergency_contact_name;
            if (emergency_contact_phone !== undefined) clientUpdates.emergency_contact_phone = emergency_contact_phone;

            // Update user table if there are user updates
            const updatePromises = [];
            
            if (Object.keys(userUpdates).length > 0) {
                updatePromises.push(new Promise((resolve, reject) => {
                    const User = require('../models/User');
                    User.update(userId, userUpdates, (err, results) => {
                        if (err) reject(err);
                        else resolve(results);
                    });
                }));
            }

            // Update client table if there are client updates
            if (Object.keys(clientUpdates).length > 0) {
                updatePromises.push(new Promise((resolve, reject) => {
                    Client.update(clientId, clientUpdates, (err, results) => {
                        if (err) reject(err);
                        else resolve(results);
                    });
                }));
            }

            // Execute all updates
            Promise.all(updatePromises)
                .then(() => {
                    // Fetch updated client data with user info
                    Client.findById(clientId, (err, updatedResults) => {
                        if (err) {
                            return res.status(500).json({ error: err.message });
                        }
                        res.status(200).json({
                            message: 'Client details updated successfully',
                            client: updatedResults[0]
                        });
                    });
                })
                .catch((error) => {
                    console.error('Error updating client details:', error);
                    return res.status(500).json({ error: error.message || 'Failed to update client details' });
                });
        });
    },

    // Create new client by admin (creates user and client in one request)
    createByAdmin: (req, res) => {
        const {
            // User fields
            first_name,
            last_name,
            email,
            phone_number,
            // Client fields
            insurance_scheme_id,
            is_cash_client,
            membership_number,
            suffix,
            address,
            date_of_birth,
            emergency_contact_name,
            emergency_contact_phone
        } = req.body;

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

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

                proceedWithUserCreation();
            });
        } else {
            proceedWithUserCreation();
        }

        function proceedWithUserCreation() {
            // Only generate password if email is provided (user will be loggable)
            let defaultPassword = null;
            let hashedPassword = null;

            if (email) {
                // Generate default password: first_name + last_name + 2026
                // Remove spaces and convert to lowercase for consistency
                defaultPassword = `${first_name}${last_name}2026`.replace(/\s+/g, '').toLowerCase();

                // Hash the password
                bcrypt.hash(defaultPassword, 10, (err, hash) => {
                    if (err) {
                        return res.status(500).json({ error: 'Error hashing password' });
                    }
                    hashedPassword = hash;
                    createUserAndClient(hashedPassword, defaultPassword);
                });
            } else {
                // Create user without password (non-loggable)
                createUserAndClient(null, null);
            }
        }

        function createUserAndClient(hashedPassword, defaultPassword) {
            // Create user with role 'client' and is_verified = true
            User.create({
                first_name,
                last_name,
                email: email || null,
                phone_number,
                password: hashedPassword,
                role: 'client',
                otp: null,
                is_verified: true  // Auto-verify admin-created clients
            }, (err, userResults) => {
                if (err) {
                    if (err.code === 'ER_DUP_ENTRY') {
                        return res.status(400).json({ error: 'Email already exists' });
                    }
                    return res.status(500).json({ error: err.message });
                }

                const userId = userResults.insertId;

                // If no insurance scheme is provided, client must be a cash client
                const isCashClient = insurance_scheme_id ? (is_cash_client || false) : true;

                // Create client record
                Client.create({
                    user_id: userId,
                    insurance_scheme_id: insurance_scheme_id || null,
                    phone_number,
                    is_cash_client: isCashClient,
                    membership_number,
                    suffix,
                    address,
                    date_of_birth,
                    emergency_contact_name,
                    emergency_contact_phone
                }, (err, clientResults) => {
                    if (err) {
                        // Rollback: delete user if client creation fails
                        User.delete(userId, () => {});
                        if (err.code === 'ER_DUP_ENTRY') {
                            return res.status(400).json({ error: 'User already has a client record' });
                        }
                        if (err.code === 'ER_NO_REFERENCED_ROW_2') {
                            return res.status(400).json({ error: 'Invalid insurance scheme ID' });
                        }
                        return res.status(500).json({ error: err.message });
                    }

                    // Return created client with user data
                    Client.findById(clientResults.insertId, (err, newClient) => {
                        if (err) {
                            return res.status(500).json({ error: err.message });
                        }
                        const response = {
                            message: 'Client created successfully by admin',
                            client: newClient[0]
                        };
                        
                        // Only include password if one was generated
                        if (defaultPassword) {
                            response.default_password = defaultPassword;
                        }
                        
                        res.status(201).json(response);
                    });
                });
            });
        }
    }
};

module.exports = clientController;

