<?php

namespace App\Models\SelfPaced;

use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;

/**
 * Course Model
 *
 * Core entity of the self-paced portal. Stores course content metadata,
 * fee, duration, exam settings, and publication status.
 *
 * @property int $id
 * @property string $title
 * @property string $slug
 * @property string $description
 * @property string|null $objectives
 * @property string|null $prerequisites
 * @property string|null $featured_image
 * @property int|null $category_id
 * @property int|null $instructor_id
 * @property float $fee_amount
 * @property string $currency
 * @property int $duration_hours
 * @property int $passing_score
 * @property int $exam_attempts_allowed
 * @property int $exam_time_limit
 * @property int $exam_questions_per_attempt
 * @property string $status
 * @property int|null $created_by
 * @property int|null $updated_by
 * @property \Illuminate\Support\Carbon|null $deleted_at
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 */
class Course extends Model
{
    use SoftDeletes;

    protected $table = 'self_paced_courses';

    protected $fillable = [
        'title',
        'slug',
        'description',
        'objectives',
        'prerequisites',
        'featured_image',
        'category_id',
        'instructor_id',
        'fee_amount',
        'currency',
        'duration_hours',
        'passing_score',
        'exam_attempts_allowed',
        'exam_time_limit',
        'exam_questions_per_attempt',
        'status',
        'created_by',
        'updated_by',
        // New payment fields
        'payment_mode',
        'registration_fee',
        'application_fee',
        'certificate_fee',
        'certificate_collection_mode',
        'book_path',
        'book_file_name',
        'book_file_size',
        'book_fee',
        'exam_failure_fee',
        'max_exam_attempts',
    ];

    protected $casts = [
        'fee_amount'               => 'decimal:2',
        'duration_hours'           => 'integer',
        'passing_score'            => 'integer',
        'exam_attempts_allowed'    => 'integer',
        'exam_time_limit'          => 'integer',
        'exam_questions_per_attempt' => 'integer',
        // New payment field casts
        'registration_fee'         => 'decimal:2',
        'application_fee'          => 'decimal:2',
        'certificate_fee'          => 'decimal:2',
        'book_fee'                 => 'decimal:2',
        'exam_failure_fee'         => 'decimal:2',
        'book_file_size'           => 'integer',
        'max_exam_attempts'        => 'integer',
        'deleted_at'               => 'datetime',
        'created_at'               => 'datetime',
        'updated_at'               => 'datetime',
    ];

    protected $attributes = [
        'fee_amount'               => 0.00,
        'currency'                 => 'UGX',
        'duration_hours'           => 0,
        'passing_score'            => 70,
        'exam_attempts_allowed'    => 3,
        'exam_time_limit'          => 60,
        'exam_questions_per_attempt' => 10,
        'status'                   => 'draft',
    ];

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

    public function category(): BelongsTo
    {
        return $this->belongsTo(CourseCategory::class, 'category_id');
    }

    public function instructor(): BelongsTo
    {
        return $this->belongsTo(User::class, 'instructor_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 topics(): HasMany
    {
        return $this->hasMany(CourseTopic::class, 'course_id')->orderBy('sort_order');
    }

    public function downloads(): HasMany
    {
        return $this->hasMany(CourseDownload::class, 'course_id');
    }

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

    public function examQuestions(): HasMany
    {
        return $this->hasMany(ExamQuestion::class, 'course_id');
    }

    public function examAttempts(): HasMany
    {
        return $this->hasMany(ExamAttempt::class, 'course_id');
    }

    public function examResults(): HasMany
    {
        return $this->hasMany(ExamResult::class, 'course_id');
    }

    public function certificates(): HasMany
    {
        return $this->hasMany(SelfPacedCertificate::class, 'course_id');
    }

    public function bookPurchases(): HasMany
    {
        return $this->hasMany(BookPurchase::class, 'course_id');
    }

    public function resitPayments(): HasMany
    {
        return $this->hasMany(ResitPayment::class, 'course_id');
    }

    public function certificatePayments(): HasMany
    {
        return $this->hasMany(CertificatePayment::class, 'course_id');
    }

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

    public function scopePublished($query)
    {
        return $query->where('status', 'published');
    }

    public function scopeDraft($query)
    {
        return $query->where('status', 'draft');
    }

    public function scopeArchived($query)
    {
        return $query->where('status', 'archived');
    }

    public function scopeFree($query)
    {
        return $query->where('fee_amount', 0);
    }

    public function scopePaid($query)
    {
        return $query->where('fee_amount', '>', 0);
    }

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

    public function isFree(): bool
    {
        return (float) $this->fee_amount === 0.0;
    }

    public function isPublished(): bool
    {
        return $this->status === 'published';
    }

    public function hasActiveEnrollments(): bool
    {
        return $this->enrollments()->whereIn('status', ['active', 'pending_payment'])->exists();
    }

    public function getActiveEnrollmentsCount(): int
    {
        return $this->enrollments()->where('status', 'active')->count();
    }

    public function getFormattedFee(): string
    {
        if ($this->isFree()) {
            return 'Free';
        }

        return number_format((float) $this->fee_amount, 0) . ' ' . $this->currency;
    }

    public function getFormattedDuration(): string
    {
        if ($this->duration_hours <= 0) {
            return 'Not specified';
        }

        return $this->duration_hours . ' ' . str('hour')->plural($this->duration_hours);
    }

    /** Exam time limit in seconds (for timer calculations). */
    public function getExamTimeLimitSeconds(): int
    {
        return $this->exam_time_limit * 60;
    }

    /**
     * Get total enrollment fee (registration + application)
     *
     * @return float
     */
    public function getTotalEnrollmentFee(): float
    {
        return (float)($this->registration_fee ?? 0) + (float)($this->application_fee ?? 0);
    }

    /**
     * Check if course is free (no registration or application fee)
     *
     * @return bool
     */
    public function isFreeToEnroll(): bool
    {
        return $this->getTotalEnrollmentFee() === 0.0;
    }

    /**
     * Check if course has a book available
     *
     * @return bool
     */
    public function hasBook(): bool
    {
        return $this->book_path !== null;
    }

    /**
     * Check if course book is free
     *
     * @return bool
     */
    public function hasFreeBook(): bool
    {
        return $this->hasBook() && ((float)$this->book_fee === 0.0);
    }

    /**
     * Check if certificates are self-downloadable
     *
     * @return bool
     */
    public function isSelfDownloadCertificate(): bool
    {
        return $this->certificate_collection_mode === 'self_download';
    }

    /**
     * Check if course accepts online (Paystack) payments
     *
     * @return bool
     */
    public function acceptsOnlinePayment(): bool
    {
        return in_array($this->payment_mode, ['online', 'both']);
    }

    /**
     * Check if course accepts cash payments
     *
     * @return bool
     */
    public function acceptsCashPayment(): bool
    {
        return in_array($this->payment_mode, ['cash', 'both']);
    }
}
