<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasOne;

/**
 * TrainingRegistration Model
 *
 * Tracks user enrollment in training programs including status,
 * payment information, and completion details.
 *
 * @property int $id
 * @property int $user_id
 * @property int $training_package_id
 * @property \Illuminate\Support\Carbon $registration_date
 * @property string $status
 * @property \Illuminate\Support\Carbon|null $status_updated_at
 * @property string $payment_status
 * @property string|null $payment_reference
 * @property string|null $payment_method
 * @property float $amount_paid
 * @property \Illuminate\Support\Carbon|null $payment_date
 * @property int|null $approved_by
 * @property int|null $rejected_by
 * @property string|null $rejection_reason
 * @property \Illuminate\Support\Carbon|null $approved_at
 * @property \Illuminate\Support\Carbon|null $rejected_at
 * @property string $registration_source
 * @property int|null $registered_by
 * @property \Illuminate\Support\Carbon|null $completion_date
 * @property float $attendance_percentage
 * @property float|null $score
 * @property bool|null $passed
 * @property bool $certificate_issued
 * @property int|null $certificate_id
 * @property string|null $notes
 * @property array|null $metadata
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 */
class TrainingRegistration extends Model
{
    use HasFactory;

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'training_registrations';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'user_id',
        'training_package_id',
        'registration_date',
        'status',
        'status_updated_at',
        'payment_status',
        'payment_reference',
        'payment_method',
        'amount_paid',
        'amount_due',
        'payment_date',
        'approved_by',
        'rejected_by',
        'rejection_reason',
        'approved_at',
        'rejected_at',
        'registration_source',
        'registered_by',
        'completion_date',
        'attendance_percentage',
        'score',
        'passed',
        'certificate_issued',
        'certificate_id',
        'notes',
        'metadata',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'registration_date'    => 'datetime',
        'status_updated_at'    => 'datetime',
        'payment_date'         => 'datetime',
        'approved_at'          => 'datetime',
        'rejected_at'          => 'datetime',
        'completion_date'      => 'datetime',
        'amount_paid'          => 'decimal:2',
        'amount_due'           => 'decimal:2',
        'attendance_percentage'=> 'decimal:2',
        'score'                => 'decimal:2',
        'passed'               => 'boolean',
        'certificate_issued'   => 'boolean',
        'metadata'             => 'array',
        'created_at'           => 'datetime',
        'updated_at'           => 'datetime',
    ];

    /**
     * The model's default values for attributes.
     *
     * @var array
     */
    protected $attributes = [
        'status'                => 'pending',
        'payment_status'        => 'not_required',
        // 'public' is used for web registrations; 'dashboard' for internal; 'admin' for admin-created
        'registration_source'   => 'dashboard',
        'attendance_percentage' => 0.00,
        'amount_paid'           => 0.00,
        'amount_due'            => 0.00,
        'certificate_issued'    => false,
    ];

    // =========================================================================
    // RELATIONSHIPS
    // =========================================================================

    /**
     * Get the user who registered.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * Get the training package.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function trainingPackage(): BelongsTo
    {
        return $this->belongsTo(TrainingPackage::class, 'training_package_id');
    }

    /**
     * Get the user who approved this registration.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function approver(): BelongsTo
    {
        return $this->belongsTo(User::class, 'approved_by');
    }

    /**
     * Get the user who rejected this registration.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function rejector(): BelongsTo
    {
        return $this->belongsTo(User::class, 'rejected_by');
    }

    /**
     * Get the user who registered this person (if registered by someone else).
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function registrar(): BelongsTo
    {
        return $this->belongsTo(User::class, 'registered_by');
    }

    /**
     * Get the certificate for this registration.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function certificate(): BelongsTo
    {
        return $this->belongsTo(TrainingCertificate::class, 'certificate_id');
    }

    /**
     * Alias for trainingPackage relationship (for view compatibility).
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function package(): BelongsTo
    {
        return $this->belongsTo(TrainingPackage::class, 'training_package_id');
    }

    // =========================================================================
    // QUERY SCOPES
    // =========================================================================

    /**
     * Scope to get pending registrations.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePending($query)
    {
        return $query->where('status', 'pending');
    }

    /**
     * Scope to get approved registrations.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeApproved($query)
    {
        return $query->where('status', 'approved');
    }

    /**
     * Scope to get completed registrations.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeCompleted($query)
    {
        return $query->where('status', 'completed');
    }

    /**
     * Scope to get registrations by status.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $status
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeWithStatus($query, string $status)
    {
        return $query->where('status', $status);
    }

    /**
     * Scope to get registrations requiring payment.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeRequiresPayment($query)
    {
        return $query->where('payment_status', 'pending');
    }

    /**
     * Scope to get paid registrations.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePaid($query)
    {
        return $query->where('payment_status', 'completed');
    }

    /**
     * Scope to get registrations for a specific training package.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $packageId
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeForPackage($query, int $packageId)
    {
        return $query->where('training_package_id', $packageId);
    }

    /**
     * Scope to get registrations for a specific user.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $userId
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeForUser($query, int $userId)
    {
        return $query->where('user_id', $userId);
    }

    // =========================================================================
    // HELPER METHODS
    // =========================================================================

    /**
     * Check if registration is pending.
     *
     * @return bool
     */
    public function isPending(): bool
    {
        return $this->status === 'pending';
    }

    /**
     * Check if registration is approved.
     *
     * @return bool
     */
    public function isApproved(): bool
    {
        return $this->status === 'approved';
    }

    /**
     * Check if registration is completed.
     *
     * @return bool
     */
    public function isCompleted(): bool
    {
        return $this->status === 'completed';
    }

    /**
     * Check if registration is rejected.
     *
     * @return bool
     */
    public function isRejected(): bool
    {
        return $this->status === 'rejected';
    }

    /**
     * Check if payment is required.
     *
     * @return bool
     */
    public function requiresPayment(): bool
    {
        return $this->payment_status !== 'not_required';
    }

    /**
     * Check if payment is completed.
     *
     * @return bool
     */
    public function isPaid(): bool
    {
        return $this->payment_status === 'completed';
    }

    /**
     * Check if payment is pending.
     *
     * @return bool
     */
    public function paymentPending(): bool
    {
        return in_array($this->payment_status, ['pending', 'processing']);
    }

    /**
     * Check if registration is from public website.
     *
     * @return bool
     */
    public function isFromPublic(): bool
    {
        return $this->registration_source === 'public';
    }

    /**
     * Check if certificate has been issued.
     *
     * @return bool
     */
    public function hasCertificate(): bool
    {
        return $this->certificate_issued && $this->certificate_id !== null;
    }

    /**
     * Approve the registration.
     *
     * @param int $approverId
     * @return bool
     */
    public function approve(int $approverId): bool
    {
        return $this->update([
            'status' => 'approved',
            'status_updated_at' => now(),
            'approved_by' => $approverId,
            'approved_at' => now(),
        ]);
    }

    /**
     * Reject the registration.
     *
     * @param int $rejectorId
     * @param string $reason
     * @return bool
     */
    public function reject(int $rejectorId, string $reason): bool
    {
        return $this->update([
            'status' => 'rejected',
            'status_updated_at' => now(),
            'rejected_by' => $rejectorId,
            'rejected_at' => now(),
            'rejection_reason' => $reason,
        ]);
    }

    /**
     * Mark as completed.
     *
     * @param float $attendancePercentage
     * @param float|null $score
     * @param bool|null $passed
     * @return bool
     */
    public function markCompleted(float $attendancePercentage, ?float $score = null, ?bool $passed = null): bool
    {
        return $this->update([
            'status' => 'completed',
            'status_updated_at' => now(),
            'completion_date' => now(),
            'attendance_percentage' => $attendancePercentage,
            'score' => $score,
            'passed' => $passed,
        ]);
    }

    /**
     * Update payment status.
     *
     * @param string $status
     * @param string|null $reference
     * @param float|null $amount
     * @return bool
     */
    public function updatePaymentStatus(string $status, ?string $reference = null, ?float $amount = null): bool
    {
        $data = [
            'payment_status'   => $status,
            'status_updated_at'=> now(),
        ];

        if ($reference) {
            $data['payment_reference'] = $reference;
        }

        if ($amount !== null) {
            $data['amount_paid'] = $amount;
        }

        if ($status === 'completed') {
            $data['payment_date'] = now();
            // Clear amount_due once paid
            $data['amount_due'] = 0.00;
        }

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

    /**
     * Mark certificate as issued.
     *
     * @param int $certificateId
     * @return bool
     */
    public function markCertificateIssued(int $certificateId): bool
    {
        return $this->update([
            'certificate_issued' => true,
            'certificate_id' => $certificateId,
        ]);
    }

    /**
     * Get the status badge color for UI.
     *
     * @return string
     */
    public function getStatusBadgeColor(): string
    {
        return match($this->status) {
            'pending' => 'yellow',
            'approved' => 'blue',
            'completed' => 'green',
            'rejected' => 'red',
            'waitlisted' => 'orange',
            'cancelled' => 'gray',
            default => 'gray',
        };
    }

    /**
     * Get the payment status badge color for UI.
     *
     * @return string
     */
    public function getPaymentStatusBadgeColor(): string
    {
        return match($this->payment_status) {
            'not_required' => 'gray',
            'pending' => 'yellow',
            'processing' => 'blue',
            'completed' => 'green',
            'failed' => 'red',
            'refunded' => 'orange',
            default => 'gray',
        };
    }
}
