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

class FinanceAnalysisService {
    private $db;

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

    public function analyze($userId, $days = 30) {
        if ($days === 'current_month') {
            $startDate = date('Y-m-01');
            $daysCalc = date('d');
        } else {
            $startDate = date('Y-m-d', strtotime("-$days days"));
            $daysCalc = $days;
        }
        
        $metrics = $this->getMetrics($userId, $startDate, $daysCalc);
        $categories = $this->getCategoryBreakdown($userId, $startDate);
        $budgets = $this->getBudgets($userId);
        $anomalies = $this->detectAnomalies($userId, $metrics['daily_average'], $startDate);
        
        $behavior = $this->detectBehavior($userId, $startDate, $metrics['total_expenses']);
        $goals = $this->getGoalsTracking($userId, $metrics['savings_rate'], $metrics['surplus']);
        
        // New Intelligence Engines
        $pressureScore = $this->getFinancialPressureScore($userId, $metrics, $budgets, $anomalies, $startDate);
        $cashFlow = $this->getCashFlow($userId);
        
        $insights = $this->generateInsights($metrics, $categories, $anomalies, $budgets, $behavior, $goals, $pressureScore);
        
        $timeline = $this->getUnifiedTimelineData($userId, $startDate);

        return [
            'metrics' => $metrics,
            'categories' => $categories,
            'budgets' => $budgets,
            'anomalies' => $anomalies,
            'behavior' => $behavior,
            'goals' => $goals,
            'insights' => $insights,
            'timeline' => $timeline,
            'pressure_score' => $pressureScore,
            'cash_flow' => $cashFlow,
            'days' => $days
        ];
    }

    private function getMetrics($userId, $startDate, $days) {
        $income = (float) $this->db->query("SELECT SUM(amount) FROM finance_incomes WHERE user_id = ? AND date_received >= ? AND deleted_at IS NULL", [$userId, $startDate])->fetchColumn() ?: 0;
        $expenses = (float) $this->db->query("SELECT SUM(amount) FROM finance_expenses WHERE user_id = ? AND expense_date >= ? AND deleted_at IS NULL", [$userId, $startDate])->fetchColumn() ?: 0;
        
        $surplus = $income - $expenses;
        $savingsRate = ($income > 0) ? ($surplus / $income) * 100 : 0;
        
        $status = 'normal';
        if ($surplus < 0) $status = 'risky';
        elseif ($savingsRate > 20) $status = 'good';

        return [
            'total_income' => $income,
            'total_expenses' => $expenses,
            'surplus' => $surplus,
            'savings_rate' => round($savingsRate, 1),
            'status' => $status,
            'daily_average' => $days > 0 ? round($expenses / $days, 2) : $expenses
        ];
    }

    private function getCategoryBreakdown($userId, $startDate) {
        $sql = "SELECT category as name, SUM(amount) as total 
                FROM finance_expenses 
                WHERE user_id = ? AND expense_date >= ? AND deleted_at IS NULL 
                GROUP BY category 
                ORDER BY total DESC";
        return $this->db->query($sql, [$userId, $startDate])->fetchAll(PDO::FETCH_ASSOC);
    }

    private function getUnifiedTimelineData($userId, $startDate) {
        // Unify incomes and expenses for a single cashflow timeline
        $sql = "
            SELECT expense_date as date, SUM(amount) as outflow, 0 as inflow
            FROM finance_expenses 
            WHERE user_id = ? AND expense_date >= ? AND deleted_at IS NULL 
            GROUP BY expense_date
            UNION
            SELECT date_received as date, 0 as outflow, SUM(amount) as inflow
            FROM finance_incomes 
            WHERE user_id = ? AND date_received >= ? AND deleted_at IS NULL 
            GROUP BY date_received
            ORDER BY date ASC
        ";
        
        $raw = $this->db->query($sql, [$userId, $startDate, $userId, $startDate])->fetchAll(PDO::FETCH_ASSOC);
        
        $merged = [];
        foreach($raw as $r) {
            $d = $r['date'];
            if(!isset($merged[$d])) {
                $merged[$d] = ['date' => $d, 'inflow' => 0, 'outflow' => 0];
            }
            $merged[$d]['inflow'] += (float)$r['inflow'];
            $merged[$d]['outflow'] += (float)$r['outflow'];
        }
        ksort($merged);
        return array_values($merged);
    }

