<?php

namespace App\Controllers\Siswa;

use App\Controllers\BaseController;
use App\Models\StudentModel;
use App\Models\UserModel;
use App\Models\SchoolSettingModel;
use App\Models\AttendanceModel;
use App\Models\StudentGradeModel;
use App\Models\AcademicPeriodModel;
use App\Models\ScheduleModel;
use App\Models\ScheduleTimeslotModel;

class StudentPortal extends BaseController
{
    protected $studentModel;
    protected $userModel;
    protected $settingModel;
    protected $periodModel;

    public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
    {
        parent::initController($request, $response, $logger);

        $this->studentModel = new StudentModel();
        $this->userModel    = new UserModel();
        $this->settingModel = new SchoolSettingModel();
        $this->periodModel  = new AcademicPeriodModel();

        // Security check: Force password change first if reset flag is active
        $router = service('router');
        $method = $router->methodName();
        $userId = session()->get('user_id');

        if (session()->get('user_role') === 'siswa' && $userId) {
            $user = $this->userModel->find($userId);
            if ($user && (int)$user['is_password_reset'] === 1 && !in_array($method, ['changePassword', 'changePasswordProcess'])) {
                $response->redirect(site_url('siswa/change-password'))->send();
                exit;
            }
        }
    }

    private function getStudentOrRedirect()
    {
        $studentId = session()->get('student_id');
        if (!$studentId) {
            session()->destroy();
            return redirect()->to('/login')->with('error', 'Sesi siswa tidak valid.');
        }

        $student = $this->studentModel->find($studentId);
        if (!$student) {
            session()->destroy();
            return redirect()->to('/login')->with('error', 'Data siswa tidak ditemukan.');
        }

        return $student;
    }

