<?php
namespace App\Modules\Spiritual\Models;

class SpiritualModel extends \Core\Model {
    protected $moduleName = 'Spiritual';
    // Spiritual entries are keyed by date, not a single ID.
    // Deletion is handled via deleteRecord($userId, $date) — base Model::delete() is not used.
    protected $useSoftDeletes = false;
    protected $logActions = false; // Minimal action logging for spiritual data

    public function __construct() {
        parent::__construct();
        $this->ensureSchemaUpdated();
    }

    private function ensureSchemaUpdated() {
        try { $this->query("ALTER TABLE spiritual_daily_logs ADD COLUMN final_status ENUM('perfect', 'partial', 'weak') DEFAULT NULL"); } catch (\Exception $e) {}
        try { $this->query("ALTER TABLE spiritual_daily_logs ADD COLUMN final_score INT DEFAULT NULL"); } catch (\Exception $e) {}
        try { $this->query("ALTER TABLE spiritual_daily_logs ADD COLUMN consistency_score INT DEFAULT 0"); } catch (\Exception $e) {}
        try { $this->query("ALTER TABLE spiritual_daily_logs ADD COLUMN spiritual_state ENUM('high', 'medium', 'low') DEFAULT 'medium'"); } catch (\Exception $e) {}
    }

    public function getDailyData($userId, $date) {
        // Run auto-finalization of past days
        $this->finalizePastDays($userId);

        // Ensure logs exist for tracking day
        $this->query("INSERT IGNORE INTO spiritual_daily_logs (user_id, date) VALUES (?, ?)", [$userId, $date]);
        $this->query("INSERT IGNORE INTO spiritual_prayers (user_id, date) VALUES (?, ?)", [$userId, $date]);
        $this->query("INSERT IGNORE INTO spiritual_adhkar (user_id, date) VALUES (?, ?)", [$userId, $date]);
        $this->query("INSERT IGNORE INTO spiritual_quran (user_id, date) VALUES (?, ?)", [$userId, $date]);
        $this->query("INSERT IGNORE INTO spiritual_charity (user_id, date) VALUES (?, ?)", [$userId, $date]);

        $log = $this->query("SELECT * FROM spiritual_daily_logs WHERE user_id=? AND date=?", [$userId, $date])->fetch();
        $prayers = $this->query("SELECT * FROM spiritual_prayers WHERE user_id=? AND date=?", [$userId, $date])->fetch();
        $adhkar = $this->query("SELECT * FROM spiritual_adhkar WHERE user_id=? AND date=?", [$userId, $date])->fetch();
        $quran = $this->query("SELECT * FROM spiritual_quran WHERE user_id=? AND date=?", [$userId, $date])->fetch();
        $charity = $this->query("SELECT * FROM spiritual_charity WHERE user_id=? AND date=?", [$userId, $date])->fetch();

        $progress = $log->final_score !== null ? $log->final_score : $this->calculateDailyProgress($prayers, $adhkar, $quran, $charity);
        $isLocked = false;
        
        // Ensure accurate status label for history logic manually if viewing old day before refresh
        $status = $log->final_status ?: $this->determineStatus($progress);

        $streaks = $this->calculateAdvancedStreaks($userId);
        $consistency = $this->calculateConsistency($userId);
        $state = $this->calculateSpiritualState($progress, $consistency);

        return [
            'log' => $log,
            'prayers' => $prayers,
            'adhkar' => $adhkar,
            'quran' => $quran,
            'charity' => $charity,
            'streaks' => $streaks,
            'records' => $this->getHistoricalBests($userId, $streaks),
            'progress' => $progress,
            'status' => $status,
            'is_locked' => $isLocked,
            'feedback' => $this->getGentleFeedback($userId, $date),
            'consistency' => $consistency,
            'state' => $state
        ];
    }

    public function getHistoricalBests($userId, $currentStreaks = null) {
        // In a real production app, we'd store these in a user_stats table.
        // For OTIS, we calculate them on the fly from the last 365 days of logs.
        $rows = $this->query(
            "SELECT date, final_status FROM spiritual_daily_logs 
             WHERE user_id=? AND final_status IS NOT NULL ORDER BY date ASC",
            [$userId]
        )->fetchAll();

        $maxPerfect = 0; $currPerfect = 0;
        $maxOverall = 0; $currOverall = 0;

        foreach ($rows as $r) {
            if ($r->final_status === 'perfect') {
                $currPerfect++;
                $currOverall++;
            } else if ($r->final_status === 'partial') {
                $currPerfect = 0;
                $currOverall++;
            } else {
                $currPerfect = 0;
                $currOverall = 0;
            }
            if ($currPerfect > $maxPerfect) $maxPerfect = $currPerfect;
            if ($currOverall > $maxOverall) $maxOverall = $currOverall;
        }

        // If current streaks are higher (e.g. today's in-progress data), update max
        if ($currentStreaks) {
            $maxPerfect = max($maxPerfect, $currentStreaks['perfect']);
            $maxOverall = max($maxOverall, $currentStreaks['overall']);
        }

        return ['max_perfect' => $maxPerfect, 'max_overall' => $maxOverall];
    }

