<?php

namespace App\Models\Mentorship;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Application extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * The table associated with the model.
     */
    protected $table = 'mentorship_applications';

    /**
     * The attributes that are mass assignable.
     */
    protected $fillable = [
        'programme_id',
        'category_id',
        'name',
        'email',
        'phone',
        'country',
        'city',
        'address',
        'occupation',
        'organization',
        'education_level',
        'bio',
        'role_preference',
        'areas_of_interest',
        'skills',
        'experience',
        'motivation',
        'expectations',
        'expertise_areas',
        'years_of_experience',
        'mentoring_experience',
        'availability',
        'learning_goals',
        'preferred_mentor_qualities',
        'time_commitment',
        'status',
        'payment_required',
        'payment_amount',
        'payment_currency',
        'payment_status',
        'payment_reference',
        'payment_phone',
        'payment_method',
        'payment_initiated_at',
        'payment_completed_at',
        'payment_details',
        'user_id',
        'reviewed_by',
        'reviewed_at',
        'review_notes',
        'rejection_reason',
        'additional_notes',
        'custom_fields',
        'documents',
        'profile_image',
        'source',
        'utm_source',
        'utm_campaign',
        'terms_accepted',
        'privacy_accepted',
        'consent_at',
    ];

    /**
     * The attributes that should be cast.
     */
    protected $casts = [
        'areas_of_interest' => 'array',
        'skills' => 'array',
        'custom_fields' => 'array',
        'documents' => 'array',
        'payment_details' => 'array',
        'payment_required' => 'boolean',
        'payment_amount' => 'decimal:2',
        'terms_accepted' => 'boolean',
        'privacy_accepted' => 'boolean',
        'reviewed_at' => 'datetime',
        'payment_initiated_at' => 'datetime',
        'payment_completed_at' => 'datetime',
        'consent_at' => 'datetime',
    ];

    /*
    |--------------------------------------------------------------------------
    | Status Constants
    |--------------------------------------------------------------------------
    */

    const STATUS_PENDING = 'pending';
    const STATUS_UNDER_REVIEW = 'under_review';
    const STATUS_APPROVED = 'approved';
    const STATUS_REJECTED = 'rejected';
    const STATUS_WAITLISTED = 'waitlisted';
    const STATUS_WITHDRAWN = 'withdrawn';
    const STATUS_PAYMENT_PENDING = 'payment_pending';

    /*
    |--------------------------------------------------------------------------
    | Payment Status Constants
    |--------------------------------------------------------------------------
    */

    const PAYMENT_PENDING = 'pending';
    const PAYMENT_PROCESSING = 'processing';
    const PAYMENT_PAID = 'paid';
    const PAYMENT_FAILED = 'failed';
    const PAYMENT_REFUNDED = 'refunded';

    /*
    |--------------------------------------------------------------------------
    | Role Preference Constants
    |--------------------------------------------------------------------------
    */

    const ROLE_MENTOR = 'mentor';
    const ROLE_MENTEE = 'mentee';

    /*
    |--------------------------------------------------------------------------
    | Relationships
    |--------------------------------------------------------------------------
    */

    /**
     * Get the programme for this application.
     */
    public function programme()
    {
        return $this->belongsTo(Programme::class, 'programme_id');
    }

    /**
     * Get the category for this application.
     */
    public function category()
    {
        return $this->belongsTo(Category::class, 'category_id');
    }

    /**
     * Get the user account created from this application.
     */
    public function user()
    {
        return $this->belongsTo(\App\Models\User::class, 'user_id');
    }

    /**
     * Get the user who reviewed this application.
     */
    public function reviewer()
    {
        return $this->belongsTo(\App\Models\User::class, 'reviewed_by');
    }

    /**
     * Get the payments for this application.
     */
    public function payments()
    {
        return $this->hasMany(Payment::class, 'application_id');
    }

    /**
     * Get the assignment as mentor (if approved as mentor).
     */
    public function mentorAssignment()
    {
        return $this->hasOne(Assignment::class, 'mentor_application_id');
    }

    /**
     * Get the assignment as mentee (if approved as mentee).
     */
    public function menteeAssignment()
    {
        return $this->hasOne(Assignment::class, 'mentee_application_id');
    }

    /*
    |--------------------------------------------------------------------------
    | Scopes
    |--------------------------------------------------------------------------
    */

    /**
     * Scope to get pending applications.
     */
    public function scopePending($query)
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * Scope to get approved applications.
     */
    public function scopeApproved($query)
    {
        return $query->where('status', self::STATUS_APPROVED);
    }

    /**
     * Scope to get rejected applications.
     */
    public function scopeRejected($query)
    {
        return $query->where('status', self::STATUS_REJECTED);
    }

    /**
     * Scope to get applications for a specific programme.
     */
    public function scopeForProgramme($query, $programmeId)
    {
        return $query->where('programme_id', $programmeId);
    }

    /**
     * Scope to get applications by role preference.
     */
    public function scopeByRole($query, $role)
    {
        return $query->where('role_preference', $role);
    }

    /**
     * Scope to get mentor applications.
     */
    public function scopeMentors($query)
    {
        return $query->where('role_preference', self::ROLE_MENTOR);
    }

    /**
     * Scope to get mentee applications.
     */
    public function scopeMentees($query)
    {
        return $query->where('role_preference', self::ROLE_MENTEE);
    }

    /**
     * Scope to get applications requiring payment.
     */
    public function scopeRequiresPayment($query)
    {
        return $query->where('payment_required', true)
            ->where('payment_status', '!=', self::PAYMENT_PAID);
    }

    /*
    |--------------------------------------------------------------------------
    | Accessors & Mutators
    |--------------------------------------------------------------------------
    */

    /**
     * Get the status label.
     */
    public function getStatusLabelAttribute(): string
    {
        return match($this->status) {
            self::STATUS_PENDING => 'Pending Review',
            self::STATUS_UNDER_REVIEW => 'Under Review',
            self::STATUS_APPROVED => 'Approved',
            self::STATUS_REJECTED => 'Rejected',
            self::STATUS_WAITLISTED => 'Waitlisted',
            self::STATUS_WITHDRAWN => 'Withdrawn',
            self::STATUS_PAYMENT_PENDING => 'Payment Pending',
            default => ucfirst($this->status),
        };
    }

    /**
     * Get the status color for badges.
     */
    public function getStatusColorAttribute(): string
    {
        return match($this->status) {
            self::STATUS_PENDING => 'yellow',
            self::STATUS_UNDER_REVIEW => 'blue',
            self::STATUS_APPROVED => 'green',
            self::STATUS_REJECTED => 'red',
            self::STATUS_WAITLISTED => 'orange',
            self::STATUS_WITHDRAWN => 'gray',
            self::STATUS_PAYMENT_PENDING => 'purple',
            default => 'gray',
        };
    }

    /**
     * Get the role preference label.
     */
    public function getRoleLabelAttribute(): string
    {
        return ucfirst($this->role_preference);
    }

    /**
     * Get the formatted payment amount.
     */
    public function getFormattedPaymentAmountAttribute(): string
    {
        if (!$this->payment_required) {
            return 'N/A';
        }

        return number_format($this->payment_amount, 2) . ' ' . $this->payment_currency;
    }

    /*
    |--------------------------------------------------------------------------
    | Helper Methods
    |--------------------------------------------------------------------------
    */

    /**
     * Check if the application is pending.
     */
    public function isPending(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * Check if the application is approved.
     */
    public function isApproved(): bool
    {
        return $this->status === self::STATUS_APPROVED;
    }

    /**
     * Check if the application is rejected.
     */
    public function isRejected(): bool
    {
        return $this->status === self::STATUS_REJECTED;
    }

    /**
     * Check if payment is required.
     */
    public function requiresPayment(): bool
    {
        return $this->payment_required && $this->payment_status !== self::PAYMENT_PAID;
    }

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

    /**
     * Check if application can be approved.
     */
    public function canBeApproved(): bool
    {
        if (!in_array($this->status, [self::STATUS_PENDING, self::STATUS_UNDER_REVIEW, self::STATUS_WAITLISTED])) {
            return false;
        }

        if ($this->requiresPayment()) {
            return false;
        }

        return true;
    }

    /**
     * Check if application can be rejected.
     */
    public function canBeRejected(): bool
    {
        return in_array($this->status, [self::STATUS_PENDING, self::STATUS_UNDER_REVIEW, self::STATUS_WAITLISTED]);
    }

    /**
     * Mark as under review.
     */
    public function markAsUnderReview(int $reviewerId): bool
    {
        return $this->update([
            'status' => self::STATUS_UNDER_REVIEW,
            'reviewed_by' => $reviewerId,
            'reviewed_at' => now(),
        ]);
    }

    /**
     * Approve the application.
     */
    public function approve(int $reviewerId, ?string $notes = null): bool
    {
        return $this->update([
            'status' => self::STATUS_APPROVED,
            'reviewed_by' => $reviewerId,
            'reviewed_at' => now(),
            'review_notes' => $notes,
        ]);
    }

    /**
     * Reject the application.
     */
    public function reject(int $reviewerId, string $reason, ?string $notes = null): bool
    {
        return $this->update([
            'status' => self::STATUS_REJECTED,
            'reviewed_by' => $reviewerId,
            'reviewed_at' => now(),
            'rejection_reason' => $reason,
            'review_notes' => $notes,
        ]);
    }

    /**
     * Mark as payment pending.
     */
    public function markPaymentPending(): bool
    {
        return $this->update([
            'status' => self::STATUS_PAYMENT_PENDING,
            'payment_status' => self::PAYMENT_PROCESSING,
            'payment_initiated_at' => now(),
        ]);
    }

    /**
     * Mark payment as completed.
     */
    public function markPaymentCompleted(string $reference, array $details = []): bool
    {
        return $this->update([
            'payment_status' => self::PAYMENT_PAID,
            'payment_reference' => $reference,
            'payment_completed_at' => now(),
            'payment_details' => $details,
            'status' => self::STATUS_PENDING, // Ready for review
        ]);
    }

    /**
     * Withdraw the application.
     */
    public function withdraw(): bool
    {
        return $this->update(['status' => self::STATUS_WITHDRAWN]);
    }
}
