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

class HabitModel extends \Core\Model {
    protected $table = 'habits';
    protected $moduleName = 'Habits';
    // Manages soft delete via its own softDelete() method and inline SQL.
    // Base Model::delete() is intentionally bypassed.
    protected $useSoftDeletes = false;

    // ─── HABITS ───────────────────────────────────────────
    public function getHabitsWithStatus($userId) {
        $today = date('Y-m-d');
        $sql = "
            SELECT h.*,
                   CASE WHEN hl.id IS NOT NULL THEN 1 ELSE 0 END AS checked_today
            FROM habits h
            LEFT JOIN habit_logs hl
                   ON hl.habit_id = h.id AND hl.log_date = ? AND hl.deleted_at IS NULL
            WHERE h.user_id = ? AND h.deleted_at IS NULL
            ORDER BY h.created_at ASC
        ";
        return $this->query($sql, [$today, $userId])->fetchAll();
    }

    public function addHabit($userId, $data) {
        $sql = "INSERT INTO habits (user_id, name, icon, frequency, color_hex) VALUES (?, ?, ?, ?, ?)";
        $res = $this->query($sql, [
            $userId,
            $data['name'],
            $data['icon']      ?? 'fa-star',
            $data['frequency'] ?? 'daily',
            $data['color_hex'] ?? '#0d6efd'
        ]);
        $this->logAction($userId, 'created', "إضافة عادة جديدة: {$data['name']}");
        return $res;
    }

    public function softDelete($id, $userId) {
        return $this->query("UPDATE habits SET deleted_at = CURRENT_TIMESTAMP WHERE id = ? AND user_id = ?", [$id, $userId]);
    }

    // ─── CHECK-IN ─────────────────────────────────────────
    public function checkin($userId, $habitId) {
        $today = date('Y-m-d');
        // Idempotent: skip if already checked in
        $exists = $this->query(
            "SELECT id FROM habit_logs WHERE habit_id = ? AND user_id = ? AND log_date = ? AND deleted_at IS NULL",
            [$habitId, $userId, $today]
        )->fetch();
        if ($exists) return false;

        $this->query(
            "INSERT INTO habit_logs (habit_id, user_id, log_date) VALUES (?, ?, ?)",
            [$habitId, $userId, $today]
        );
        $this->logAction($userId, 'checkin', "تسجيل إتمام عادة رقم {$habitId} بتاريخ {$today}");
        
        // Gamification Reward
        require_once __DIR__ . '/../../../../core/Services/GamificationEngine.php';
        \Core\Services\GamificationEngine::getInstance()->onEvent('habit_done', $userId);
        
        return true;
    }

    public function undoCheckin($userId, $habitId) {
        $today = date('Y-m-d');
        return $this->query(
            "UPDATE habit_logs SET deleted_at = CURRENT_TIMESTAMP WHERE habit_id = ? AND user_id = ? AND log_date = ?",
            [$habitId, $userId, $today]
        );
    }

    // ─── STREAK ───────────────────────────────────────────
    /**
     * Calculate consecutive days ending today that the habit was checked in.
     */
    public function getStreak($userId, $habitId) {
        // Fetch last 365 check-in dates in descending order
        $rows = $this->query(
            "SELECT log_date FROM habit_logs WHERE habit_id = ? AND user_id = ? AND deleted_at IS NULL ORDER BY log_date DESC LIMIT 365",
            [$habitId, $userId]
        )->fetchAll(\PDO::FETCH_COLUMN);

        if (empty($rows)) return 0;

        $streak    = 0;
        $checkDate = new \DateTime(date('Y-m-d'));

        foreach ($rows as $dateStr) {
            $logDate = new \DateTime($dateStr);
            $diff    = (int)$checkDate->diff($logDate)->days;
            if ($diff === 0 || $diff === 1) {
                $streak++;
                $checkDate = $logDate;
            } else {
                break;
            }
        }
        return $streak;
    }

    // ─── STATS ────────────────────────────────────────────
    /**
     * Returns last 7 days completion for a given habit (for mini-chart)
     */
    public function getLast7Days($userId, $habitId) {
        $result = [];
        for ($i = 6; $i >= 0; $i--) {
            $date = date('Y-m-d', strtotime("-{$i} days"));
            $done = $this->query(
                "SELECT id FROM habit_logs WHERE habit_id = ? AND user_id = ? AND log_date = ? AND deleted_at IS NULL",
                [$habitId, $userId, $date]
            )->fetch();
            $result[] = ['date' => $date, 'done' => $done ? 1 : 0];
        }
        return $result;
    }

