<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use App\Models\BaseModel;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class SemesterScore extends BaseModel
{
    protected $table = 'semester_scores';

    protected $fillable = [
        'student_id',
        'school_id',
        'class_section_id',
        'updated_by',
        'homework_avg',
        'quiz_avg',
        'project_avg',
        'midterm_exam_score',
        'final_exam_score',
        'attendance_score',
        'participation_score',
        'ptap_score',
        'test_avg',
        'semester_score',
        'semester',
        'school_year',
        'created_at',
        'updated_at',
    ];

    /**
     * If your table has created_at/updated_at columns, keep this true (default).
     * If it does NOT, set to false.
     */
    public $timestamps = true;

    protected $casts = [
        'student_id'        => 'integer',
        'school_id'         => 'integer',
        'class_section_id'  => 'integer',
        'updated_by'        => 'integer',

        // averages/scores: keep decimal to avoid float drift
        'homework_avg'        => 'decimal:2',
        'quiz_avg'            => 'decimal:2',
        'project_avg'         => 'decimal:2',
        'midterm_exam_score'  => 'decimal:2',
        'final_exam_score'    => 'decimal:2',
        'attendance_score'    => 'decimal:2',
        'participation_score' => 'decimal:2',
        'ptap_score'          => 'decimal:2',
        'test_avg'            => 'decimal:2',
        'semester_score'      => 'decimal:2',

        'created_at'        => 'datetime',
        'updated_at'        => 'datetime',
    ];

    /* ============================================================
     * Relationships (optional)
     * ============================================================
     */

    public function student(): BelongsTo
    {
        return $this->belongsTo(Student::class, 'student_id');
    }

    public function classSection(): BelongsTo
    {
        return $this->belongsTo(ClassSection::class, 'class_section_id');
    }

    public function school(): BelongsTo
    {
        return $this->belongsTo(School::class, 'school_id');
    }

    public function updater(): BelongsTo
    {
        // Change Admin/User model to match your app
        return $this->belongsTo(Admin::class, 'updated_by');
    }

    /* ============================================================
     * Scopes
     * ============================================================
     */

    public function scopeForStudent(Builder $q, int $studentId): Builder
    {
        return $q->where('student_id', $studentId);
    }

    public function scopeForTerm(Builder $q, string $semester, string $schoolYear): Builder
    {
        return $q->where('semester', $semester)
                 ->where('school_year', $schoolYear);
    }

    public function scopeForClassSection(Builder $q, ?int $classSectionId): Builder
    {
        return $classSectionId !== null
            ? $q->where('class_section_id', $classSectionId)
            : $q;
    }

    /* ============================================================
     * Upsert (Laravel style)
     * ============================================================
     */

    /**
     * True upsert (update or create) by (student_id, semester, school_year).
     * Returns the saved model or null if required keys missing.
     */
    public static function upsertScore(array $data): ?self
    {
        if (empty($data['student_id']) || empty($data['semester']) || empty($data['school_year'])) {
            return null;
        }

        $keys = [
            'student_id'  => (int) $data['student_id'],
            'semester'    => (string) $data['semester'],
            'school_year' => (string) $data['school_year'],
        ];

        // Update fields: only allow fillable keys
        $payload = array_intersect_key($data, array_flip((new static)->getFillable()));

        return static::updateOrCreate($keys, $payload);
    }

    /**
     * CI-compatible boolean wrapper (matches your CI upsert(): bool).
     */
    public static function upsertBool(array $data): bool
    {
        return (bool) static::upsertScore($data);
    }

    /* ============================================================
     * Optional validation helper (FormRequest/controller)
     * ============================================================
     */

    public static function rules(bool $updating = false): array
    {
        $required = $updating ? 'sometimes' : 'required';

        return [
            'student_id'       => [$required, 'integer', 'min:1'],
            'semester'         => [$required, 'string', 'max:20'],
            'school_year'      => [$required, 'string', 'max:20'],

            'school_id'        => ['nullable', 'integer', 'min:1'],
            'class_section_id' => ['nullable', 'integer', 'min:1'],
            'updated_by'       => ['nullable', 'integer', 'min:1'],

            'homework_avg'        => ['nullable', 'numeric', 'min:0'],
            'quiz_avg'            => ['nullable', 'numeric', 'min:0'],
            'project_avg'         => ['nullable', 'numeric', 'min:0'],
            'midterm_exam_score'  => ['nullable', 'numeric', 'min:0'],
            'final_exam_score'    => ['nullable', 'numeric', 'min:0'],
            'attendance_score'    => ['nullable', 'numeric', 'min:0'],
            'participation_score' => ['nullable', 'numeric', 'min:0'],
            'ptap_score'          => ['nullable', 'numeric', 'min:0'],
            'test_avg'            => ['nullable', 'numeric', 'min:0'],
            'semester_score'      => ['nullable', 'numeric', 'min:0'],
        ];
    }
}