<?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;
use Illuminate\Database\Eloquent\Relations\HasMany;

class EsercizioContabile extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'esercizi_contabili';

    protected $fillable = [
        'stabile_id',
        'descrizione',
        'anno',
        'data_inizio',
        'data_fine',
        'tipologia',
        'descrizione_straordinaria',
        'ordine_sequenza',
        'stato',
        'chiusa_contabilita',
        'data_limite_bilancio',
        'approvato_assemblea',
        'data_approvazione',
        'assemblea_id',
        'esercizio_precedente_id',
    ];

    protected $casts = [
        'data_inizio' => 'date',
        'data_fine' => 'date',
        'data_limite_bilancio' => 'date',
        'data_approvazione' => 'date',
        'chiusa_contabilita' => 'boolean',
        'approvato_assemblea' => 'boolean',
        'anno' => 'integer',
        'ordine_sequenza' => 'integer',
    ];

    protected $dates = [
        'data_inizio',
        'data_fine',
        'data_limite_bilancio',
        'data_approvazione',
        'deleted_at',
    ];

    // === RELATIONSHIPS ===

    /**
     * Stabile di appartenenza
     */
    public function stabile(): BelongsTo
    {
        return $this->belongsTo(Stabile::class);
    }

    /**
     * Esercizio precedente
     */
    public function esercizio_precedente(): BelongsTo
    {
        return $this->belongsTo(EsercizioContabile::class, 'esercizio_precedente_id');
    }

    /**
     * Esercizio successivo
     */
    public function esercizio_successivo()
    {
        return $this->hasOne(EsercizioContabile::class, 'esercizio_precedente_id');
    }

    /**
     * Assemblea di approvazione
     */
    public function assemblea(): BelongsTo
    {
        return $this->belongsTo(Assemblea::class);
    }

    /**
     * Movimenti contabili dell'esercizio
     */
    public function movimenti(): HasMany
    {
        return $this->hasMany(MovimentoContabile::class, 'esercizio_id');
    }

    /**
     * Bilanci dell'esercizio
     */
    public function bilanci(): HasMany
    {
        return $this->hasMany(Bilancio::class, 'esercizio_id');
    }

    // === ACCESSORS ===

    /**
     * Nome completo dell'esercizio
     */
    public function getNomeCompletoAttribute(): string
    {
        $tipologia = ucfirst($this->tipologia);
        $nome = "{$tipologia} {$this->anno}";
        
        if ($this->tipologia === 'straordinaria' && $this->descrizione_straordinaria) {
            $nome .= " - " . $this->descrizione_straordinaria;
        }
        
        return $nome;
    }

    /**
     * Verifica se l'esercizio è aperto
     */
    public function getIsApertoAttribute(): bool
    {
        return $this->stato === 'aperto';
    }

    /**
     * Verifica se l'esercizio è chiuso
     */
    public function getIsChiusoAttribute(): bool
    {
        return $this->stato === 'chiuso';
    }

    /**
     * Verifica se l'esercizio è consolidato
     */
    public function getIsConsolidatoAttribute(): bool
    {
        return $this->stato === 'consolidato';
    }

    /**
     * Colore badge per la tipologia
     */
    public function getColoreBadgeAttribute(): string
    {
        return match($this->tipologia) {
            'ordinaria' => 'primary',
            'riscaldamento' => 'warning',
            'straordinaria' => 'danger',
            default => 'secondary'
        };
    }

    /**
     * Icona per la tipologia
     */
    public function getIconaAttribute(): string
    {
        return match($this->tipologia) {
            'ordinaria' => 'fas fa-calendar-alt',
            'riscaldamento' => 'fas fa-fire',
            'straordinaria' => 'fas fa-exclamation-triangle',
            default => 'fas fa-book'
        };
    }

    // === SCOPES ===

    /**
     * Scope per filtrare per tipologia
     */
    public function scopeByTipologia($query, string $tipologia)
    {
        return $query->where('tipologia', $tipologia);
    }

    /**
     * Scope per esercizi aperti
     */
    public function scopeAperti($query)
    {
        return $query->where('stato', 'aperto');
    }

    /**
     * Scope per esercizi chiusi
     */
    public function scopeChiusi($query)
    {
        return $query->where('stato', 'chiuso');
    }

    /**
     * Scope per esercizi di uno stabile
     */
    public function scopeByStabile($query, int $stabileId)
    {
        return $query->where('stabile_id', $stabileId);
    }

    /**
     * Scope per esercizi per anno
     */
    public function scopeByAnno($query, int $anno)
    {
        return $query->where('anno', $anno);
    }

    /**
     * Scope per ordinamento sequenziale
     */
    public function scopeOrdinatiSequenzialmente($query)
    {
        return $query->orderBy('tipologia', 'asc')
                    ->orderBy('ordine_sequenza', 'asc')
                    ->orderBy('anno', 'asc');
    }

    // === METHODS ===

    /**
     * Verifica se l'esercizio può essere modificato
     */
    public function puoEssereModificato(): bool
    {
        return $this->stato === 'aperto' && !$this->chiusa_contabilita;
    }

    /**
     * Verifica se l'esercizio può essere chiuso
     */
    public function puoEssereChiuso(): bool
    {
        return $this->stato === 'aperto' && !$this->chiusa_contabilita;
    }

    /**
     * Chiude l'esercizio
     */
    public function chiudi(): bool
    {
        if (!$this->puoEssereChiuso()) {
            return false;
        }

        $this->stato = 'chiuso';
        $this->chiusa_contabilita = true;
        
        return $this->save();
    }

    /**
     * Consolida l'esercizio
     */
    public function consolida(): bool
    {
        if ($this->stato !== 'chiuso') {
            return false;
        }

        $this->stato = 'consolidato';
        return $this->save();
    }

    /**
     * Ottieni il prossimo numero di sequenza per una tipologia
     */
    public static function getNextSequenza(int $stabileId, string $tipologia): int
    {
        return static::where('stabile_id', $stabileId)
                    ->where('tipologia', $tipologia)
                    ->max('ordine_sequenza') + 1;
    }

    /**
     * Crea esercizio successivo
     */
    public function creaEsercizioSuccessivo(array $attributes = []): ?EsercizioContabile
    {
        $defaults = [
            'stabile_id' => $this->stabile_id,
            'tipologia' => $this->tipologia,
            'anno' => $this->anno + 1,
            'ordine_sequenza' => $this->ordine_sequenza + 1,
            'esercizio_precedente_id' => $this->id,
        ];

        return static::create(array_merge($defaults, $attributes));
    }
}
