<?php

namespace App\Models;

use CodeIgniter\Model;

class AssessmentScoreModel extends Model
{
    protected $table            = 'assessment_scores';
    protected $primaryKey       = 'id';
    protected $useAutoIncrement = true;
    protected $returnType       = 'array';
    protected $useSoftDeletes   = false;
    protected $allowedFields    = [
        'assessment_id', 'student_id', 'classroom_id', 'subject_id',
        'jawaban_pg', 'jawaban_bs',
        'skor_pg', 'skor_bs', 'skor_isian', 'skor_essay',
        'nilai_akhir',
        'notif_pg', 'notif_bs',
    ];

    protected $useTimestamps = true;
    protected $createdField  = 'created_at';
    protected $updatedField  = 'updated_at';

    protected $beforeInsert = ['checkPeriodIsActive'];
    protected $beforeUpdate = ['checkPeriodIsActive'];
    protected $beforeDelete = ['checkPeriodIsActiveDelete'];

    protected function checkPeriodIsActive(array $data)
    {
        $assessmentId = $data['data']['assessment_id'] ?? null;
        if (!$assessmentId && isset($data['id'])) {
            $record = $this->find($data['id'][0] ?? $data['id']);
            $assessmentId = $record['assessment_id'] ?? null;
        }

        if ($assessmentId) {
            $db = \Config\Database::connect();
            $assessment = $db->table('assessments')
                ->select('academic_period_id')
                ->where('id', $assessmentId)
                ->get()
                ->getRowArray();
                
            $periodId = $assessment['academic_period_id'] ?? null;

            if ($periodId && !is_period_active($periodId)) {
                $role = session()->get('user_role');
                if (!in_array($role, ['superadmin', 'admin'])) {
                    throw new \RuntimeException('Periode akademik untuk asesmen ini telah ditutup. Data tidak dapat diubah!');
                }
            }
        }

        return $data;
    }

    protected function checkPeriodIsActiveDelete(array $data)
    {
        $id = $data['id'][0] ?? $data['id'] ?? null;
        if ($id) {
            $record = $this->find($id);
            $assessmentId = $record['assessment_id'] ?? null;
            if ($assessmentId) {
                $db = \Config\Database::connect();
                $assessment = $db->table('assessments')
                    ->select('academic_period_id')
                    ->where('id', $assessmentId)
                    ->get()
                    ->getRowArray();
                    
                $periodId = $assessment['academic_period_id'] ?? null;
                if ($periodId && !is_period_active($periodId)) {
                    $role = session()->get('user_role');
                    if (!in_array($role, ['superadmin', 'admin'])) {
                        throw new \RuntimeException('Periode akademik untuk asesmen ini telah ditutup. Data tidak dapat dihapus!');
                    }
                }
            }
        }
        return $data;
    }

    /**
     * Ambil semua skor untuk 1 assessment + 1 kelas + 1 mapel
     * Termasuk data siswa
     */
    public function getScoresByAssessmentAndClass($assessmentId, $classroomId, $subjectId)
    {
        return $this->select('assessment_scores.*, students.full_name, students.nis, students.nisn')
                    ->join('students', 'students.id = assessment_scores.student_id')
                    ->where('assessment_scores.assessment_id', $assessmentId)
                    ->where('assessment_scores.classroom_id', $classroomId)
                    ->where('assessment_scores.subject_id', $subjectId)
                    ->where('students.deleted_at', null)
                    ->orderBy('students.full_name', 'ASC')
                    ->findAll();
    }

    /**
     * Ambil skor 1 siswa untuk 1 assessment + kelas + mapel
     */
    public function getScore($assessmentId, $studentId, $classroomId, $subjectId)
    {
        return $this->where('assessment_id', $assessmentId)
                    ->where('student_id', $studentId)
                    ->where('classroom_id', $classroomId)
                    ->where('subject_id', $subjectId)
                    ->first();
    }

    /**
     * Upsert skor siswa
     */
    public function saveScore($assessmentId, $studentId, $classroomId, $subjectId, $data)
    {
        $existing = $this->getScore($assessmentId, $studentId, $classroomId, $subjectId);

        $data['assessment_id'] = $assessmentId;
        $data['student_id']    = $studentId;
        $data['classroom_id']  = $classroomId;
        $data['subject_id']    = $subjectId;

        if ($existing) {
            return $this->update($existing['id'], $data);
        }

        return $this->insert($data);
    }

    /**
     * Ambil semua skor (lama, tanpa classroom/subject filter)
     */
    public function getScoresByAssessment($assessmentId)
    {
        return $this->select('assessment_scores.*, students.full_name, students.nis')
                    ->join('students', 'students.id = assessment_scores.student_id')
                    ->where('assessment_id', $assessmentId)
                    ->orderBy('students.full_name', 'ASC')
                    ->findAll();
    }

    /**
     * Ambil daftar siswa di kelas + status sudah/belum dikoreksi
     * untuk 1 assessment + 1 kelas + 1 mapel
     */
    public function getStudentsWithStatus($assessmentId, $classroomId, $subjectId, $periodId)
    {
        $db = \Config\Database::connect();

        // Ambil siswa yang ada di kelas ini pada periode ini
        $students = $db->table('student_academic_histories sah')
            ->select('students.id, students.nis, students.nisn, students.full_name, students.gender')
            ->join('students', 'students.id = sah.student_id')
            ->where('sah.classroom_id', $classroomId)
            ->where('sah.academic_period_id', $periodId)
            ->where('students.deleted_at', null)
            ->orderBy('students.full_name', 'ASC')
            ->get()->getResultArray();

        if (empty($students)) return [];

        // Ambil skor yang sudah ada
        $scores = $this->where('assessment_id', $assessmentId)
                       ->where('classroom_id', $classroomId)
                       ->where('subject_id', $subjectId)
                       ->findAll();

        // Index skor berdasarkan student_id
        $scoreMap = [];
        foreach ($scores as $score) {
            $scoreMap[$score['student_id']] = $score;
        }

        // Gabungkan
        $result = [];
        foreach ($students as $student) {
            $result[] = array_merge($student, [
                'score' => $scoreMap[$student['id']] ?? null,
            ]);
        }

        return $result;
    }

    /**
     * Cek apakah semua siswa di kelas ini sudah dikoreksi
     */
    public function isAllKoreksi($assessmentId, $classroomId, $subjectId, $periodId)
    {
        $students = $this->getStudentsWithStatus($assessmentId, $classroomId, $subjectId, $periodId);
        if (empty($students)) return false;

        foreach ($students as $s) {
            if ($s['score'] === null || $s['score']['nilai_akhir'] === null) {
                return false;
            }
        }

        return true;
    }

    public function countStudentsInClass($classroomId, $periodId)
    {
        $db = \Config\Database::connect();
        return $db->table('student_academic_histories sah')
                  ->join('students', 'students.id = sah.student_id')
                  ->where('sah.classroom_id', $classroomId)
                  ->where('sah.academic_period_id', $periodId)
                  ->where('students.deleted_at', null)
                  ->countAllResults();
    }

    public function countGradedStudents($assessmentId, $classroomId, $subjectId)
    {
        return $this->where('assessment_id', $assessmentId)
                    ->where('classroom_id', $classroomId)
                    ->where('subject_id', $subjectId)
                    ->where('nilai_akhir IS NOT NULL')
                    ->countAllResults();
    }
}