    // ── 1. DASHBOARD ──────────────────────────────────────────
    public function dashboard()
    {
        $student = $this->getStudentOrRedirect();
        if ($student instanceof \CodeIgniter\HTTP\RedirectResponse) return $student;

        $db = \Config\Database::connect();
        $activePeriod = $this->periodModel->getActive();
        $setting = $this->settingModel->getSettings();

        // Ambil kelas aktif siswa saat ini
        $classroom = null;
        $attendanceStats = ['hadir' => 0, 'sakit' => 0, 'izin' => 0, 'alpha' => 0, 'persentase' => 100];
        $todaySchedule = [];

        if ($activePeriod) {
            $history = $db->table('student_academic_histories h')
                ->select('h.classroom_id, c.name as classroom_name, g.name as grade_name')
                ->join('classrooms c', 'c.id = h.classroom_id')
                ->join('grades g', 'g.id = c.grade_id')
                ->where('h.student_id', $student['id'])
                ->where('h.academic_period_id', $activePeriod['id'])
                ->get()->getRowArray();

            if ($history) {
                $classroom = $history;

                // Hitung statistik presensi semester ini
                $attModel = new AttendanceModel();
                $sakit = $attModel->where('student_id', $student['id'])
                                  ->where('academic_period_id', $activePeriod['id'])
                                  ->where('status', 'Sakit')
                                  ->countAllResults();
                $izin = $attModel->where('student_id', $student['id'])
                                 ->where('academic_period_id', $activePeriod['id'])
                                  ->where('status', 'Izin')
                                  ->countAllResults();
                $alpha = $attModel->where('student_id', $student['id'])
                                  ->where('academic_period_id', $activePeriod['id'])
                                  ->where('status', 'Alpha')
                                  ->countAllResults();

                $effectiveDays = $attModel->countActiveDays($activePeriod['start_date'], date('Y-m-d'));
                if ($effectiveDays < 0) $effectiveDays = 0;

                if ($effectiveDays === 0) {
                    $hadir = 0;
                    $persentase = 100;
                } else {
                    $hadir = $effectiveDays - ($sakit + $izin + $alpha);
                    if ($hadir < 0) $hadir = 0;
                    $persentase = round(($hadir / $effectiveDays) * 100, 1);
                }

                $attendanceStats = [
                    'hadir'       => $hadir,
                    'sakit'       => $sakit,
                    'izin'        => $izin,
                    'alpha'       => $alpha,
                    'persentase'  => $persentase,
                    'efektif'     => $effectiveDays
                ];

                // Ambil jadwal hari ini
                $dayNumber = date('N'); // 1=Senin, 7=Minggu
                if ($dayNumber < 7) {
                    $sourceRow = $db->table('settings')->where('setting_key', 'schedule_source')->get()->getRowArray();
                    $scheduleSource = $sourceRow['setting_value'] ?? 'local';

                    if ($scheduleSource === 'asc') {
                        $activeImport = $db->table('asc_imports')->where('is_active', 1)->get()->getRowArray();
                        if ($activeImport) {
                            $ascClass = $db->table('asc_classes')
                                           ->where('import_id', $activeImport['id'])
                                           ->where('classroom_id', $classroom['classroom_id'])
                                           ->get()->getRowArray();
                            if ($ascClass) {
                                $todaySchedule = $db->table('asc_schedules se')
                                    ->select('se.period_number, COALESCE(ss.name, se.subject_name) as subject_name, COALESCE(t.name, se.teacher_name) as teacher_name')
                                    ->join('asc_subjects sub', 'sub.asc_id = se.subject_asc_id AND sub.import_id = se.import_id', 'left')
                                    ->join('school_subjects ss', 'ss.id = sub.school_subject_id', 'left')
                                    ->join('asc_teachers at', 'at.asc_id = se.teacher_asc_id AND at.import_id = se.import_id', 'left')
                                    ->join('teachers t', 't.id = at.teacher_id', 'left')
                                    ->where('se.import_id', $activeImport['id'])
                                    ->where('se.class_asc_id', $ascClass['asc_id'])
                                    ->where('se.day_number', $dayNumber)
                                    ->orderBy('se.period_number', 'ASC')
                                    ->get()->getResultArray();
                            }
                        }
                    } else {
                        // Jalur lokal
                        $publishedSchedule = $db->table('schedules')
                            ->where('academic_period_id', $activePeriod['id'])
                            ->where('status', 'published')
                            ->where('type', $scheduleSource)
                            ->get()->getRowArray();

                        if ($publishedSchedule) {
                            $todaySchedule = $db->table('schedule_entries se')
                                ->select('se.slot_number as period_number, ss.name as subject_name, t.name as teacher_name')
                                ->join('school_subjects ss', 'ss.id = se.school_subject_id')
                                ->join('teachers t', 't.id = se.teacher_id')
                                ->where('se.schedule_id', $publishedSchedule['id'])
                                ->where('se.classroom_id', $classroom['classroom_id'])
                                ->where('se.day', $dayNumber)
                                ->orderBy('se.slot_number', 'ASC')
                                ->get()->getResultArray();
                        }
                    }
                }
            }
        }

        $violationModel = new \App\Models\StudentViolationModel();
        $sanctionModel  = new \App\Models\ViolationSanctionModel();
        $violationPoints = $activePeriod ? $violationModel->getAccumulatedPoints($student['id'], $activePeriod['id']) : 0;
        $activeSanction = $sanctionModel->getActiveSanction($violationPoints);

        $data = [
            'title'           => 'Dashboard Siswa',
            'student'         => $student,
            'classroom'       => $classroom,
            'attendanceStats' => $attendanceStats,
            'todaySchedule'   => $todaySchedule,
            'setting'         => $setting,
            'activePeriod'    => $activePeriod,
            'violationPoints' => $violationPoints,
            'activeSanction'  => $activeSanction ? $activeSanction['action_title'] : 'Aman',
        ];

        return view('siswa/dashboard', $data);
    }

