<?php

namespace App\Domain\Training\Models;

use App\Domain\Identity\Models\Branch;
use App\Domain\Shared\Traits\Auditable;
use App\Domain\Shared\Traits\BelongsToAcademy;
use App\Domain\Shared\Traits\HasUuid;
use App\Domain\Shared\Traits\ManglesUniqueOnDelete;
use App\Domain\Training\Enums\ProgramStatus;
use App\Domain\Training\Enums\RenewalPolicy;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Domain\Shared\Traits\BelongsToBranch;

class TrainingProgram extends Model
{
    use BelongsToAcademy, HasUuid, SoftDeletes, Auditable, ManglesUniqueOnDelete, BelongsToBranch;

    protected array $uniqueFieldsToMangle = ['slug'];

    protected $fillable = [
        'academy_id', 'activity_id', 'branch_id', 'default_trainer_id',
        'name', 'name_ar', 'slug', 'description', 'description_ar',
        'objectives', 'skill_level', 'age_min', 'age_max', 'gender',
        'sessions_per_week', 'session_duration_minutes', 'total_sessions', 'program_duration_weeks',
        'min_participants', 'max_participants', 'allow_waitlist',
        'attendance_requirement_percent', 'assessment_required',
        'prerequisites', 'facility_type', 'equipment_required',
        'registration_open', 'registration_deadline',
        'program_start_date', 'program_end_date',
        'renewal_policy', 'billing_cycle', 'billing_day', 'cancellation_policy', 'refund_policy',
        'status', 'featured', 'sort_order', 'metadata', 'created_by',
    ];

    protected $casts = [
        'status' => ProgramStatus::class,
        'renewal_policy' => RenewalPolicy::class,
        'billing_day' => 'integer',
        'objectives' => 'array',
        'prerequisites' => 'array',
        'equipment_required' => 'array',
        'metadata' => 'array',
        'age_min' => 'integer',
        'age_max' => 'integer',
        'sessions_per_week' => 'integer',
        'session_duration_minutes' => 'integer',
        'total_sessions' => 'integer',
        'program_duration_weeks' => 'integer',
        'min_participants' => 'integer',
        'max_participants' => 'integer',
        'allow_waitlist' => 'boolean',
        'attendance_requirement_percent' => 'integer',
        'assessment_required' => 'boolean',
        'registration_open' => 'boolean',
        'registration_deadline' => 'date',
        'program_start_date' => 'date',
        'program_end_date' => 'date',
        'featured' => 'boolean',
        'sort_order' => 'integer',
    ];

    public function activity(): BelongsTo
    {
        return $this->belongsTo(Activity::class);
    }

    public function branch(): BelongsTo
    {
        return $this->belongsTo(Branch::class);
    }

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

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

    public function groups(): HasMany
    {
        return $this->hasMany(TrainingGroup::class, 'training_program_id');
    }

    /**
     * Products a participant must buy to be properly enrolled in this
     * programme. Unlike products.is_essential (a global flag) this is per
     * programme, so a "فرق" team can require a registration card while an
     * academy-hour programme does not.
     */
    public function bundledProducts()
    {
        return $this->belongsToMany(
            \App\Domain\Inventory\Models\Product::class,
            'program_products',
            'training_program_id',
            'product_id'
        )->withPivot(['is_required', 'quantity'])->withTimestamps();
    }

    /**
     * Kits a participant must buy to be properly enrolled — the same obligation
     * as bundledProducts(), for a set sold as one thing.
     */
    public function bundledKits()
    {
        return $this->belongsToMany(
            \App\Domain\Inventory\Models\Kit::class,
            'program_kits',
            'training_program_id',
            'kit_id'
        )->withPivot(['is_required', 'quantity'])->withTimestamps();
    }

    public function enrollments(): HasMany
    {
        return $this->hasMany(Enrollment::class, 'training_program_id');
    }

    /**
     * The group the programme is created with. Most programmes are run as a
     * single squad and never grow a second group, so this is where their weekly
     * timetable lives. Oldest first, so opening a second group later never
     * moves the schedule out from under the form that wrote it.
     */
    public function defaultGroup(): ?TrainingGroup
    {
        return $this->groups()->orderBy('id')->first();
    }

    public function scopeActive($query)
    {
        return $query->where('status', ProgramStatus::Active);
    }

    public function scopeOpen($query)
    {
        return $query->where('registration_open', true)->where('status', ProgramStatus::Active);
    }
}
