<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Cupon extends Model
{
    protected $table = 'cupones';

    public const TIPO_PORCENTAJE = 'porcentaje';

    public const TIPO_MONTO_FIJO = 'monto_fijo';

    public const ORIGEN_MANUAL = 'manual';

    public const ORIGEN_SISTEMA = 'sistema';

    protected $fillable = [
        'codigo', 'tipo', 'porcentaje', 'monto', 'fecha_inicio', 'fecha_fin',
        'usos_maximos', 'usos_actuales', 'activo', 'origen',
    ];

    protected function casts(): array
    {
        return [
            'porcentaje' => 'decimal:2',
            'monto' => 'decimal:2',
            'fecha_inicio' => 'date',
            'fecha_fin' => 'date',
            'activo' => 'boolean',
        ];
    }

    public function esPorcentaje(): bool
    {
        return $this->tipo === self::TIPO_PORCENTAJE;
    }

    /**
     * Monto de descuento a aplicar sobre una base determinada.
     * Para "monto fijo" nunca excede la base (evita subtotales negativos).
     */
    public function calcularDescuento(float $base): float
    {
        if ($this->esPorcentaje()) {
            return round($base * ((float) $this->porcentaje / 100), 2);
        }

        return round(min((float) $this->monto, $base), 2);
    }

    public function etiquetaDescuento(): string
    {
        return $this->esPorcentaje()
            ? number_format($this->porcentaje, 2).'%'
            : number_format($this->monto, 2).' (monto fijo)';
    }

    public function esValido(): bool
    {
        if (! $this->activo) {
            return false;
        }

        $hoy = now()->toDateString();

        if ($this->fecha_inicio && $hoy < $this->fecha_inicio->toDateString()) {
            return false;
        }

        if ($this->fecha_fin && $hoy > $this->fecha_fin->toDateString()) {
            return false;
        }

        if ($this->usos_maximos !== null && $this->usos_actuales >= $this->usos_maximos) {
            return false;
        }

        return true;
    }

    public function motivoInvalidez(): ?string
    {
        if (! $this->activo) {
            return 'El cupón está inactivo.';
        }

        $hoy = now()->toDateString();

        if ($this->fecha_inicio && $hoy < $this->fecha_inicio->toDateString()) {
            return 'El cupón todavía no está vigente.';
        }

        if ($this->fecha_fin && $hoy > $this->fecha_fin->toDateString()) {
            return 'El cupón ya venció.';
        }

        if ($this->usos_maximos !== null && $this->usos_actuales >= $this->usos_maximos) {
            return 'El cupón alcanzó su límite de usos.';
        }

        return null;
    }
}
