<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

/**
 * Per-student record tracking the promotion lifecycle for a single
 * school year transition (see plan sections 3, 6, 9, 11).
 *
 * Promotion eligibility lives here separately from the actual class
 * assignment – the student is only "Promoted and Enrolled" once the
 * parent finishes enrollment for the next school year.
 */
class StudentPromotionRecord extends BaseModel
{
    protected $table = 'student_promotion_records';
    protected $primaryKey = 'promotion_id';

    public $timestamps = true;

    public const STATUS_NOT_REVIEWED = 'not_reviewed';
    public const STATUS_ELIGIBLE = 'eligible_for_promotion';
    public const STATUS_AWAITING_PARENT = 'awaiting_parent_enrollment';
    public const STATUS_ENROLLMENT_STARTED = 'enrollment_started';
    public const STATUS_PROMOTED_AND_ENROLLED = 'promoted_and_enrolled';
    public const STATUS_CONDITIONAL = 'conditional_promotion';
    public const STATUS_REPEATED = 'repeated_level';
    public const STATUS_ON_HOLD = 'on_hold';
    public const STATUS_WITHDRAWN = 'withdrawn';
    public const STATUS_GRADUATED = 'graduated';
    public const STATUS_NOT_ENROLLED = 'not_enrolled_for_next_year';

    public const ENROLLMENT_NOT_STARTED = 'not_started';
    public const ENROLLMENT_IN_PROGRESS = 'in_progress';
    public const ENROLLMENT_COMPLETED = 'completed';
    public const ENROLLMENT_EXPIRED = 'expired';

    public const ALL_STATUSES = [
        self::STATUS_NOT_REVIEWED,
        self::STATUS_ELIGIBLE,
        self::STATUS_AWAITING_PARENT,
        self::STATUS_ENROLLMENT_STARTED,
        self::STATUS_PROMOTED_AND_ENROLLED,
        self::STATUS_CONDITIONAL,
        self::STATUS_REPEATED,
        self::STATUS_ON_HOLD,
        self::STATUS_WITHDRAWN,
        self::STATUS_GRADUATED,
        self::STATUS_NOT_ENROLLED,
    ];

    protected $fillable = [
        'student_id',
        'parent_id',
        'current_school_year',
        'next_school_year',
        'current_level_id',
        'promoted_level_id',
        'current_level_name',
        'promoted_level_name',
        'promotion_status',
        'passed_current_level',
        'final_average',
        'attendance_ok',
        'eligibility_notes',
        'enrollment_required',
        'enrollment_status',
        'enrollment_id',
        'parent_notified_at',
        'enrollment_deadline',
        'enrollment_started_at',
        'enrollment_completed_at',
        'promotion_finalized_at',
        'info_confirmed',
        'documents_uploaded',
        'agreement_accepted',
        'payment_completed',
        'updated_by',
    ];

    protected $casts = [
        'student_id' => 'integer',
        'parent_id' => 'integer',
        'current_level_id' => 'integer',
        'promoted_level_id' => 'integer',
        'passed_current_level' => 'boolean',
        'final_average' => 'float',
        'attendance_ok' => 'boolean',
        'enrollment_required' => 'boolean',
        'enrollment_id' => 'integer',
        'parent_notified_at' => 'datetime',
        'enrollment_deadline' => 'date',
        'enrollment_started_at' => 'datetime',
        'enrollment_completed_at' => 'datetime',
        'promotion_finalized_at' => 'datetime',
        'info_confirmed' => 'boolean',
        'documents_uploaded' => 'boolean',
        'agreement_accepted' => 'boolean',
        'payment_completed' => 'boolean',
        'updated_by' => 'integer',
    ];

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

    public function parent(): BelongsTo
    {
        return $this->belongsTo(User::class, 'parent_id');
    }

    public function enrollment(): BelongsTo
    {
        return $this->belongsTo(Enrollment::class, 'enrollment_id');
    }

    public function scopeForNextYear(Builder $q, string $year): Builder
    {
        return $q->where('next_school_year', $year);
    }

    public function scopeStatus(Builder $q, string $status): Builder
    {
        return $q->where('promotion_status', $status);
    }

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

    public function scopeForParent(Builder $q, int $parentId): Builder
    {
        return $q->where('parent_id', $parentId);
    }

    /**
     * Statuses the parent portal should treat as "actionable" (parent
     * can still complete enrollment).
     */
    public static function parentActionableStatuses(): array
    {
        return [
            self::STATUS_ELIGIBLE,
            self::STATUS_AWAITING_PARENT,
            self::STATUS_ENROLLMENT_STARTED,
        ];
    }

    /**
     * Statuses considered "open" for the next school year (admin views
     * may want to filter on these).
     */
    public static function openStatuses(): array
    {
        return [
            self::STATUS_NOT_REVIEWED,
            self::STATUS_ELIGIBLE,
            self::STATUS_AWAITING_PARENT,
            self::STATUS_ENROLLMENT_STARTED,
            self::STATUS_CONDITIONAL,
            self::STATUS_ON_HOLD,
        ];
    }

    public function isFinalized(): bool
    {
        return in_array(
            $this->promotion_status,
            [
                self::STATUS_PROMOTED_AND_ENROLLED,
                self::STATUS_REPEATED,
                self::STATUS_WITHDRAWN,
                self::STATUS_GRADUATED,
                self::STATUS_NOT_ENROLLED,
            ],
            true
        );
    }

    public function enrollmentChecklistComplete(): bool
    {
        // Mirrors plan section 8 – parent-side completion criteria.
        // Payment is only required when payment_completed has been
        // explicitly set; treat null/false as still required by default.
        return (bool) $this->info_confirmed
            && (bool) $this->documents_uploaded
            && (bool) $this->agreement_accepted
            && (bool) $this->payment_completed;
    }
}
