<?php

namespace App\Models;

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

class ContributionFee extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'membership_category_id',
        'name',
        'description',
        'amount',
        'currency',
        'cycle',
        'is_optional',
        'is_active',
        'due_day',
        'effective_from',
        'effective_until',
        'created_by',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'amount' => 'decimal:2',
        'is_optional' => 'boolean',
        'is_active' => 'boolean',
        'due_day' => 'integer',
        'effective_from' => 'date',
        'effective_until' => 'date',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * Get the membership category for the contribution fee.
     */
    public function membershipCategory(): BelongsTo
    {
        return $this->belongsTo(MembershipCategory::class);
    }

    /**
     * Get the user who created the fee.
     */
    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    /**
     * Scope a query to only include active fees.
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope a query to only include mandatory fees.
     */
    public function scopeMandatory($query)
    {
        return $query->where('is_optional', false);
    }

    /**
     * Scope a query to only include optional fees.
     */
    public function scopeOptional($query)
    {
        return $query->where('is_optional', true);
    }

    /**
     * Get formatted amount with currency.
     */
    public function getFormattedAmountAttribute(): string
    {
        $symbols = [
            'USD' => '$',
            'SSP' => '£',
            'KES' => 'KSh',
            'UGX' => 'USh',
        ];

        $symbol = $symbols[$this->currency] ?? $this->currency . ' ';
        return $symbol . number_format($this->amount, 2);
    }

    /**
     * Get cycle display name.
     */
    public function getCycleDisplayAttribute(): string
    {
        return match($this->cycle) {
            'monthly' => 'Monthly',
            'quarterly' => 'Quarterly',
            'biannual' => 'Bi-annually',
            'annual' => 'Annually',
            default => ucfirst($this->cycle),
        };
    }

    /**
     * Calculate next due date from a given date.
     */
    public function calculateNextDueDate(\Carbon\Carbon $fromDate = null): \Carbon\Carbon
    {
        $fromDate = $fromDate ?? now();
        
        return match($this->cycle) {
            'monthly' => $fromDate->copy()->addMonth()->setDay($this->due_day),
            'quarterly' => $fromDate->copy()->addMonths(3)->setDay($this->due_day),
            'biannual' => $fromDate->copy()->addMonths(6)->setDay($this->due_day),
            'annual' => $fromDate->copy()->addYear()->setDay($this->due_day),
            default => $fromDate->copy()->addMonth()->setDay($this->due_day),
        };
    }

    /**
     * Get period label for a specific date.
     */
    public function getPeriodLabel(\Carbon\Carbon $date): string
    {
        return match($this->cycle) {
            'monthly' => $date->format('F Y'),
            'quarterly' => 'Q' . ceil($date->month / 3) . ' ' . $date->year,
            'biannual' => 'H' . (ceil($date->month / 6)) . ' ' . $date->year,
            'annual' => $date->year,
            default => $date->format('F Y'),
        };
    }
}
