const db = require('../db');

/**
 * Service to handle badge awarding logic
 */
const badgeService = {
    /**
     * Award a badge to a user if they don't already have it
     * @param {number} userId 
     * @param {string} badgeName 
     * @returns {Promise<boolean>} true if badge was newly awarded, false otherwise
     */
    awardBadge: async (userId, badgeName, options = {}) => {
        try {
            // 1. Get badge details
            const badgeResult = await db.query('SELECT * FROM badges WHERE name = ?', [badgeName]);
            if (badgeResult.rows.length === 0) {
                console.warn(`Badge '${badgeName}' not found in database.`);
                return false;
            }
            const badge = badgeResult.rows[0];

            // 2. Check if user already has this badge (in user_badges table)
            let query = 'SELECT * FROM user_badges WHERE user_id = ? AND badge_id = ?';
            const params = [userId, badge.id];

            if (options && options.checkFrequency === 'monthly') {
                query += ' AND MONTH(awarded_at) = MONTH(NOW()) AND YEAR(awarded_at) = YEAR(NOW())';
            }

            const existing = await db.query(query, params);

            if (existing.rows.length > 0) {
                return false; // Already has badge (strictly or for this month)
            }

            // 3. Award badge in user_badges table
            await db.query(
                'INSERT INTO user_badges (user_id, badge_id, earned_at) VALUES (?, ?, NOW())',
                [userId, badge.id]
            );

            // 4. Sync to users.badges JSON column for frontend performance/compatibility
            // Fetch all current badges for user
            const allBadgesResult = await db.query(`
                SELECT b.id, b.name, b.icon_url, b.description, b.badge_type, b.xp_reward 
                FROM user_badges ub 
                JOIN badges b ON ub.badge_id = b.id 
                WHERE ub.user_id = ?
            `, [userId]);

            // Transform for frontend JSON
            const badgesForJson = allBadgesResult.rows.map(b => {
                // Map DB badge_type/xp to Frontend visual type (gold/silver/bronze)
                let visualType = 'bronze';
                if (b.xp_reward >= 500) visualType = 'gold';
                else if (b.xp_reward >= 100) visualType = 'silver';
                
                return {
                    id: b.id,
                    name: b.name,
                    icon: b.icon_url, // Map icon_url to icon
                    description: b.description,
                    type: visualType, // Use visual type
                    xp_reward: b.xp_reward
                };
            });

            const badgesJson = JSON.stringify(badgesForJson);
            await db.query('UPDATE users SET badges = ? WHERE id = ?', [badgesJson, userId]);

            // 5. Award XP (Optional: You might want to use xpService here if you want level ups)
            if (badge.xp_reward > 0) {
                 // Creating a circular dependency with xpService might be risky if xpService uses badgeService.
                 // Ideally, we import xpService here.
                 const xpService = require('../utils/xpService');
                 try {
                     await xpService.awardXP(userId, badge.xp_reward);
                 } catch (xpError) {
                     console.error('Failed to award XP for badge:', xpError);
                 }
            }

            console.log(`Awarded badge '${badgeName}' to user ${userId}`);
            return true;

        } catch (error) {
            console.error(`Error awarding badge '${badgeName}' to user ${userId}:`, error);
            return false;
        }
    },

    /**
     * Check constraints based on time of day (Legacy Badges)
     * Queries existing badges: Night Owl, Early Bird, Lunch Break Hacker, Day Walker
     * @param {number} userId 
     */
    checkActivityBadges: async (userId) => {
        const now = new Date();
        const hour = now.getHours();

        // Night Owl: 12 AM - 4 AM (00:00 - 04:00)
        if (hour >= 0 && hour < 4) {
            await badgeService.awardBadge(userId, 'Night Owl');
        }

        // Early Bird: 5 AM - 8 AM (05:00 - 08:00)
        if (hour >= 5 && hour < 8) {
            await badgeService.awardBadge(userId, 'Early Bird');
        }

        // Day Walker: 9 AM - 5 PM (09:00 - 17:00)
        if (hour >= 9 && hour < 17) {
            await badgeService.awardBadge(userId, 'Day Walker');
        }

        // Lunch Break Hacker: 12 PM - 1 PM (12:00 - 13:00)
        if (hour === 12) { // 12:00 - 12:59
            await badgeService.awardBadge(userId, 'Lunch Break Hacker');
        }
    },

    /**
     * Check for badges based on total investigation count
     * Removed "The Grinder" / "Elite" as per user request to use only old badges.
     * @param {number} userId 
     */
    /**
     * Check for badges based on total investigation count
     * Restored: The Grinder, Elite Investigator
     * @param {number} userId 
     */
    checkVolumeBadges: async (userId) => {
        try {
            const countResult = await db.query(
                'SELECT COUNT(*) as count FROM investigations WHERE user_id = ? AND status = ?',
                [userId, 'graded']
            );
            const count = parseInt(countResult.rows[0].count);

            if (count >= 50) {
                await badgeService.awardBadge(userId, 'The Grinder');
            }
             if (count >= 100) {
                await badgeService.awardBadge(userId, 'Elite Investigator');
            }
        } catch (error) {
            console.error('Error checking volume badges:', error);
        }
    },

    /**
     * Check for performance/special badges
     * Speed Demon: Under 10 mins
     * First Blood: First to solve an alert
     * @param {number} userId
     * @param {object} investigation
     */
    checkPerformanceBadges: async (userId, investigation) => {
        try {
            // Speed Demon: Created to Closed in < 10 mins
            const created = new Date(investigation.created_at);
            const now = new Date(); // roughly completion time
            const diffMs = now - created;
            const diffMins = diffMs / 1000 / 60;

            if (diffMins < 10) {
                await badgeService.awardBadge(userId, 'Speed Demon');
            }

            // First Blood: Check if this alert_id has ANY other graded investigations
            const existingSolves = await db.query(
                'SELECT COUNT(*) as count FROM investigations WHERE alert_id = ? AND status = ? AND id != ?',
                [investigation.alert_id, 'graded', investigation.id]
            );
            
            if (parseInt(existingSolves.rows[0].count) === 0) {
                 await badgeService.awardBadge(userId, 'First Blood');
            }

        } catch (error) {
            console.error('Error checking performance badges:', error);
        }
    }
};

module.exports = badgeService;