    // ── 2. PROFIL & EDIT DATA MANDIRI ──────────────────────────
    public function profile()
    {
        $student = $this->getStudentOrRedirect();
        if ($student instanceof \CodeIgniter\HTTP\RedirectResponse) return $student;

        $setting = $this->settingModel->getSettings();
        $editableFields = json_decode($setting['student_portal_editable_fields'] ?? '[]', true);
        if (!is_array($editableFields)) $editableFields = [];

        $data = [
            'title'          => 'Profil & Verifikasi Data',
            'student'        => $student,
            'editableFields' => $editableFields,
        ];

        return view('siswa/profile', $data);
    }

    public function updateProfile()
    {
        $student = $this->getStudentOrRedirect();
        if ($student instanceof \CodeIgniter\HTTP\RedirectResponse) return $student;

        $setting = $this->settingModel->getSettings();
        $editableFields = json_decode($setting['student_portal_editable_fields'] ?? '[]', true);
        if (!is_array($editableFields)) $editableFields = [];

        // Kumpulkan payload edit berdasarkan izin admin saja
        $payload = [];
        $allowedFieldsList = [
            'nik', 'gender', 'religion', 'kip_no', 'graduation_certificate_no', 'origin_school', 'entry_year', 'entry_date',
            'phone', 'address', 'rt', 'rw', 'village', 'district', 'city', 'province', 'postal_code',
            'family_card_no', 'family_head_name',
            'father_name', 'father_nik', 'father_birth_place', 'father_birth', 'father_edu', 'father_job', 'father_phone',
            'mother_name', 'mother_nik', 'mother_birth_place', 'mother_birth', 'mother_edu', 'mother_job', 'mother_phone'
        ];

        foreach ($allowedFieldsList as $field) {
            if (in_array($field, $editableFields) && $this->request->getPost($field) !== null) {
                $payload[$field] = $this->request->getPost($field);
            }
        }

        if (empty($payload)) {
            return redirect()->back()->with('error', 'Tidak ada data diubah atau diizinkan untuk diubah.');
        }

        // --- VALIDASI SISI SERVER (BACKEND) ---
        // 1. Validasi Kolom 16 Digit (NIK Siswa, No. KK, NIK Ayah, NIK Ibu) jika diinput
        $sixteenDigitFields = ['nik', 'family_card_no', 'father_nik', 'mother_nik'];
        foreach ($sixteenDigitFields as $f) {
            if (isset($payload[$f]) && trim($payload[$f]) !== '') {
                $val = trim($payload[$f]);
                if (strlen($val) !== 16 || !ctype_digit($val)) {
                    $label = match($f) {
                        'nik' => 'NIK Siswa',
                        'family_card_no' => 'Nomor KK',
                        'father_nik' => 'NIK Ayah',
                        'mother_nik' => 'NIK Ibu',
                        default => $f
                    };
                    return redirect()->back()->withInput()->with('error', "Gagal menyimpan. {$label} harus terdiri dari tepat 16 digit angka.");
                }
            }
        }

        // 2. Validasi Tahun Lahir Orang Tua (4 Digit Angka, Tahun 1900 s.d Sekarang) jika diinput
        $yearFields = ['father_birth', 'mother_birth'];
        $currentYear = date('Y');
        foreach ($yearFields as $f) {
            if (isset($payload[$f]) && trim($payload[$f]) !== '') {
                $val = trim($payload[$f]);
                $yearNum = (int)$val;
                if (strlen($val) !== 4 || !ctype_digit($val) || $yearNum < 1900 || $yearNum > $currentYear) {
                    $label = match($f) {
                        'father_birth' => 'Tahun Lahir Ayah',
                        'mother_birth' => 'Tahun Lahir Ibu',
                        default => $f
                    };
                    return redirect()->back()->withInput()->with('error', "Gagal menyimpan. {$label} harus berupa 4 digit angka tahun yang valid (1900 - {$currentYear}).");
                }
            }
        }

        // 3. Validasi Nomor HP jika diinput
        $phoneKeys = ['phone', 'father_phone', 'mother_phone'];
        foreach ($phoneKeys as $pk) {
            if (isset($payload[$pk]) && trim($payload[$pk]) !== '') {
                $phoneVal = trim($payload[$pk]);
                if (!str_starts_with($phoneVal, '628') || strlen($phoneVal) < 10 || strlen($phoneVal) > 15 || !ctype_digit($phoneVal)) {
                    return redirect()->back()->withInput()->with('error', 'Gagal menyimpan. Nomor HP harus diawali dengan 628 dan terdiri dari 10 s.d. 15 digit angka.');
                }
            }
        }

        // Jalankan update
        $this->studentModel->update($student['id'], $payload);

        log_activity('update', 'siswa_portal', $student['id'], "Siswa mengubah data profil mandiri: " . json_encode($payload));

        return redirect()->to('/siswa/profile')->with('success', 'Data profil Anda berhasil diperbarui!');
    }