    private function finalizePastDays($userId) {
        // Find un-finalized days in the past
        $unfinalized = $this->query("SELECT date FROM spiritual_daily_logs WHERE user_id=? AND date < CURDATE() AND final_status IS NULL", [$userId])->fetchAll();
        foreach ($unfinalized as $row) {
            $d = $row->date;
            $prayers = $this->query("SELECT * FROM spiritual_prayers WHERE user_id=? AND date=?", [$userId, $d])->fetch();
            $adhkar = $this->query("SELECT * FROM spiritual_adhkar WHERE user_id=? AND date=?", [$userId, $d])->fetch();
            $quran = $this->query("SELECT * FROM spiritual_quran WHERE user_id=? AND date=?", [$userId, $d])->fetch();
            $charity = $this->query("SELECT * FROM spiritual_charity WHERE user_id=? AND date=?", [$userId, $d])->fetch();
            
            $score = $this->calculateDailyProgress($prayers, $adhkar, $quran, $charity);
            $status = $this->determineStatus($score);
            $consistency = $this->calculateConsistency($userId, $d);
            $state = $this->calculateSpiritualState($score, $consistency);
            
            $this->query("UPDATE spiritual_daily_logs SET final_score=?, final_status=?, consistency_score=?, spiritual_state=? WHERE user_id=? AND date=?", [$score, $status, $consistency, $state, $userId, $d]);
        }
    }

    private function determineStatus($score) {
        if ($score === 100) return 'perfect';
        if ($score > 40) return 'partial';
        return 'weak';
    }

    public function toggleStatus($userId, $date, $table, $field, $value = null) {
        $allowedTables = ['spiritual_prayers', 'spiritual_adhkar', 'spiritual_quran', 'spiritual_charity', 'spiritual_daily_logs'];
        if (!in_array($table, $allowedTables)) return false;

        if ($value === null) {
            $sql = "UPDATE {$table} SET {$field} = NOT {$field} WHERE user_id=? AND date=?";
            $this->query($sql, [$userId, $date]);
        } else {
            $sql = "UPDATE {$table} SET {$field} = ? WHERE user_id=? AND date=?";
            $this->query($sql, [$value, $userId, $date]);
        }
        
        $rs = $this->query("SELECT {$field} FROM {$table} WHERE user_id=? AND date=?", [$userId, $date])->fetch();
        $this->logAction($userId, 'updated', "تحديث الروحانيات: {$table}.{$field}");
        
        // Recalculate if past
        if ($date < date('Y-m-d')) {
            $prayers = $this->query("SELECT * FROM spiritual_prayers WHERE user_id=? AND date=?", [$userId, $date])->fetch();
            $adhkar = $this->query("SELECT * FROM spiritual_adhkar WHERE user_id=? AND date=?", [$userId, $date])->fetch();
            $quran = $this->query("SELECT * FROM spiritual_quran WHERE user_id=? AND date=?", [$userId, $date])->fetch();
            $charity = $this->query("SELECT * FROM spiritual_charity WHERE user_id=? AND date=?", [$userId, $date])->fetch();
            
            $score = $this->calculateDailyProgress($prayers, $adhkar, $quran, $charity);
            $status = $this->determineStatus($score);
            $consistency = $this->calculateConsistency($userId, $date);
            $state = $this->calculateSpiritualState($score, $consistency);
            
            $this->query("UPDATE spiritual_daily_logs SET final_score=?, final_status=?, consistency_score=?, spiritual_state=? WHERE user_id=? AND date=?", [$score, $status, $consistency, $state, $userId, $date]);
        }
        
        return $rs->$field;
    }

    public function deleteRecord($userId, $date) {
        $this->query("DELETE FROM spiritual_daily_logs WHERE user_id=? AND date=?", [$userId, $date]);
        $this->query("DELETE FROM spiritual_prayers WHERE user_id=? AND date=?", [$userId, $date]);
        $this->query("DELETE FROM spiritual_adhkar WHERE user_id=? AND date=?", [$userId, $date]);
        $this->query("DELETE FROM spiritual_quran WHERE user_id=? AND date=?", [$userId, $date]);
        $this->query("DELETE FROM spiritual_charity WHERE user_id=? AND date=?", [$userId, $date]);
    }

