import bcrypt from 'bcrypt';
import { User, Settings } from '../models/index.js';

const getUploadPath = (file) => file ? `/uploads/${file.filename}` : null;

const buildUserPayload = (user) => ({
    id: user.id,
    name: user.name,
    email: user.email,
    password: user.password,
    role: user.role,
    status: user.status,
    avatar: user.avatar,
    permissions: user.permissions,
});

const getOrCreateSettings = async (userId) => {
    let settings = await Settings.findOne();

    if (!settings) {
        const user = await User.findByPk(userId);
        settings = await Settings.create({
            name: user?.name || 'Admin',
            email: user?.email || `settings-${userId}@deytal.local`,
            phone: '+91 00000 00000',
            password: user?.password || 'settings',
            role: user?.role || 'admin'
        });
    }

    return settings;
};

export const getProfileSettings = async (req, res) => {
    try {
        const user = await User.findByPk(req.user.id);

        if (!user) {
            return res.status(404).json({
                success: false,
                message: 'User not found',
            });
        }

        return res.status(200).json({
            success: true,
            message: 'Profile settings retrieved successfully',
            user: buildUserPayload(user),
        });

    } catch (error) {
        return res.status(500).json({
            success: false,
            message: 'Failed to retrieve profile settings',
            error: error.message,
        });
    }
};

export const updateProfileSettings = async (req, res) => {
    try {
        const user = await User.findByPk(req.user.id);

        if (!user) {
            return res.status(404).json({
                success: false,
                message: 'User not found',
            });
        }

        const normalizedName = typeof req.body.name === 'string' ? req.body.name.trim() : '';
        const normalizedEmail = typeof req.body.email === 'string' ? req.body.email.trim().toLowerCase() : '';
        const rawPassword = typeof req.body.password === 'string' ? req.body.password.trim() : '';
        const avatar = getUploadPath(req.file);

        const hasNameChange = normalizedName !== '' && normalizedName !== user.name;
        const hasEmailChange = normalizedEmail !== '' && normalizedEmail !== user.email;
        const hasPasswordChange = rawPassword !== '';

        if (!hasNameChange && !hasEmailChange && !hasPasswordChange && !avatar) {
            return res.status(200).json({
                success: true,
                message: 'No changes detected. Profile settings are already the same',
                user: buildUserPayload(user),
            });
        }

        if (hasEmailChange) {
            const existing = await User.findOne({ where: { email: normalizedEmail } });
            if (existing) {
                return res.status(409).json({
                    success: false,
                    message: 'A user with this email already exists',
                });
            }
        }

        const updateData = {};

        if (hasNameChange) updateData.name = normalizedName;
        if (hasEmailChange) updateData.email = normalizedEmail;
        if (hasPasswordChange) updateData.password = await bcrypt.hash(rawPassword, 10);
        if (avatar) {
            if (user.avatar) {
                try {
                    const fs = await import('fs');
                    const path = await import('path');
                    const oldAvatarPath = path.join(process.cwd(), user.avatar);

                    if (fs.existsSync(oldAvatarPath)) {
                        fs.unlinkSync(oldAvatarPath);
                    }
                } catch (err) {
                    console.log('Could not delete old avatar file');
                }
            }

            updateData.avatar = avatar;
        }

        await user.update(updateData);
        await user.reload();

        return res.status(200).json({
            success: true,
            message: 'Profile settings updated successfully',
            user: buildUserPayload(user),
        });

    } catch (error) {
        return res.status(500).json({
            success: false,
            message: 'Failed to update profile settings',
            error: error.message,
        });
    }
};

