<?php

namespace App\Domain\Participant\Models;

use App\Domain\Identity\Models\Guardian;
use App\Domain\Identity\Models\Person;
use App\Domain\Participant\Enums\MembershipType;
use App\Domain\Participant\Enums\ParticipantStatus;
use App\Domain\Participant\Enums\RegistrationSource;
use App\Domain\Participant\Enums\SkillLevel;
use App\Domain\Shared\Traits\Auditable;
use App\Domain\Shared\Traits\BelongsToBranch;
use App\Domain\Shared\Traits\BelongsToAcademy;
use App\Domain\Shared\Traits\HasUuid;
use App\Domain\Training\Models\Activity;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Relations\MorphOne;
use Illuminate\Database\Eloquent\SoftDeletes;

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

    protected $fillable = [
        'academy_id',
        'branch_id',
        'person_id',
        'participant_number',
        'registration_date',
        'registration_source',
        'referred_by_id',
        'primary_guardian_id',
        'primary_activity_id',
        'skill_level',
        'medical_clearance',
        'medical_clearance_expires',
        'photo_path',
        'jersey_number',
        'jersey_size',
        'shoe_size',
        'dominant_hand',
        'dominant_foot',
        'height_cm',
        'weight_kg',
        'status',
        'status_changed_at',
        'status_reason',
        'is_free',
        'membership_type',
        'membership_id',
        'membership_expires_at',
        'total_paid',
        'outstanding_balance',
        'metadata',
        'notes',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'status' => ParticipantStatus::class,
        'registration_source' => RegistrationSource::class,
        'skill_level' => SkillLevel::class,
        'membership_type' => MembershipType::class,
        'registration_date' => 'date',
        'medical_clearance' => 'boolean',
        'medical_clearance_expires' => 'date',
        'status_changed_at' => 'datetime',
        'membership_expires_at' => 'date',
        'total_paid' => 'integer',
        'outstanding_balance' => 'integer',
        'height_cm' => 'decimal:1',
        'weight_kg' => 'decimal:1',
        'is_free' => 'boolean',
        'metadata' => 'array',
        'jersey_number' => 'integer',
    ];

    // ─── Relationships ────────────────────────────────────────

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

    public function primaryGuardian(): BelongsTo
    {
        return $this->belongsTo(Guardian::class, 'primary_guardian_id');
    }

    public function guardians(): BelongsToMany
    {
        return $this->belongsToMany(Guardian::class, 'guardian_participant')
            ->withPivot('relationship_type', 'is_primary', 'is_emergency_contact', 'can_pickup', 'receives_notifications', 'can_authorize_payment', 'created_at');
    }

    public function primaryActivity(): BelongsTo
    {
        return $this->belongsTo(Activity::class, 'primary_activity_id');
    }

    public function referredBy(): BelongsTo
    {
        return $this->belongsTo(self::class, 'referred_by_id');
    }

    public function referrals(): HasMany
    {
        return $this->hasMany(self::class, 'referred_by_id');
    }

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

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

    public function enrollments(): HasMany
    {
        return $this->hasMany(\App\Domain\Training\Models\Enrollment::class);
    }

    public function activeEnrollments(): HasMany
    {
        return $this->hasMany(\App\Domain\Training\Models\Enrollment::class)
            ->where('status', 'active');
    }

    public function branch(): BelongsTo
    {
        return $this->belongsTo(\App\Domain\Identity\Models\Branch::class);
    }

    public function wallet(): MorphOne
    {
        return $this->morphOne(\App\Domain\Financial\Models\Wallet::class, 'owner');
    }

    public function invoices(): MorphMany
    {
        return $this->morphMany(\App\Domain\Financial\Models\Invoice::class, 'billable');
    }

    public function payments(): MorphMany
    {
        return $this->morphMany(\App\Domain\Financial\Models\Payment::class, 'payer');
    }

    public function attendanceRecords(): MorphMany
    {
        return $this->morphMany(\App\Domain\Attendance\Models\AttendanceRecord::class, 'subject');
    }

    public function documents(): MorphMany
    {
        return $this->morphMany(\App\Domain\Document\Models\Document::class, 'documentable');
    }

    public function posTransactions(): HasMany
    {
        return $this->hasMany(\App\Domain\POS\Models\POSTransaction::class);
    }

    public function evaluations(): HasMany
    {
        return $this->hasMany(\App\Domain\Training\Models\Evaluation::class);
    }

    // ─── Accessors ────────────────────────────────────────────

    public function getFullNameAttribute(): string
    {
        return $this->person?->name_ar ?? $this->person?->name ?? '';
    }

    public function getFullNameEnAttribute(): string
    {
        return $this->person?->name ?? $this->person?->name_ar ?? '';
    }

    public function getAgeAttribute(): ?int
    {
        return $this->person?->date_of_birth?->age;
    }

    // ─── Scopes ───────────────────────────────────────────────

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

    public function scopeCanAttend($query)
    {
        return $query->whereIn('status', [
            ParticipantStatus::Active->value,
        ]);
    }
}