    // ── 3. JADWAL PELAJARAN ───────────────────────────────────
    public function schedule()
    {
        $student = $this->getStudentOrRedirect();
        if ($student instanceof \CodeIgniter\HTTP\RedirectResponse) return $student;

        $db = \Config\Database::connect();
        
        $activePeriod = $this->periodModel->getActive();
        $selectedPeriodId = $activePeriod['id'] ?? null;
        
        $scheduleData = [];
        $scheduleDays = [];
        $schedulePeriods = [];
        $classroomInfo = null;

        if ($selectedPeriodId) {
            // Temukan kelas di periode aktif tersebut
            $selectedHistory = $db->table('student_academic_histories h')
                ->select('h.classroom_id, c.name as classroom_name, y.name as year_name, p.semester')
                ->join('classrooms c', 'c.id = h.classroom_id')
                ->join('academic_periods p', 'p.id = h.academic_period_id')
                ->join('academic_years y', 'y.id = p.academic_year_id')
                ->where('h.student_id', $student['id'])
                ->where('h.academic_period_id', $selectedPeriodId)
                ->get()->getRowArray();

            if ($selectedHistory) {
                $classroomInfo = $selectedHistory;
                $classroomId = $selectedHistory['classroom_id'];

                $sourceRow = $db->table('settings')->where('setting_key', 'schedule_source')->get()->getRowArray();
                $scheduleSource = $sourceRow['setting_value'] ?? 'local';

                if ($scheduleSource === 'asc') {
                    $activeImport = $db->table('asc_imports')->where('is_active', 1)->get()->getRowArray();
                    if ($activeImport) {
                        $ascClass = $db->table('asc_classes')
                                       ->where('import_id', $activeImport['id'])
                                       ->where('classroom_id', $classroomId)
                                       ->get()->getRowArray();
                        
                        if ($ascClass) {
                            $ascScheduleModel = new \App\Models\AscScheduleModel();
                            $scheduleData = $ascScheduleModel->getByClass($activeImport['id'], $ascClass['asc_id']);
                            $scheduleDays = $ascScheduleModel->getDayList($activeImport['id']);
                            $schedulePeriods = $ascScheduleModel->getPeriodList($activeImport['id']);
                        }
                    }
                } else {
                    $publishedSchedule = $db->table('schedules')
                        ->where('academic_period_id', $selectedPeriodId)
                        ->where('status', 'published')
                        ->where('type', $scheduleSource)
                        ->get()->getRowArray();

                    if ($publishedSchedule) {
                        $dayNames = ['', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];
                        $activeDays = array_map('intval', explode(',', $publishedSchedule['active_days']));
                        foreach ($activeDays as $dNum) {
                            $scheduleDays[] = [
                                'day_number' => $dNum,
                                'day_name'   => $dayNames[$dNum] ?? ''
                            ];
                        }

                        $timeslotModel = new ScheduleTimeslotModel();
                        $builder = $timeslotModel
                            ->whereIn('day', $activeDays)
                            ->where('is_active', 1);

                        if ($publishedSchedule['type'] !== 'manual') {
                            $builder->where('slot_type', 'kbm');
                        }

                        $timeslotsRaw = $builder->orderBy('slot_number', 'ASC')->findAll();

                        // Hitung batas jam kustom
                        $customHours = $publishedSchedule['custom_hours'] ? json_decode($publishedSchedule['custom_hours'], true) : [];
                        $maxSlotNumber = 0;
                        $filteredRaw = [];
                        foreach ($timeslotsRaw as $slot) {
                            $day = (int)$slot['day'];
                            $slotNum = (int)$slot['slot_number'];
                            if (isset($customHours[$day])) {
                                if ($slotNum > $customHours[$day]) {
                                    continue;
                                }
                            }
                            if ($slotNum > $maxSlotNumber) {
                                $maxSlotNumber = $slotNum;
                            }
                            $filteredRaw[] = $slot;
                        }

                        $schedulePeriods = [];
                        for ($i = 1; $i <= $maxSlotNumber; $i++) {
                            $startTime = '00:00';
                            $endTime = '00:00';
                            foreach ($filteredRaw as $slot) {
                                if ((int)$slot['slot_number'] === $i) {
                                    $startTime = $slot['start_time'];
                                    $endTime = $slot['end_time'];
                                    break;
                                }
                            }
                            $schedulePeriods[] = [
                                'period_number' => $i,
                                'start_time'    => $startTime,
                                'end_time'      => $endTime
                            ];
                        }

                        $rows = $db->table('schedule_entries se')
                            ->select('se.day as day_number, se.slot_number as period_number, ss.name as subject_name, t.name as teacher_name')
                            ->join('school_subjects ss', 'ss.id = se.school_subject_id')
                            ->join('teachers t', 't.id = se.teacher_id')
                            ->where('se.schedule_id', $publishedSchedule['id'])
                            ->where('se.classroom_id', $classroomId)
                            ->get()->getResultArray();

                        foreach ($rows as $row) {
                            $scheduleData[$row['day_number']][$row['period_number']] = $row;
                        }
                    }
                }
            }
        }

        $data = [
            'title'           => 'Jadwal Pelajaran Kelas',
            'histories'       => [],
            'selectedPeriod'  => $selectedPeriodId,
            'classroomInfo'   => $classroomInfo,
            'scheduleDays'    => $scheduleDays,
            'schedulePeriods' => $schedulePeriods,
            'scheduleData'    => $scheduleData,
            'customHours'     => $customHours ?? [],
        ];

        return view('siswa/schedule', $data);
    }