    private function getBudgets($userId) {
        $startOfMonth = date('Y-m-01');
        $endOfMonth = date('Y-m-t');

        $cats = $this->db->query("SELECT * FROM fin_categories WHERE user_id = ? AND type = 'expense' AND monthly_budget IS NOT NULL AND monthly_budget > 0 AND deleted_at IS NULL", [$userId])->fetchAll(PDO::FETCH_ASSOC);
        
        $budgetList = [];
        foreach($cats as $c) {
            $used = (float) $this->db->query("SELECT SUM(amount) FROM finance_expenses WHERE user_id = ? AND category = ? AND expense_date BETWEEN ? AND ? AND deleted_at IS NULL", [$userId, $c['name'], $startOfMonth, $endOfMonth])->fetchColumn() ?: 0;
            
            $limit = (float) $c['monthly_budget'];
            $pct = min(100, round(($used / $limit) * 100));
            $rem = max(0, $limit - $used);
            
            $status = 'success';
            if ($pct >= 100) $status = 'danger';
            elseif ($pct > 75) $status = 'warning';

            $budgetList[] = [
                'category' => $c['name'],
                'limit' => $limit,
                'used' => $used,
                'remaining' => $rem,
                'percent' => $pct,
                'status' => $status
            ];
        }
        return $budgetList;
    }

    private function detectAnomalies($userId, $dailyAverage, $startDate) {
        if ($dailyAverage <= 0) return [];
        $threshold = $dailyAverage * 3;
        
        $sql = "SELECT * FROM finance_expenses 
                WHERE user_id = ? AND expense_date >= ? AND amount > ? AND deleted_at IS NULL 
                ORDER BY expense_date DESC LIMIT 5";
        
        return $this->db->query($sql, [$userId, $startDate, $threshold])->fetchAll(PDO::FETCH_ASSOC);
    }

