<?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\HasMany;

class Debt extends Model
{
    use HasFactory;

    protected $fillable = [
        'customer_id',
        'sale_id',
        'debt_number',
        'total_debt_amount',
        'paid_amount',
        'remaining_amount',
        'status',
        'due_date',
        'notes',
    ];

    protected $casts = [
        'debt_number' => 'string',
        'total_debt_amount' => 'decimal:2',
        'paid_amount' => 'decimal:2',
        'remaining_amount' => 'decimal:2',
        'due_date' => 'date',
    ];

    // Debt status constants
    const STATUS_PENDING = 'pending';

    const STATUS_PARTIAL = 'partial';

    const STATUS_PAID = 'paid';

    const DEBT_STATUSES = [
        ['id' => 'pending', 'name' => 'En attente', 'slug' => 'pending'],
        ['id' => 'partial', 'name' => 'Partiellement payé', 'slug' => 'partial'],
        ['id' => 'paid', 'name' => 'Payé', 'slug' => 'paid'],
    ];

    public function getRouteKeyName()
    {
        return 'debt_number';
    }

    /**
     * Get the customer that owns the debt.
     */
    public function customer(): BelongsTo
    {
        return $this->belongsTo(Customer::class);
    }

    /**
     * Get the sale that created this debt.
     */
    public function sale(): BelongsTo
    {
        return $this->belongsTo(Sale::class);
    }

    /**
     * Get all debt payments for this debt.
     */
    public function payments(): HasMany
    {
        return $this->hasMany(DebtPayment::class);
    }

    /**
     * Get the formatted total debt amount.
     */
    public function getFormattedTotalDebtAmountAttribute(): string
    {
        return number_format($this->total_debt_amount, 0, ',', ' ') . ' ' . \App\Models\Setting::DEFAULT_CURRENCY;
    }

    /**
     * Get the formatted paid amount.
     */
    public function getFormattedPaidAmountAttribute(): string
    {
        return number_format($this->paid_amount, 0, ',', ' ') . ' ' . \App\Models\Setting::DEFAULT_CURRENCY;
    }

    /**
     * Get the formatted remaining amount.
     */
    public function getFormattedRemainingAmountAttribute(): string
    {
        return number_format($this->remaining_amount, 0, ',', ' ') . ' ' . \App\Models\Setting::DEFAULT_CURRENCY;
    }

    /**
     * Get the debt status label.
     */
    public function getStatusLabelAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_PENDING => 'En attente',
            self::STATUS_PARTIAL => 'Partiellement payé',
            self::STATUS_PAID => 'Payé',
            default => 'Inconnu',
        };
    }

    /**
     * Get the debt status color class.
     */
    public function getStatusColorAttribute(): string
    {
        return match ($this->status) {
            self::STATUS_PENDING => 'bg-yellow-100 text-yellow-800',
            self::STATUS_PARTIAL => 'bg-blue-100 text-blue-800',
            self::STATUS_PAID => 'bg-green-100 text-green-800',
            default => 'bg-gray-100 text-gray-800',
        };
    }

    /**
     * Check if the debt is overdue.
     */
    public function isOverdue(): bool
    {
        return $this->due_date && $this->due_date->isPast() && $this->status !== self::STATUS_PAID;
    }

    /**
     * Get the days until due date (negative if overdue).
     */
    public function getDaysUntilDueAttribute(): int
    {
        if (! $this->due_date) {
            return 0;
        }

        return now()->diffInDays($this->due_date, false);
    }

    /**
     * Update the debt status based on paid amount.
     */
    public function updateStatus(): void
    {
        if ($this->paid_amount >= $this->total_debt_amount) {
            $this->status = self::STATUS_PAID;
            $this->remaining_amount = 0;
        } elseif ($this->paid_amount > 0) {
            $this->status = self::STATUS_PARTIAL;
            $this->remaining_amount = $this->total_debt_amount - $this->paid_amount;
        } else {
            $this->status = self::STATUS_PENDING;
            $this->remaining_amount = $this->total_debt_amount;
        }

        $this->save();
    }

    /**
     * Add a payment to this debt.
     */
    public function addPayment(float $amount, ?string $notes = null): DebtPayment
    {
        $payment = $this->payments()->create([
            'amount' => $amount,
            'notes' => $notes,
            'payment_date' => now(),
        ]);

        $this->paid_amount += $amount;
        $this->updateStatus();

        return $payment;
    }

    /**
     * Scope to get debts by status.
     */
    public function scopeByStatus($query, string $status)
    {
        return $query->where('status', $status);
    }

    /**
     * Scope to get overdue debts.
     */
    public function scopeOverdue($query)
    {
        return $query->where('due_date', '<', now())
            ->where('status', '!=', self::STATUS_PAID);
    }

    /**
     * Scope to get debts for a specific customer.
     */
    public function scopeForCustomer($query, int $customerId)
    {
        return $query->where('customer_id', $customerId);
    }

    /**
     * Get the debt reference number.
     */

    public static function generateUniqueDebtNumber()
    {
        // Prefix: SL + YYYYMMDD
        $prefix = 'DBT' . date('Ymd');

        // Find the last sale for today (sequence resets daily)
        $lastSaleToday = Debt::where('debt_number', 'like', $prefix . '%')
            ->orderBy('debt_number', 'desc')
            ->first();

        $lastSequence = $lastSaleToday
            ? (int) substr($lastSaleToday->debt_number, strlen($prefix))
            : 0;

        return $prefix . str_pad((string) ($lastSequence + 1), 5, '0', STR_PAD_LEFT);
    }

    public function getStatusBadge()
    {
        return match ($this->status) {
            self::STATUS_PAID => '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800 border border-green-500 min-w-30 justify-center"><i class="ph ph-check-circle mr-1"></i>Payé</span>',
            self::STATUS_PARTIAL => '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800 border border-blue-500 min-w-30 justify-center"><i class="ph ph-x-circle mr-1"></i>Partiellement payé</span>',
            default => '<span class="inline-flex items-center px-2.5 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800 border border-yellow-500 min-w-30 justify-center">En attente</span>'
        };
    }
}