    /**
     * Batch calculation of streaks for all active habits of a user.
     * Prevents N+1 query problem.
     */
    public function getBatchStreaks($userId) {
        $sql = "
            SELECT habit_id, log_date 
            FROM habit_logs 
            WHERE user_id = ? AND deleted_at IS NULL 
            ORDER BY habit_id, log_date DESC
        ";
        $allLogs = $this->query($sql, [$userId])->fetchAll();
        
        $streaks = [];
        $logsByHabit = [];
        foreach ($allLogs as $log) {
            $logsByHabit[$log->habit_id][] = $log->log_date;
        }

        foreach ($logsByHabit as $habitId => $dates) {
            $streak = 0;
            $checkDate = new \DateTime(date('Y-m-d'));
            foreach ($dates as $dateStr) {
                $logDate = new \DateTime($dateStr);
                $diff = (int)$checkDate->diff($logDate)->days;
                if ($diff === 0 || $diff === 1) {
                    $streak++;
                    $checkDate = $logDate;
                } else {
                    break;
                }
            }
            $streaks[$habitId] = $streak;
        }
        return $streaks;
    }

    /**
     * Cross-Module Impact: Finance / Health / Productivity
     */
    public function logImpact($habitId, $userId, $undo = false) {
        $habit = $this->query("SELECT * FROM habits WHERE id = ? AND user_id = ?", [$habitId, $userId])->fetch();
        if (!$habit || $habit->impact_category === 'general') return;

        if ($habit->impact_category === 'finance' && $habit->habit_type === 'break') {
            if (!$undo) {
                // Log "Shadow Saving"
                $this->query("INSERT INTO finance_expenses (user_id, amount, category, description, expense_date) 
                             VALUES (?, ?, ?, ?, CURDATE())", 
                             [$userId, -$habit->impact_amount, 'Savings', "توفير من ترك عادت سيئة: {$habit->name}"]);
            } else {
                // Remove saving log (approximate by deleting last similar entry)
                $this->query("DELETE FROM finance_expenses WHERE user_id = ? AND description LIKE ? AND expense_date = CURDATE() LIMIT 1", 
                             [$userId, "%{$habit->name}%"]);
            }
        }
        
        // Health impact logic can be added here if health_vitality table exists
    }

    /**
     * Sync habit to Calendar as a "Ritual" time block.
     */
    public function syncToCalendar($habitId, $userId, $undo = false) {
        $habit = $this->query("SELECT * FROM habits WHERE id = ? AND user_id = ?", [$habitId, $userId])->fetch();
        if (!$habit) return;

        if ($undo) {
            // Remove from calendar_time_blocks for today
            $this->query("UPDATE calendar_time_blocks SET deleted_at = CURRENT_TIMESTAMP 
                         WHERE user_id = ? AND title LIKE ? AND block_date = CURDATE()", 
                         [$userId, "%{$habit->name}%"]);
        } else {
            // Add to calendar_time_blocks (as a 30m block)
            $this->query("INSERT INTO calendar_time_blocks (user_id, title, block_date, start_time, end_time, category, color_hex, notes) 
                         VALUES (?, ?, CURDATE(), '09:00:00', '09:30:00', 'ritual', ?, ?)", 
                         [$userId, "إتمام عادة: {$habit->name}", $habit->color_hex, $habit->identity_statement]);
        }
    }

    /**
     * Gets all logs for the past N days for ALL habits of a user.
     * Returns associative array: [habit_id => [date1 => true, date2 => true]]
     */
    public function getRecentLogsAssoc($userId, $days = 7) {
        $logs = $this->query(
            "SELECT habit_id, log_date FROM habit_logs WHERE user_id = ? AND log_date >= DATE_SUB(CURDATE(), INTERVAL ? DAY) AND deleted_at IS NULL",
            [$userId, $days - 1]
        )->fetchAll();
        
        $assoc = [];
        foreach ($logs as $log) {
            $assoc[$log->habit_id][$log->log_date] = true;
        }
        return $assoc;
    }
}
