<?php
namespace Core\Services;
use Core\Database;

class GamificationEngine {
    private static $instance = null;
    private $db;

    private $eventXp = [
        'task_completed' => 10,
        'habit_done' => 5,
        'fast_completed' => 15,
        'finance_logged' => 5
    ];

    private function __construct() {
        $this->db = Database::getInstance();
    }

    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new GamificationEngine();
        }
        return self::$instance;
    }

    private function calculateLevel($xp) {
        return max(1, floor($xp / 100) + 1);
    }
    
    public function getTargetXpForLevel($level) {
        return ($level) * 100;
    }

    public function getProfile($userId) {
        $profile = $this->db->query("SELECT * FROM user_xp WHERE user_id = ?", [$userId])->fetch();
        if (!$profile) {
            $this->db->query("INSERT IGNORE INTO user_xp (user_id, xp_points, level, last_gain_at) VALUES (?, 0, 1, NOW())", [$userId]);
            $profile = (object)['xp_points' => 0, 'level' => 1];
        }
        
        $xp = (int)$profile->xp_points;
        $currentLevel = $this->calculateLevel($xp);
        
        // Sync level if disjointed
        if ($currentLevel != $profile->level) {
            $this->db->query("UPDATE user_xp SET level = ? WHERE user_id = ?", [$currentLevel, $userId]);
        }

        $nextXp = $this->getTargetXpForLevel($currentLevel);
        $prevXp = $this->getTargetXpForLevel($currentLevel - 1);
        $progress = 0;
        if ($nextXp > $prevXp) {
            $progress = (($xp - $prevXp) / ($nextXp - $prevXp)) * 100;
        }

        // Add standard RPG Titles based on Level
        $titles = [1=>'المبتدئ',2=>'المتدرب',3=>'الساعي',4=>'المنضبط',5=>'المحارب',6=>'الفارس',7=>'المعمار',8=>'المخضرم',9=>'الخبير',10=>'الأسطورة'];
        $title = $titles[min($currentLevel, 10)] ?? 'الأسطورة';

        return [
            'xp' => $xp,
            'level' => $currentLevel,
            'title' => $title,
            'next_xp' => $nextXp,
            'prev_xp' => $prevXp,
            'progress_pct' => min(100, max(0, $progress))
        ];
    }

    public function onEvent($eventType, $userId) {
        if (!isset($this->eventXp[$eventType])) return false;
        
        $xpGain = $this->eventXp[$eventType];
        
        // Check Smart Engine Multiplier
        require_once __DIR__ . '/UserProfileEngine.php';
        $intelligence = \Core\Services\UserProfileEngine::getInstance()->getIntelligence($userId);
        $multiplier = $intelligence['decisions']['xp_multiplier'] ?? 1.0;
        $xpGain = (int)($xpGain * $multiplier);
        $profile = $this->getProfile($userId);
        
        $oldLevel = $profile['level'];
        $newXp = $profile['xp'] + $xpGain;
        $newLevel = $this->calculateLevel($newXp);
        
        $this->db->query("UPDATE user_xp SET xp_points = ?, level = ?, last_gain_at = NOW() WHERE user_id = ?", [$newXp, $newLevel, $userId]);
        
        // Fire generic toast for XP
        $this->flashToast("✨ +{$xpGain} XP نقطة خبرة!", "success");

        if ($newLevel > $oldLevel) {
            $titles = [1=>'المبتدئ',2=>'المتدرب',3=>'الساعي',4=>'المنضبط',5=>'المحارب',6=>'الفارس',7=>'المعمار',8=>'المخضرم',9=>'الخبير',10=>'الأسطورة'];
            $newTitle = $titles[min($newLevel, 10)] ?? 'الأسطورة';
            $this->flashToast("🎉 مستوى جديد! لقد ارتقيت إلى المستوى $newLevel ($newTitle)!", "primary");
        }

        $this->checkBadges($userId, $eventType);
        return true;
    }

    /**
     * @deprecated Legacy bridge to maintain 100% zero breakage for old system calls.
     */
    public function awardXp($userId, $amount, $reason = '') {
        // Soft fallback: silently map to unspecific event or do nothing so system won't crash
        return true;
    }

    private function checkBadges($userId, $eventType) {
        // Fetch specific event badges that user doesn't have yet
        $badges = $this->db->query(
            "SELECT b.* FROM badges b 
             LEFT JOIN user_badges ub ON b.id = ub.badge_id AND ub.user_id = ?
             WHERE ub.badge_id IS NULL AND b.condition_type = ?",
            [$userId, $eventType]
        )->fetchAll();

        if (empty($badges)) return;

        // Condition evaluation
        foreach ($badges as $badge) {
            $met = false;
            
            if ($badge->condition_type == 'task_completed') {
                $count = $this->db->query("SELECT COUNT(*) FROM todo_tasks WHERE user_id = ? AND status = 'completed'", [$userId])->fetchColumn();
                $met = ($count >= $badge->condition_value);
            } 
            elseif ($badge->condition_type == 'habit_done') {
                // Total habit completions approx. For accurate streak we'd check logs
                $count = $this->db->query("SELECT COUNT(*) FROM habit_logs WHERE habit_id IN (SELECT id FROM habits WHERE user_id = ?) AND status='done'", [$userId])->fetchColumn();
                $met = ($count >= $badge->condition_value);
            }
            elseif ($badge->condition_type == 'finance_logged') {
                // Sum of expense rows
                $count = $this->db->query("SELECT COUNT(*) FROM finance_expenses WHERE user_id = ?", [$userId])->fetchColumn();
                $met = ($count >= $badge->condition_value);
            }
            elseif ($badge->condition_type == 'fast_completed') {
                $count = $this->db->query("SELECT COUNT(*) FROM health_fasts WHERE user_id = ? AND status = 'completed'", [$userId])->fetchColumn();
                $met = ($count >= $badge->condition_value);
            }

            if ($met) {
                // Award Badge
                $this->db->query("INSERT IGNORE INTO user_badges (user_id, badge_id, earned_at) VALUES (?, ?, NOW())", [$userId, $badge->id]);
                // Toast
                $this->flashToast("🔥 حصلت على وسام جديد: {$badge->name}!", "warning");
            }
        }
    }

    public function getUserBadges($userId) {
        return $this->db->query("
            SELECT b.*, ub.earned_at 
            FROM badges b
            LEFT JOIN user_badges ub ON b.id = ub.badge_id AND ub.user_id = ?
            ORDER BY ub.earned_at IS NULL, ub.earned_at DESC
        ", [$userId])->fetchAll();
    }

    private function flashToast($msg, $type) {
        if (session_status() === PHP_SESSION_NONE) session_start();
        $_SESSION['flash_messages'][] = [
            'type' => $type,
            'message' => $msg
        ];
    }
}