    private function calculateDailyProgress($prayers, $adhkar, $quran, $charity) {
        $items = 0; $done = 0;
        if ($prayers) {
            $pFields = ['fajr', 'dhuhr', 'asr', 'maghrib', 'isha'];
            foreach($pFields as $f) { $items++; if($prayers->$f) $done++; }
        }
        if ($adhkar) {
            $aFields = ['morning_done', 'evening_done'];
            foreach($aFields as $f) { $items++; if($adhkar->$f) $done++; }
        }
        if ($quran) {
            $qFields = ['wird_completed', 'yaseen', 'waqiah'];
            foreach($qFields as $f) { $items++; if($quran->$f) $done++; }
        }
        if ($charity) {
            $items++; if($charity->completed) $done++;
        }
        return $items > 0 ? round(($done / $items) * 100) : 0;
    }

    public function calculateAdvancedStreaks($userId) {
        // Include today's data too (not just past days)
        $rows = $this->query(
            "SELECT date, final_score, final_status FROM spiritual_daily_logs 
             WHERE user_id=? AND date <= CURDATE() ORDER BY date DESC LIMIT 90",
            [$userId]
        )->fetchAll();
        
        $overall = 0;
        $perfect = 0;
        $perfectBroken = false;
        
        foreach ($rows as $r) {
            // Infer status if not yet finalized (e.g., today or un-finalized past days)
            $status = $r->final_status;
            if ($status === null && $r->final_score !== null) {
                $status = $this->determineStatus((int)$r->final_score);
            }
            
            // For today specifically, calculate live progress even if final_score is null
            if ($status === null && $r->date === date('Y-m-d')) {
                // Fetch today's live progress
                $p = $this->query("SELECT * FROM spiritual_prayers WHERE user_id=? AND date=?", [$userId, $r->date])->fetch();
                $a = $this->query("SELECT * FROM spiritual_adhkar WHERE user_id=? AND date=?",  [$userId, $r->date])->fetch();
                $q = $this->query("SELECT * FROM spiritual_quran WHERE user_id=? AND date=?",   [$userId, $r->date])->fetch();
                $c = $this->query("SELECT * FROM spiritual_charity WHERE user_id=? AND date=?", [$userId, $r->date])->fetch();
                $todayScore = $this->calculateDailyProgress($p, $a, $q, $c);
                $status = $todayScore > 0 ? $this->determineStatus($todayScore) : null;
            }
            
            // Only 'weak' breaks a streak; NULL (no data) simply stops counting but doesn't break perfect
            if ($status === 'weak') {
                break;
            }
            if ($status === null) {
                // If today is empty, don't break the loop yet — allow yesterday's streak to be counted
                if ($r->date === date('Y-m-d')) continue;
                break;
            }
            if ($status === 'perfect' || $status === 'partial') {
                $overall++;
            }
            if ($status === 'perfect' && !$perfectBroken) {
                $perfect++;
            } else if ($status !== 'perfect') {
                $perfectBroken = true;
            }
        }
        
        return ['overall' => $overall, 'perfect' => $perfect];
    }

    public function calculateConsistency($userId, $endDate = null) {
        $dateParam = $endDate ? $endDate : date('Y-m-d');
        // Consistency is not just perfection, it's about showing up consistently avoiding zero/weak days
        $rows = $this->query("SELECT final_score FROM spiritual_daily_logs WHERE user_id=? AND date <= ? ORDER BY date DESC LIMIT 7", [$userId, $dateParam])->fetchAll();
        
        if (empty($rows)) return 50; // default baseline

        $sum = 0;
        $count = 0;
        foreach ($rows as $r) {
            $score = (int)$r->final_score;
            // Reward showing up: even a score of 40 yields significant consistency points.
            if ($score >= 80) $sum += 100;
            else if ($score >= 40) $sum += 75; // Partial effort highly rewarded
            else if ($score > 0) $sum += 40;
            $count++;
        }
        return $count > 0 ? (int)round($sum / $count) : 50;
    }

    public function calculateSpiritualState($score, $consistency) {
        $combined = ($score * 0.4) + ($consistency * 0.6); // Consistency weighs more
        if ($combined >= 80) return 'high';
        if ($combined >= 45) return 'medium';
        return 'low';
    }

    public function getArchive($userId) {
        $this->finalizePastDays($userId);
        return $this->query("SELECT * FROM spiritual_daily_logs WHERE user_id=? AND date < CURDATE() ORDER BY date DESC", [$userId])->fetchAll();
    }