    // ── 4. NILAI LEGGER / RAPOR ───────────────────────────────
    public function grades()
    {
        $student = $this->getStudentOrRedirect();
        if ($student instanceof \CodeIgniter\HTTP\RedirectResponse) return $student;

        $db = \Config\Database::connect();
        
        // 1. Ambil semua tingkat kelas yang ada di sekolah secara urut
        $schoolGrades = $db->table('grades')
            ->select('id, name')
            ->where('deleted_at', null)
            ->orderBy('id', 'ASC')
            ->get()->getResultArray();

        // 2. Ambil semua data nilai siswa tersebut di database
        $rows = $db->table('student_grades sg')
            ->select('sg.score, ss.name as subject_name, c.grade_id, p.semester')
            ->join('school_subjects ss', 'ss.id = sg.school_subject_id')
            ->join('classrooms c', 'c.id = sg.classroom_id')
            ->join('academic_periods p', 'p.id = sg.academic_period_id')
            ->where('sg.student_id', $student['id'])
            ->get()->getResultArray();

        $matrix = [];
        $subjects = [];
        foreach ($rows as $row) {
            $subjName = $row['subject_name'];
            $subjects[$subjName] = true;
            $gradeId = $row['grade_id'];
            $sem = ($row['semester'] === 'Ganjil') ? 1 : 2;
            
            $matrix[$subjName][$gradeId][$sem] = $row['score'];
        }
        ksort($subjects);

        $data = [
            'title'        => 'Laporan Nilai Rapor (Legger)',
            'schoolGrades' => $schoolGrades,
            'subjects'     => array_keys($subjects),
            'matrix'       => $matrix,
        ];

        return view('siswa/grades', $data);
    }

