<?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 RecurringInstance extends Model
{
    use HasFactory, SoftDeletes;

    protected $fillable = [
        'user_id',
        'recurring_template_id',
        'occurrence_number',
        'due_date',
        'planned_amount',
        'status',
        'transaction_id',
        'paid_at',
        'paid_amount',
        'paid_notes',
    ];

    protected $casts = [
        'due_date' => 'date',
        'paid_at' => 'datetime',
        'planned_amount' => 'decimal:2',
        'paid_amount' => 'decimal:2',
        'occurrence_number' => 'integer',
    ];

    public const STATUS_PENDING = 'pending';
    public const STATUS_PAID = 'paid';
    public const STATUS_SKIPPED = 'skipped';
    public const STATUS_CANCELLED = 'cancelled';

    // ============================================
    // Relacionamentos
    // ============================================

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

    public function template(): BelongsTo
    {
        return $this->belongsTo(RecurringTemplate::class, 'recurring_template_id');
    }

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

    // ============================================
    // Scopes
    // ============================================

    public function scopePending($query)
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    public function scopePaid($query)
    {
        return $query->where('status', self::STATUS_PAID);
    }

    public function scopeOverdue($query)
    {
        return $query->where('status', self::STATUS_PENDING)
            ->where('due_date', '<', now()->startOfDay());
    }

    public function scopeDueSoon($query, int $days = 7)
    {
        return $query->where('status', self::STATUS_PENDING)
            ->whereBetween('due_date', [
                now()->startOfDay(),
                now()->addDays($days)->endOfDay()
            ]);
    }

    // ============================================
    // Métodos de Negócio
    // ============================================

    /**
     * Verifica se está vencida
     */
    public function isOverdue(): bool
    {
        return $this->status === self::STATUS_PENDING 
            && $this->due_date->lt(now()->startOfDay());
    }

    /**
     * Verifica se está paga
     */
    public function isPaid(): bool
    {
        return $this->status === self::STATUS_PAID;
    }

    /**
     * Verifica se está pendente
     */
    public function isPending(): bool
    {
        return $this->status === self::STATUS_PENDING;
    }

    /**
     * Retorna a diferença entre valor planejado e pago
     */
    public function getDifferenceAttribute(): ?float
    {
        if ($this->paid_amount === null) {
            return null;
        }
        return (float) $this->paid_amount - (float) $this->planned_amount;
    }

    /**
     * Retorna dias até o vencimento (negativo se vencido)
     */
    public function getDaysUntilDueAttribute(): int
    {
        return (int) now()->startOfDay()->diffInDays($this->due_date, false);
    }

    /**
     * Retorna status formatado
     */
    public function getStatusLabelAttribute(): string
    {
        return match($this->status) {
            self::STATUS_PENDING => 'Pendente',
            self::STATUS_PAID => 'Pago',
            self::STATUS_SKIPPED => 'Pulado',
            self::STATUS_CANCELLED => 'Cancelado',
            default => $this->status,
        };
    }
}