    public function getWeeklySummary($userId) {
        $this->finalizePastDays($userId);
        $w = $this->query("SELECT l.*, p.fajr, p.dhuhr, p.asr, p.maghrib, p.isha, a.morning_done, a.evening_done, q.wird_completed
                           FROM spiritual_daily_logs l
                           LEFT JOIN spiritual_prayers p ON l.user_id = p.user_id AND l.date = p.date
                           LEFT JOIN spiritual_adhkar a ON l.user_id = a.user_id AND l.date = a.date
                           LEFT JOIN spiritual_quran q ON l.user_id = q.user_id AND l.date = q.date
                           WHERE l.user_id=? AND l.date >= DATE_SUB(CURDATE(), INTERVAL 7 DAY) AND l.date < CURDATE() ORDER BY l.date ASC", [$userId])->fetchAll();
        
        if (!$w) return ['avg' => 0, 'best' => null, 'worst' => null, 'strengths' => [], 'weaknesses' => []];
        
        $sum = 0; $count = 0;
        $best = ['score' => -1, 'date' => null];
        $worst = ['score' => 101, 'date' => null];
        
        $stats = [
            'fajr' => 0, 'all_prayers' => 0, 'adhkar' => 0, 'wird' => 0
        ];

        foreach ($w as $d) {
            $sum += $d->final_score;
            $count++;
            if ($d->final_score > $best['score']) { $best['score'] = $d->final_score; $best['date'] = $d->date; }
            if ($d->final_score < $worst['score']) { $worst['score'] = $d->final_score; $worst['date'] = $d->date; }
            
            if ($d->fajr) $stats['fajr']++;
            if ($d->fajr && $d->dhuhr && $d->asr && $d->maghrib && $d->isha) $stats['all_prayers']++;
            if ($d->morning_done && $d->evening_done) $stats['adhkar']++;
            if ($d->wird_completed) $stats['wird']++;
        }

        $strengths = [];
        $weaknesses = [];
        
        if ($stats['fajr'] >= 5) $strengths[] = 'المواظبة على صلاة الفجر';
        else if ($stats['fajr'] <= 2) $weaknesses[] = 'تحتاج للتركيز أكثر على صلاة الفجر';
        
        if ($stats['adhkar'] >= 5) $strengths[] = 'ثبات ممتاز في المحافظة على الأذكار';
        else if ($stats['adhkar'] <= 2) $weaknesses[] = 'ورد الأذكار غير منتظم، حاول ربطه بعادة أخرى';
        
        if ($stats['wird'] >= 4) $strengths[] = 'استمرارية طيبة في الورد القرآني';
        else if ($stats['wird'] <= 2) $weaknesses[] = 'زاحم يومك بالقرآن ولو بنصف وجه يومياً';

        return [
            'avg' => $count ? round($sum / $count) : 0,
            'best' => $best,
            'worst' => $worst,
            'days' => $w,
            'strengths' => $strengths,
            'weaknesses' => $weaknesses
        ];
    }

    public function getGentleFeedback($userId, $date) {
        $recent = $this->query(
            "SELECT l.date, l.final_score, p.fajr, p.isha, a.morning_done, a.evening_done, q.wird_completed
             FROM spiritual_daily_logs l
             LEFT JOIN spiritual_prayers p ON l.user_id=p.user_id AND l.date=p.date
             LEFT JOIN spiritual_adhkar a ON l.user_id=a.user_id AND l.date=a.date
             LEFT JOIN spiritual_quran q ON l.user_id=q.user_id AND l.date=q.date
             WHERE l.user_id=? AND l.date <= ? ORDER BY l.date DESC LIMIT 4", 
             [$userId, $date]
        )->fetchAll();

        if (count($recent) < 2) return "كل يوم هو بداية جديدة، توكل على الله واسمح للسكينة أن تملأ قلبك.";

        $missedWird = 0; $missedFajr = 0; $missedAdhkar = 0; $consistent = 0;
        foreach ($recent as $r) {
            if (!$r->wird_completed) $missedWird++;
            if (!$r->fajr) $missedFajr++;
            if (!$r->morning_done && !$r->evening_done) $missedAdhkar++;
            if ($r->final_score && $r->final_score >= 40) $consistent++; // Reward showing up
        }

        if ($consistent >= 3) return "ما شاء الله، إقبالك وثباتك يثلج الصدر. استمر في هذا المسار النير، فالقليل الدائم خير.";
        
        $tips = [];
        if ($missedFajr >= 2) $tips[] = "لركعتا الفجر خير من الدنيا وما فيها، جرب ضبط منبهك بحب لحضور هذه اللحظة.";
        if ($missedAdhkar >= 2) $tips[] = "أذكارك حصن دافئ لروحك، حاول جعلها جزءاً من روتينك البسيط.";
        if ($missedWird >= 2) $tips[] = "حتى آية واحدة يومياً تنير قلبك. ابدأ بخطوات صغيرة بلا ضغط.";

        if(empty($tips)) return "الاستمرار نعمة، تقبل تفاوت طاقتك واحرص على ما ينفعك بلطف.";
        
        // Return only the first gentle tip to avoid overwhelming
        return "رسالة اليوم لطمأنينتك: " . $tips[0];
    }
}