    // ── 4. REKAP KEHADIRAN ─────────────────────────────────────
    public function attendance()
    {
        $student = $this->getStudentOrRedirect();
        if ($student instanceof \CodeIgniter\HTTP\RedirectResponse) return $student;

        $db = \Config\Database::connect();

        $activePeriod = $this->periodModel->getActive();
        $selectedPeriodId = $activePeriod['id'] ?? null;

        $attendanceStats = ['hadir' => 0, 'sakit' => 0, 'izin' => 0, 'alpha' => 0, 'persentase' => 100, 'efektif' => 0];
        $monthlyRecap = [];
        $detailedLogs = [];

        if ($selectedPeriodId) {
            // Ambil periode akademik terkait
            $period = $db->table('academic_periods')
                ->where('id', $selectedPeriodId)
                ->get()->getRowArray();

            if ($period) {
                $attModel = new AttendanceModel();

                // 1. Hitung total kumulatif presensi
                $sakit = $attModel->where('student_id', $student['id'])
                                  ->where('academic_period_id', $selectedPeriodId)
                                  ->where('status', 'Sakit')
                                  ->countAllResults();
                $izin = $attModel->where('student_id', $student['id'])
                                 ->where('academic_period_id', $selectedPeriodId)
                                  ->where('status', 'Izin')
                                  ->countAllResults();
                $alpha = $attModel->where('student_id', $student['id'])
                                  ->where('academic_period_id', $selectedPeriodId)
                                  ->where('status', 'Alpha')
                                  ->countAllResults();

                // Hitung efektif hari. Jika periode berakhir di masa depan, batasi efektif hari sampai hari ini.
                $endDate = $period['end_date'];
                if (strtotime($endDate) > time()) {
                    $endDate = date('Y-m-d');
                }
                $effectiveDays = $attModel->countActiveDays($period['start_date'], $endDate);
                if ($effectiveDays < 0) $effectiveDays = 0;

                if ($effectiveDays === 0) {
                    $hadir = 0;
                    $persentase = 100;
                } else {
                    $hadir = $effectiveDays - ($sakit + $izin + $alpha);
                    if ($hadir < 0) $hadir = 0;
                    $persentase = round(($hadir / $effectiveDays) * 100, 1);
                }

                $attendanceStats = [
                    'hadir'      => $hadir,
                    'sakit'      => $sakit,
                    'izin'       => $izin,
                    'alpha'      => $alpha,
                    'persentase' => $persentase,
                    'efektif'    => $effectiveDays
                ];

                // 2. Rincian Bulanan (Monthly Summary)
                // Kita buat list bulan dari start_date sampai end_date periode tersebut
                $start = new \DateTime($period['start_date']);
                $end = new \DateTime($period['end_date']);
                $interval = new \DateInterval('P1M');
                $dateRange = new \DatePeriod($start, $interval, $end->modify('+1 day'));

                foreach ($dateRange as $dt) {
                    $monthNum = $dt->format('m');
                    $yearNum = $dt->format('Y');
                    $monthName = $dt->format('F');

                    // Terjemahkan nama bulan ke Indonesia
                    $monthsIndo = [
                        'January' => 'Januari', 'February' => 'Februari', 'March' => 'Maret',
                        'April' => 'April', 'May' => 'Mei', 'June' => 'Juni',
                        'July' => 'Juli', 'August' => 'Agustus', 'September' => 'September',
                        'October' => 'Oktober', 'November' => 'November', 'December' => 'Desember'
                    ];
                    $monthLabel = $monthsIndo[$monthName] ?? $monthName;

                    // Cari rentang tanggal bulan tersebut dalam semester
                    $firstOfMonth = date("$yearNum-$monthNum-01");
                    $lastOfMonth = date("$yearNum-$monthNum-t");

                    // Batasi dengan tanggal mulai dan selesai semester
                    $startQueryDate = max($period['start_date'], $firstOfMonth);
                    $endQueryDate = min($period['end_date'], $lastOfMonth);

                    // Batasi juga dengan hari ini agar tidak menghitung masa depan
                    if (strtotime($endQueryDate) > time()) {
                        $endQueryDate = date('Y-m-d');
                    }

                    if (strtotime($startQueryDate) <= strtotime($endQueryDate)) {
                        $mSakit = $attModel->where('student_id', $student['id'])
                                           ->where('academic_period_id', $selectedPeriodId)
                                           ->where('status', 'Sakit')
                                           ->where('date >=', $startQueryDate)
                                           ->where('date <=', $endQueryDate)
                                           ->countAllResults();

                        $mIzin = $attModel->where('student_id', $student['id'])
                                          ->where('academic_period_id', $selectedPeriodId)
                                          ->where('status', 'Izin')
                                          ->where('date >=', $startQueryDate)
                                          ->where('date <=', $endQueryDate)
                                          ->countAllResults();

                        $mAlpha = $attModel->where('student_id', $student['id'])
                                           ->where('academic_period_id', $selectedPeriodId)
                                           ->where('status', 'Alpha')
                                           ->where('date >=', $startQueryDate)
                                           ->where('date <=', $endQueryDate)
                                           ->countAllResults();

                        $mEffective = $attModel->countActiveDays($startQueryDate, $endQueryDate);
                        $mHadir = $mEffective - ($mSakit + $mIzin + $mAlpha);
                        if ($mHadir < 0) $mHadir = 0;

                        if ($mEffective > 0) {
                            $monthlyRecap[] = [
                                'month_name' => $monthLabel . ' ' . $yearNum,
                                'hadir'      => $mHadir,
                                'sakit'      => $mSakit,
                                'izin'       => $mIzin,
                                'alpha'      => $mAlpha,
                                'efektif'    => $mEffective
                            ];
                        }
                    }
                }

                // 3. Detail Logs Ketidakhadiran (Hanya status selain Hadir)
                $detailedLogs = $db->table('attendances a')
                    ->select('a.date, a.status, u.name as recorder_name')
                    ->join('users u', 'u.id = a.recorded_by', 'left')
                    ->where('a.student_id', $student['id'])
                    ->where('a.academic_period_id', $selectedPeriodId)
                    ->whereIn('a.status', ['Sakit', 'Izin', 'Alpha'])
                    ->orderBy('a.date', 'DESC')
                    ->get()->getResultArray();
            }
        }

        $data = [
            'title'           => 'Laporan Kehadiran Siswa',
            'histories'       => [],
            'selectedPeriod'  => $selectedPeriodId,
            'attendanceStats' => $attendanceStats,
            'monthlyRecap'    => $monthlyRecap,
            'detailedLogs'    => $detailedLogs,
        ];

        return view('siswa/attendance', $data);
    }