    private function detectBehavior($userId, $startDate, $totalExpenses) {
        $behavior = [];
        if ($totalExpenses <= 0) return $behavior;

        $freqCat = $this->db->query("SELECT category as name, COUNT(id) as freq FROM finance_expenses WHERE user_id = ? AND expense_date >= ? AND deleted_at IS NULL GROUP BY category ORDER BY freq DESC LIMIT 1", [$userId, $startDate])->fetch(PDO::FETCH_ASSOC);
        if ($freqCat) {
            $behavior['frequent_category'] = $freqCat;
        }

        $valCat = $this->db->query("SELECT category as name, SUM(amount) as total FROM finance_expenses WHERE user_id = ? AND expense_date >= ? AND deleted_at IS NULL GROUP BY category ORDER BY total DESC LIMIT 1", [$userId, $startDate])->fetch(PDO::FETCH_ASSOC);
        if ($valCat) {
            $behavior['highest_category'] = $valCat;
        }

        $endOfMonthExpenses = (float) $this->db->query("SELECT SUM(amount) FROM finance_expenses WHERE user_id = ? AND expense_date >= ? AND DAY(expense_date) >= 24 AND deleted_at IS NULL", [$userId, $startDate])->fetchColumn() ?: 0;
        
        $ratio = $endOfMonthExpenses / $totalExpenses;
        $behavior['end_of_month_spike'] = ($ratio > 0.4);

        // Analyze from journal to find emotional/impulsive spending
        // Check if there are days where mood was < 5 and expenses were high
        $triggerDays = false;
        try {
            $triggerDays = $this->db->query("
                SELECT j.entry_date, j.mood_score, SUM(f.amount) as total_spent
                FROM journal_entries j
                JOIN finance_expenses f ON DATE(j.entry_date) = f.expense_date AND f.user_id = j.user_id
                WHERE j.user_id = ? AND j.mood_score <= 4 AND f.deleted_at IS NULL AND j.deleted_at IS NULL
                GROUP BY j.entry_date
                HAVING total_spent > 0
                ORDER BY total_spent DESC
                LIMIT 1
            ", [$userId])->fetch(PDO::FETCH_ASSOC);
        } catch (\PDOException $e) {
            // Journal table might not exist yet; safely ignore
            $triggerDays = false;
        }

        $behavior['emotional_spending'] = $triggerDays ? true : false;
        if($triggerDays) {
            $behavior['emotional_spending_details'] = $triggerDays;
            
            // Mark those expenses as impulsive if not already
            try {
                $this->db->query("UPDATE finance_expenses SET is_impulsive = 1 WHERE user_id = ? AND expense_date = ? AND amount > 0", [$userId, $triggerDays['entry_date']]);
            } catch (\PDOException $e) {
                // Ignore if field doesn't exist
            }
        }

        return $behavior;
    }

    private function getGoalsTracking($userId, $savingsRate, $surplus) {
        $goalsQuery = "SELECT * FROM finance_saving_goals WHERE user_id = ? AND current_amount < target_amount AND deleted_at IS NULL ORDER BY expected_date ASC";
        $goals = $this->db->query($goalsQuery, [$userId])->fetchAll(PDO::FETCH_ASSOC);

        $trackedGoals = [];
        $today = new \DateTime();

        foreach ($goals as $goal) {
            $target = (float) $goal['target_amount'];
            $current = (float) $goal['current_amount'];
            $deadlineStr = $goal['expected_date'];
            
            $remDays = 30; // default if no deadline
            $deadline = null;

            if ($deadlineStr) {
                $deadline = new \DateTime($deadlineStr);
                if ($deadline <= $today) {
                    $remDays = 1;
                } else {
                    $remDays = $today->diff($deadline)->days;
                }
            }

            $remMonths = max(1, $remDays / 30);
            $requiredMonthly = ($target - $current) / $remMonths;
            $percent = min(100, ($current / $target) * 100);

            $urgency = 'safe';
            $urgencyColor = 'success';
            if ($remDays <= 30) {
                $urgency = 'urgent';
                $urgencyColor = 'danger';
            } elseif ($remDays <= 90) {
                $urgency = 'normal';
                $urgencyColor = 'warning';
            }

            $onTrack = ($surplus >= $requiredMonthly);

            $trackedGoals[] = [
                'id' => $goal['id'],
                'title' => $goal['title'],
                'target' => $target,
                'current' => $current,
                'percent' => round($percent, 1),
                'deadline' => $deadlineStr,
                'remaining_days' => $remDays,
                'required_monthly' => $requiredMonthly,
                'urgency' => $urgency,
                'urgency_color' => $urgencyColor,
                'on_track' => $onTrack
            ];
        }
        return $trackedGoals;
    }

    private function getCashFlow($userId) {
        $todayStr = date('Y-m-d');
        $weekStart = date('Y-m-d', strtotime('last sunday'));
        $monthStart = date('Y-m-01');

        $getFlow = function($start) use ($userId, $todayStr) {
            $in = (float) $this->db->query("SELECT SUM(amount) FROM finance_incomes WHERE user_id = ? AND date_received >= ? AND date_received <= ? AND deleted_at IS NULL", [$userId, $start, $todayStr])->fetchColumn() ?: 0;
            $out = (float) $this->db->query("SELECT SUM(amount) FROM finance_expenses WHERE user_id = ? AND expense_date >= ? AND expense_date <= ? AND deleted_at IS NULL", [$userId, $start, $todayStr])->fetchColumn() ?: 0;
            return ['in' => $in, 'out' => $out, 'net' => $in - $out];
        };

        return [
            'today' => $getFlow($todayStr),
            'week' => $getFlow($weekStart),
            'month' => $getFlow($monthStart),
        ];
    }

    private function getFinancialPressureScore($userId, $metrics, $budgets, $anomalies, $startDate) {
        $score = 0;
        
        // Base metric risk
        if ($metrics['status'] === 'risky') $score += 30; // Deficit
        if ($metrics['surplus'] < 0) $score += 20;

        // Over budget penalties
        foreach($budgets as $b) {
            if ($b['percent'] >= 100) $score += 15;
            elseif ($b['percent'] >= 85) $score += 5;
        }

        // Anomalies penalty
        if (count($anomalies) > 0) $score += 10;

        // Upcoming debt pressure
        $upcomingDebts = $this->db->query("SELECT SUM(amount) - IFNULL((SELECT SUM(amount) FROM finance_debt_payments WHERE debt_id = finance_debts.id), 0) as remaining_debt FROM finance_debts WHERE user_id = ? AND type='owed' AND status='pending' AND due_date IS NOT NULL AND due_date BETWEEN CURDATE() AND DATE_ADD(CURDATE(), INTERVAL 14 DAY) AND deleted_at IS NULL", [$userId])->fetchColumn() ?: 0;
        
        if ($upcomingDebts > 0 && $metrics['surplus'] < $upcomingDebts) {
            $score += 25; // Critical: Upcoming debt larger than current surplus
        }

        // Cap to 100
        $score = min(100, $score);
        
        if ($score >= 70) {
            $level = 'high';
            $label = 'ضغط مالي مرتفع';
        } elseif ($score >= 40) {
            $level = 'medium';
            $label = 'ضغط مالي متوسط';
        } else {
            $level = 'low';
            $label = 'استقرار مالي';
        }

        return [
            'score' => $score,
            'level' => $level,
            'label' => $label,
            'can_spend' => ($score < 70) // Anti-impulse flag
        ];
    }

    private function generateInsights($metrics, $categories, $anomalies, $budgets, $behavior, $goals, $pressure) {
        $insights = [];

        if ($pressure['level'] === 'high') {
            $insights[] = [
                'type' => 'danger',
                'title' => 'تحذير توقف عن الصرف',
                'text' => 'مؤشر الضغط المالي لديك بلغ ' . $pressure['score'] . '%. النصحية الحالية هي تجميد جميع المصروفات الكمالية فوراً.'
            ];
        }

        if ($metrics['status'] === 'risky') {
            $insights[] = [
                'type' => 'danger',
                'title' => 'عجز مالي وانخفاض السيولة',
                'text' => 'مصروفاتك خلال هذه الفترة سجلت عجزاً واستهلكت أكثر مما دخل إليك.'
            ];
        } elseif ($metrics['status'] === 'good') {
            $insights[] = [
                'type' => 'success',
                'title' => 'أداء ادخار ممتاز',
                'text' => 'معدل ادخارك تجاوز 20%، وهو مؤشر رائع على الاستقرار المالي واستدامة الأرباح.'
            ];
        }

        if (!empty($categories) && $metrics['total_expenses'] > 0) {
            $topCat = $categories[0];
            $pct = round(($topCat['total'] / $metrics['total_expenses']) * 100);
            if ($pct >= 40) {
                $insights[] = [
                    'type' => 'warning',
                    'title' => 'سيطرة إنفاقية لفئة معينة',
                    'text' => "الإنفاق على [ {$topCat['name']} ] يمثل {$pct}% من إجمالي مصاريفك، راقب هذه الشريحة جيداً لتفعيل الترشيد."
                ];
            }
        }

        if (!empty($anomalies)) {
            $insights[] = [
                'type' => 'warning',
                'title' => 'مصروف غیر معتاد (طفرة)',
                'text' => 'تم رصد ' . count($anomalies) . ' مدفوعات ذات قيمة ضخمة وغير مألوفة مقارنة بمتوسطك المعتاد. يرجى المراجعة.'
            ];
        }

        foreach($budgets as $b) {
            if ($b['percent'] >= 100) {
                $insights[] = [
                    'type' => 'danger',
                    'title' => 'تجاوزت الميزانية: ' . htmlspecialchars($b['category']),
                    'text' => 'لقد استنفذت 100% من الميزانية المحددة لهذه الفئة. توقف عن الصرف هنا.'
                ];
            } elseif ($b['percent'] >= 85) {
                $insights[] = [
                    'type' => 'warning',
                    'title' => 'اقتراب نفاذ ميزانية ' . htmlspecialchars($b['category']),
                    'text' => 'متبقي ' . $b['remaining'] . ' فقط في هذه الميزانية، توخّ الحذر.'
                ];
            }
        }

        if (!empty($behavior['emotional_spending']) && $behavior['emotional_spending']) {
            $insights[] = [
                'type' => 'danger',
                'title' => 'إنفاق عاطفي / مندفع!',
                'text' => 'تم رصد مصروفات مرتفعة ارتبطت بأيام كان فيها تقييمك المزاجي منخفضاً (Journal). احذر من الشراء المندفع وقت الضغط.'
            ];
        }

        if (!empty($behavior['end_of_month_spike']) && $behavior['end_of_month_spike']) {
            $insights[] = [
                'type' => 'warning',
                'title' => 'متلازمة نهاية الشهر',
                'text' => 'تميل لزيادة الإنفاق بشكل كبير في نهاية الشهر، مما يشير لاندفاع إنفاقي يجب تقنينه.'
            ];
        }

        if (!empty($behavior['frequent_category'])) {
            $catName = htmlspecialchars($behavior['frequent_category']['name']);
            $insights[] = [
                'type' => 'info',
                'title' => 'أكثر تصنيف تكراراً',
                'text' => "بعيداً عن القيمة المالية، تكررت مشترياتك في [ {$catName} ] أكثر من أي شيء آخر."
            ];
        }

        foreach ($goals as $goal) {
            $goalTitle = htmlspecialchars($goal['title']);
            if (!$goal['on_track']) {
                $insights[] = [
                    'type' => 'danger',
                    'title' => "عائق نحو تحقيق هدف: {$goalTitle}",
                    'text' => "بمعدل تدفقاتك الحالية، لن تتمكن من توفير القسط المطلوب (".number_format($goal['required_monthly'])." ج.م/شهرياً) للوصول للهدف."
                ];
            } else {
                if ($goal['urgency'] === 'urgent') {
                    $insights[] = [
                        'type' => 'warning',
                        'title' => "تنبيه ملح: {$goalTitle}",
                        'text' => "اقترب موعد تحقيق الهدف جداً! متبقي ".$goal['remaining_days']." يوم، وأنت تسير بمعدل ادخار آمن للالتزام به."
                    ];
                }
            }
        }

        return $insights;
    }
}
