<?php

namespace App\Models;

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

class TabellaMillesimale extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'tabelle_millesimali';

    protected $fillable = [
        'stabile_id',
        'nome_tabella', // Campo effettivo nel database
        'codice_tabella', // TAB.A, TAB.B, TAB.C, etc.
        'nome_tabella_millesimale', // Mantengo per compatibilità
        'denominazione', // Spese Generali, Spese Scale, etc.
        'descrizione',
        'tipo', // Mantengo per compatibilità
        'tipo_tabella', // 'generali', 'scale', 'riscaldamento', 'ascensore', 'altro'
        'tipo_calcolo', // 'millesimi', 'parti', 'fisso'
        'totale_millesimi',
        'attiva', // Mantengo per compatibilità
        'stato_tabella', // 'attiva', 'sospesa', 'archiviata'
        'data_approvazione',
        'data_decorrenza',
        'ordinamento',
        'note',
        'creato_da',
        'modificato_da'
    ];

    protected $casts = [
        'attiva' => 'boolean',
        'totale_millesimi' => 'decimal:4',
        'data_approvazione' => 'date',
        'data_decorrenza' => 'date',
        'ordinamento' => 'integer',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * Relazione con Stabile
     */
    public function stabile()
    {
        return $this->belongsTo(Stabile::class, 'stabile_id', 'id');
    }

    /**
     * Relazione con Dettagli Millesimi
     */
    public function dettagli()
    {
        return $this->hasMany(DettaglioMillesimale::class, 'tabella_id');
    }

    /**
     * Relazione con dettagli millesimali per unità (nuovo nome)
     */
    public function dettagliMillesimali()
    {
        return $this->hasMany(DettaglioMillesimale::class, 'tabella_id');
    }

    /**
     * Relazione con utente che ha creato
     */
    public function createBy()
    {
        return $this->belongsTo(User::class, 'creato_da');
    }

    /**
     * Relazione con utente che ha modificato
     */
    public function updatedBy()
    {
        return $this->belongsTo(User::class, 'modificato_da');
    }

    /**
     * Relazione con RipartizioneSpese
     */
    public function ripartizioniSpese()
    {
        return $this->hasMany(RipartizioneSpese::class);
    }

    /**
     * Scope per tabelle attive
     */
    public function scopeAttive($query)
    {
        return $query->where('attiva', true)
            ->orWhere('stato_tabella', 'attiva');
    }

    /**
     * Scope per tipo tabella
     */
    public function scopeTipo($query, $tipo)
    {
        return $query->where('tipo_tabella', $tipo)
            ->orWhere('tipo', $tipo);
    }

    /**
     * Scope per stabile
     */
    public function scopePerStabile($query, $stabileId)
    {
        return $query->where('stabile_id', $stabileId);
    }

    /**
     * Scope ordinato
     */
    public function scopeOrdinato($query)
    {
        return $query->orderBy('ordinamento')->orderBy('nome_tabella_millesimale');
    }

    /**
     * Calcola il totale millesimi
     */
    public function getTotaleMillesimiAttribute()
    {
        return $this->dettagli()->sum('millesimi');
    }

    /**
     * Calcola totale millesimi dalla somma dei dettagli
     */
    public function calcolaTotaleMillesimi()
    {
        return $this->dettagliMillesimali()->sum('millesimi');
    }

    /**
     * Accessor per descrizione completa
     */
    public function getDescrizioneCompletaAttribute()
    {
        $codice = $this->codice_tabella ?: $this->nome_tabella_millesimale;
        $nome = $this->denominazione ?: $this->nome_tabella_millesimale;
        return "{$codice} - {$nome}";
    }

    /**
     * Verifica se la tabella è bilanciata (totale = 1000)
     */
    public function getIsBilanciataAttribute()
    {
        $totale = $this->totale_millesimi;
        return abs($totale - 1000) < 0.0001; // Tolleranza per errori di precisione
    }

    /**
     * Verifica se la tabella è bilanciata
     */
    public function isBilanciata()
    {
        $calcolato = $this->calcolaTotaleMillesimi();
        return abs($calcolato - 1000) < 0.01; // Tolleranza di 0.01
    }

    /**
     * Ottieni tutte le unità con i loro millesimi per questa tabella
     */
    public function getUnitaConMillesimi()
    {
        return $this->dettagliMillesimali()
            ->with('unitaImmobiliare')
            ->orderBy('millesimi', 'desc')
            ->get();
    }

    /**
     * Ottieni lo sbilanciamento della tabella
     */
    public function getSbilanciamentoAttribute()
    {
        return $this->totale_millesimi - 1000;
    }

    /**
     * Conta le unità immobiliari con millesimi assegnati
     */
    public function getUnitaAssegnateAttribute()
    {
        return $this->dettagli()->count();
    }

    /**
     * Accessor per riassunto tabella
     */
    public function getRiassuntoAttribute()
    {
        return [
            'nome' => $this->nome_tabella_millesimale,
            'stabile' => $this->stabile->denominazione ?? 'N/A',
            'unita_assegnate' => $this->unita_assegnate,
            'totale_millesimi' => $this->totale_millesimi,
            'is_bilanciata' => $this->is_bilanciata,
            'sbilanciamento' => $this->sbilanciamento
        ];
    }

    /**
     * Metodo per assegnare millesimi a un'unità immobiliare
     */
    public function assegnaMillesimi($unitaImmobiliareId, $millesimi)
    {
        return DettaglioTabellaMillesimale::updateOrCreate(
            [
                'tabella_millesimale_id' => $this->id,
                'unita_immobiliare_id' => $unitaImmobiliareId
            ],
            [
                'millesimi' => $millesimi
            ]
        );
    }

    /**
     * Metodo per bilanciare automaticamente la tabella
     */
    public function bilancia()
    {
        $dettagli = $this->dettagli;
        $totaleCorrente = $dettagli->sum('millesimi');

        if ($totaleCorrente == 0) {
            throw new \InvalidArgumentException('Impossibile bilanciare una tabella senza millesimi assegnati');
        }

        $fattoreCorrezione = 1000 / $totaleCorrente;

        foreach ($dettagli as $dettaglio) {
            $nuoviMillesimi = round($dettaglio->millesimi * $fattoreCorrezione, 4);
            $dettaglio->update(['millesimi' => $nuoviMillesimi]);
        }

        return $this->fresh();
    }

    /**
     * Ottieni tutte le tipologie standard di tabelle millesimali
     */
    public static function getTipologieStandard()
    {
        return [
            'proprieta_generale' => 'Proprietà Generale',
            'scale' => 'Scale',
            'ascensore' => 'Ascensore',
            'riscaldamento' => 'Riscaldamento',
            'acqua_calda' => 'Acqua Calda Sanitaria',
            'condizionamento' => 'Condizionamento',
            'garage' => 'Garage/Autorimesse',
            'giardino' => 'Giardino',
            'piscina' => 'Piscina',
            'personalizzata' => 'Personalizzata'
        ];
    }

    /**
     * Metodo per creare ripartizione spese automatica
     */
    public function creaRipartizioneSpese($voceSpesaId, $importoTotale, $dataRipartizione = null)
    {
        return RipartizioneSpese::create([
            'voce_spesa_id' => $voceSpesaId,
            'stabile_id' => $this->id,
            'tabella_millesimale_id' => $this->tabelleMillesimali()->where('tipo', 'generale')->first()?->id,
            'tipo_ripartizione' => 'millesimale',
            'importo_totale' => $importoTotale,
            'data_ripartizione' => $dataRipartizione ?? now(),
            'stato' => 'bozza',
            'creato_da' => auth()->id() ?? 1
        ]);
    }
}