    // ── 5. UBAH PASSWORD MANDIRI ──────────────────────────────
    public function changePassword()
    {
        $this->getStudentOrRedirect();

        return view('siswa/change_password', [
            'title' => 'Ubah Password Akun'
        ]);
    }

    public function changePasswordProcess()
    {
        $userId = session()->get('user_id');
        if (!$userId) return redirect()->to('/login');

        $rules = [
            'new_password'     => 'required|min_length[6]',
            'confirm_password' => 'required|matches[new_password]',
        ];

        if (!$this->validate($rules)) {
            return redirect()->back()->withInput()->with('errors', $this->validator->getErrors());
        }

        $newPass = $this->request->getPost('new_password');
        
        $this->userModel->update($userId, [
            'password'          => password_hash($newPass, PASSWORD_DEFAULT),
            'is_password_reset' => 0
        ]);

        log_activity('update', 'siswa_portal_password', session()->get('student_id'), "Siswa mengubah password login akun mandiri");

        return redirect()->to('/siswa/dashboard')->with('success', 'Password Anda berhasil diperbarui!');
    }

    // ── 6. POIN PELANGGARAN SISWA ──────────────────────────────
    public function violations()
    {
        $student = $this->getStudentOrRedirect();
        if ($student instanceof \CodeIgniter\HTTP\RedirectResponse) return $student;

        $activePeriod = $this->periodModel->getActive();
        if (!$activePeriod) {
            return redirect()->to('/siswa/dashboard')->with('error', 'Semester aktif tidak ditemukan.');
        }

        $violationModel = new \App\Models\StudentViolationModel();
        $sanctionModel  = new \App\Models\ViolationSanctionModel();

        $points = $violationModel->getAccumulatedPoints($student['id'], $activePeriod['id']);
        $sanction = $sanctionModel->getActiveSanction($points);
        $logs = $violationModel->getLogsByStudent($student['id'], $activePeriod['id']);

        // Dapatkan batas sanksi berikutnya untuk progress bar
        $nextSanction = $sanctionModel->where('min_points >', $points)->orderBy('min_points', 'ASC')->first();

        $data = [
            'title'        => 'Poin & Riwayat Pelanggaran',
            'student'      => $student,
            'points'       => $points,
            'sanction'     => $sanction,
            'nextSanction' => $nextSanction,
            'logs'         => $logs,
            'activePeriod' => $activePeriod,
        ];

        return view('siswa/violations', $data);
    }