export const updateCompanySettings = async (req, res) => {
    try {
        const {
            company_name,
            tax_id,
            company_address,
            currency
        } = req.body;
        const logoFile = req.file;

        const normalizedCompanyName = company_name?.trim();
        const normalizedTaxId = tax_id?.trim();
        const normalizedAddress = company_address?.trim();
        const normalizedCurrency = currency?.trim();

        // Allow partial updates, but require at least one field or a logo.
        if (!normalizedCompanyName && !normalizedTaxId && !normalizedAddress && !normalizedCurrency && !logoFile) {
            return res.status(400).json({
                success: false,
                message: 'Please provide at least one company setting to update',
            });
        }

        if (normalizedCompanyName !== undefined && normalizedCompanyName !== '' && normalizedCompanyName.length < 2) {
            return res.status(400).json({
                success: false,
                message: 'Company name must be at least 2 characters',
            });
        }

        if (normalizedTaxId !== undefined && normalizedTaxId !== '' && normalizedTaxId.length < 3) {
            return res.status(400).json({
                success: false,
                message: 'Tax ID/VAT number must be at least 3 characters',
            });
        }

        if (normalizedAddress !== undefined && normalizedAddress !== '' && normalizedAddress.length < 5) {
            return res.status(400).json({
                success: false,
                message: 'Address must be at least 5 characters',
            });
        }

        // Find or create company settings (assuming single company record)
        let settings = await Settings.findOne();

        if (!settings) {
            const user = await User.findByPk(req.user.id);

            settings = await Settings.create({
                name: user?.name || 'Admin',
                email: user?.email || `settings-${req.user.id}@deytal.local`,
                phone: '+91 00000 00000',
                password: user?.password || 'settings',
                role: user?.role || 'admin',
                company_name: normalizedCompanyName || null,
                tax_id: normalizedTaxId || null,
                company_address: normalizedAddress || null,
                currency: normalizedCurrency || null,
                company_logo: getUploadPath(logoFile),
            });

            return res.status(201).json({
                success: true,
                message: 'Company settings created successfully',
                data: {
                    id: settings.id,
                    company_name: settings.company_name,
                    tax_id: settings.tax_id,
                    company_address: settings.company_address,
                    currency: settings.currency,
                    company_logo: settings.company_logo,
                }
            });
        }

        // Check if data is same as existing
        if (
            (normalizedCompanyName === undefined || normalizedCompanyName === settings.company_name) &&
            (normalizedTaxId === undefined || normalizedTaxId === settings.tax_id) &&
            (normalizedAddress === undefined || normalizedAddress === settings.company_address) &&
            (normalizedCurrency === undefined || normalizedCurrency === settings.currency) &&
            !logoFile
        ) {
            return res.status(200).json({
                success: true,
                message: 'No changes detected. Company settings are already the same',
                data: {
                    id: settings.id,
                    company_name: settings.company_name,
                    tax_id: settings.tax_id,
                    company_address: settings.company_address,
                    currency: settings.currency,
                    company_logo: settings.company_logo,
                }
            });
        }

        // Update settings
        const updateData = {};

        if (normalizedCompanyName !== undefined) updateData.company_name = normalizedCompanyName || null;
        if (normalizedTaxId !== undefined) updateData.tax_id = normalizedTaxId || null;
        if (normalizedAddress !== undefined) updateData.company_address = normalizedAddress || null;
        if (normalizedCurrency !== undefined) updateData.currency = normalizedCurrency || null;

        if (logoFile) {
            // Delete old logo if exists
            if (settings.company_logo) {
                try {
                    const fs = await import('fs');
                    const path = await import('path');
                    const oldLogoPath = path.join(process.cwd(), settings.company_logo);

                    if (fs.existsSync(oldLogoPath)) {
                        fs.unlinkSync(oldLogoPath);
                    }
                } catch (err) {
                    console.log('Could not delete old logo file');
                }
            }
            updateData.company_logo = getUploadPath(logoFile);
        }

        await settings.update(updateData);

        return res.status(200).json({
            success: true,
            message: 'Company settings updated successfully',
            data: {
                id: settings.id,
                company_name: settings.company_name,
                tax_id: settings.tax_id,
                company_address: settings.company_address,
                currency: settings.currency,
                company_logo: settings.company_logo,
            }
        });

    } catch (error) {
        return res.status(500).json({
            success: false,
            message: 'Failed to update company settings',
            error: error.message,
        });
    }
};