    // ── TAHFIDZ AL-QUR'AN SISWA ──────────────────────────────────────
    public function tahfidz()
    {
        $student = $this->getStudentOrRedirect();
        if ($student instanceof \CodeIgniter\HTTP\RedirectResponse) return $student;

        $activePeriod = $this->periodModel->getActive();
        if (!$activePeriod) {
            return redirect()->to('/siswa/dashboard')->with('error', 'Semester aktif tidak ditemukan.');
        }

        $db = \Config\Database::connect();
        
        // Ambil program tahfidz yang diikuti siswa pada periode aktif ini
        $programs = $db->query("
            SELECT tp.*
            FROM tahfidz_programs tp
            JOIN tahfidz_program_students tps ON tps.program_id = tp.id
            WHERE tps.student_id = ?
              AND tp.academic_period_id = ?
              AND tp.deleted_at IS NULL
              AND tp.is_active = 1
        ", [$student['id'], $activePeriod['id']])->getResultArray();

        // Tentukan program yang aktif/terpilih
        $selectedProgramId = $this->request->getGet('program_id') ? (int) $this->request->getGet('program_id') : null;
        $selectedProgram = null;
        if (!empty($programs)) {
            if ($selectedProgramId) {
                foreach ($programs as $p) {
                    if ($p['id'] == $selectedProgramId) {
                        $selectedProgram = $p;
                        break;
                    }
                }
            }
            if (!$selectedProgram) {
                $selectedProgram = $programs[0];
            }
        }

        // Variabel penampung data
        $totalHafal    = 0;
        $avgNilai      = 0.0;
        $progressJuz   = [];
        $recentSetoran = [];
        $lastSetoran   = null;

        if ($selectedProgram) {
            $setoranModel = new \App\Models\TahfidzSetoranModel();
            $hafalanModel = new \App\Models\TahfidzHafalanModel();

            $totalHafal    = $hafalanModel->countHafal($student['id'], $selectedProgram['id']);
            $avgNilai      = $setoranModel->getAvgNilai($student['id'], $selectedProgram['id']);
            $progressJuz   = $hafalanModel->getProgressPerJuz($student['id'], $selectedProgram['id']);
            $recentSetoran = $setoranModel->getByStudentProgram($student['id'], $selectedProgram['id']);
            if (!empty($recentSetoran)) {
                $lastSetoran = $recentSetoran[0];
            }
        }

        return view('siswa/tahfidz', [
            'title'             => 'Laporan Tahfidz Al-Qur\'an',
            'student'           => $student,
            'activePeriod'      => $activePeriod,
            'programs'          => $programs,
            'selectedProgram'   => $selectedProgram,
            'totalHafal'        => $totalHafal,
            'avgNilai'          => $avgNilai,
            'progressJuz'       => $progressJuz,
            'recentSetoran'     => $recentSetoran,
            'lastSetoran'       => $lastSetoran,
        ]);
    }
}