export const getCompanySettings = async (req, res) => {
    try {
        const settings = await Settings.findOne();

        if (!settings) {
            return res.status(404).json({
                success: false,
                message: 'Company settings not found',
            });
        }

        return res.status(200).json({
            success: true,
            message: 'Company settings retrieved successfully',
            data: {
                id: settings.id,
                company_name: settings.company_name,
                tax_id: settings.tax_id,
                company_address: settings.company_address,
                currency: settings.currency,
                company_logo: settings.company_logo,
            }
        });

    } catch (error) {
        return res.status(500).json({
            success: false,
            message: 'Failed to retrieve company settings',
            error: error.message,
        });
    }
};

export const getMailSettings = async (req, res) => {
    try {
        const settings = await getOrCreateSettings(req.user.id);

        return res.status(200).json({
            success: true,
            message: 'Mail settings retrieved successfully',
            data: {
                id: settings.id,
                smtp_host: settings.smtp_host || '',
                smtp_port: settings.smtp_port || 465,
                smtp_user: settings.smtp_user || '',
                smtp_pass: settings.smtp_pass || '',
                smtp_secure: settings.smtp_secure !== false,
                smtp_from_email: settings.smtp_from_email || '',
                smtp_from_name: settings.smtp_from_name || ''
            }
        });
    } catch (error) {
        return res.status(500).json({
            success: false,
            message: 'Failed to retrieve mail settings',
            error: error.message,
        });
    }
};

export const updateMailSettings = async (req, res) => {
    try {
        const {
            smtp_host,
            smtp_port,
            smtp_user,
            smtp_pass,
            smtp_secure,
            smtp_from_email,
            smtp_from_name
        } = req.body;

        if (!smtp_user || !smtp_pass) {
            return res.status(400).json({
                success: false,
                message: 'Please provide smtp_user and smtp_pass'
            });
        }

        const settings = await getOrCreateSettings(req.user.id);

        await settings.update({
            smtp_host: smtp_host?.trim() || settings.smtp_host || null,
            smtp_port: smtp_port ? Number(smtp_port) : settings.smtp_port || 465,
            smtp_user: smtp_user.trim(),
            smtp_pass: smtp_pass,
            smtp_secure: smtp_secure === undefined ? (settings.smtp_secure !== false) : (smtp_secure === true || smtp_secure === 'true'),
            smtp_from_email: smtp_from_email?.trim() || smtp_user.trim(),
            smtp_from_name: smtp_from_name ? smtp_from_name.trim() : (settings.smtp_from_name || '')
        });

        return res.status(200).json({
            success: true,
            message: 'Mail settings updated successfully',
            data: {
                id: settings.id,
                smtp_host: settings.smtp_host,
                smtp_port: settings.smtp_port,
                smtp_user: settings.smtp_user,
                smtp_secure: settings.smtp_secure,
                smtp_from_email: settings.smtp_from_email,
                smtp_from_name: settings.smtp_from_name
            }
        });
    } catch (error) {
        return res.status(500).json({
            success: false,
            message: 'Failed to update mail settings',
            error: error.message,
        });
    }
};

export const createTitle = async (req, res) => {
    try {
        const { title } = req.body;
        const settings = await getOrCreateSettings(req.user.id);
        const normalized = typeof title === 'string' ? title.trim() : '';
        await settings.update({ title: normalized || null });
        return res.status(200).json({
            success: true,
            message: 'Title updated successfully',
            data: {
                id: settings.id,
                title: settings.title
            }
        });
    } catch (error) {
        return res.status(500).json({
            success: false,
            message: 'Failed to update title',
            error: error.message,
        });
    }
};
// get title
export const getTitle = async (req, res) => {
    try {
        const settings = await getOrCreateSettings(req.user.id);
        return res.status(200).json({
            success: true,
            message: 'Title retrieved successfully',
            data: {
                id: settings.id,    
            title: settings.title
            }
        });
    }
    catch (error) {
        return res.status(500).json({
            success: false,
            message: 'Failed to retrieve title',
            error: error.message,
        });
    }
}