<?php

namespace App\Models;

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

/**
 * Class Rata
 * 
 * Gestisce le rate singole dei piani di rateizzazione
 * 
 * @package App\Models
 */
class Rata extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'rate';

    protected $fillable = [
        'codice_rata',
        'piano_rateizzazione_id',
        'unita_immobiliare_id',
        'anagrafica_condominiale_id',
        'numero_rata',
        'descrizione',
        'importo_rata',
        'data_scadenza',
        'stato',
        'importo_pagato',
        'importo_residuo',
        'data_pagamento',
        'note_pagamento',
        'dettagli_pagamento',
        'metodo_pagamento',
        'riferimento_pagamento',
        'registrato_da',
        // Compatibilità con vecchia struttura
        'gestione_id',
        'soggetto_id',
        'importo',
        'tipo_rata',
        'note'
    ];

    protected $casts = [
        'importo_rata' => 'decimal:2',
        'importo_pagato' => 'decimal:2',
        'importo_residuo' => 'decimal:2',
        'data_scadenza' => 'date',
        'data_pagamento' => 'date',
        'dettagli_pagamento' => 'array',
        'numero_rata' => 'integer',
        // Compatibilità
        'importo' => 'decimal:2'
    ];

    protected $dates = [
        'data_scadenza',
        'data_pagamento',
        'created_at',
        'updated_at',
        'deleted_at'
    ];

    /**
     * Boot method per generare automaticamente il codice rata
     */
    protected static function boot()
    {
        parent::boot();
        
        static::creating(function ($model) {
            if (empty($model->codice_rata)) {
                $model->codice_rata = self::generaCodiceRata();
            }
            
            // Inizializza importo_residuo se non impostato
            if (is_null($model->importo_residuo)) {
                $model->importo_residuo = $model->importo_rata ?? $model->importo ?? 0;
            }
        });
    }

    /**
     * Genera un codice univoco per la rata
     */
    public static function generaCodiceRata()
    {
        do {
            $codice = 'RT' . strtoupper(Str::random(6));
        } while (self::where('codice_rata', $codice)->exists());
        
        return $codice;
    }

    /**
     * Relazione con PianoRateizzazione
     */
    public function pianoRateizzazione()
    {
        return $this->belongsTo(PianoRateizzazione::class);
    }

    /**
     * Relazione con RipartizioneSpese
     */
    public function ripartizione()
    {
        return $this->belongsTo(RipartizioneSpese::class, 'ripartizione_spese_id');
    }

    /**
     * Relazione con UnitaImmobiliare
     */
    public function unitaImmobiliare()
    {
        return $this->belongsTo(UnitaImmobiliare::class);
    }

    /**
     * Relazione con AnagraficaCondominiale
     */
    public function anagraficaCondominiale()
    {
        return $this->belongsTo(AnagraficaCondominiale::class);
    }

    /**
     * Relazione con User (registrato da)
     */
    public function registratoDa()
    {
        return $this->belongsTo(User::class, 'registrato_da');
    }

    // Relazioni di compatibilità con vecchia struttura
    /**
     * Relazione con Gestione (compatibilità)
     */
    public function gestione()
    {
        return $this->belongsTo(Gestione::class, 'gestione_id', 'id_gestione');
    }

    /**
     * Relazione con Soggetto (compatibilità)
     */
    public function soggetto()
    {
        return $this->belongsTo(Soggetto::class, 'soggetto_id', 'id_soggetto');
    }

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

    /**
     * Scope per rate scadute
     */
    public function scopeScadute($query)
    {
        return $query->where('data_scadenza', '<', now()->toDateString())
                    ->whereIn('stato', ['emessa']);
    }

    /**
     * Scope per rate in scadenza
     */
    public function scopeInScadenza($query, $giorni = 30)
    {
        return $query->whereBetween('data_scadenza', [now()->toDateString(), now()->addDays($giorni)->toDateString()])
                    ->whereIn('stato', ['emessa']);
    }

    /**
     * Scope per rate pagate
     */
    public function scopePagate($query)
    {
        return $query->where('stato', 'pagata');
    }

    /**
     * Scope per rate emesse
     */
    public function scopeEmesse($query)
    {
        return $query->where('stato', 'emessa');
    }

    /**
     * Scope per piano rateizzazione
     */
    public function scopePerPiano($query, $pianoId)
    {
        return $query->where('piano_rateizzazione_id', $pianoId);
    }

    /**
     * Scope per unità immobiliare
     */
    public function scopePerUnita($query, $unitaId)
    {
        return $query->where('unita_immobiliare_id', $unitaId);
    }

    /**
     * Metodo per registrare pagamento completo
     */
    public function registraPagamento($importo, $metodo = null, $riferimento = null, $note = null, $userId = null)
    {
        $importoPagamento = min($importo, $this->importo_residuo);
        $nuovoImportoPagato = $this->importo_pagato + $importoPagamento;
        $nuovoImportoResiduo = $this->importo_rata - $nuovoImportoPagato;

        $nuovoStato = $nuovoImportoResiduo <= 0 ? 'pagata' : 'parzialmente_pagata';

        $this->update([
            'importo_pagato' => $nuovoImportoPagato,
            'importo_residuo' => $nuovoImportoResiduo,
            'stato' => $nuovoStato,
            'data_pagamento' => now(),
            'metodo_pagamento' => $metodo,
            'riferimento_pagamento' => $riferimento,
            'note_pagamento' => $note,
            'registrato_da' => $userId ?? auth()->id()
        ]);

        return $this;
    }

    /**
     * Metodo per registrare pagamento parziale
     */
    public function registraPagamentoParziale($importo, $metodo = null, $riferimento = null, $note = null, $userId = null)
    {
        return $this->registraPagamento($importo, $metodo, $riferimento, $note, $userId);
    }

    /**
     * Metodo per annullare la rata
     */
    public function annulla($motivo = null)
    {
        $this->update([
            'stato' => 'annullata',
            'note_pagamento' => $motivo
        ]);

        return $this;
    }

    /**
     * Metodo per verificare se è scaduta
     */
    public function isScaduta()
    {
        return $this->data_scadenza < now()->toDateString() && 
               in_array($this->stato, ['emessa']);
    }

    /**
     * Metodo per verificare se è in scadenza
     */
    public function isInScadenza($giorni = 30)
    {
        $dataLimite = now()->addDays($giorni)->toDateString();
        return $this->data_scadenza <= $dataLimite && 
               $this->data_scadenza >= now()->toDateString() &&
               in_array($this->stato, ['emessa']);
    }

    /**
     * Metodo per aggiornare automaticamente lo stato
     */
    public function aggiornaStato()
    {
        if ($this->stato === 'emessa' && $this->isScaduta()) {
            $this->update(['stato' => 'scaduta']);
        }

        return $this;
    }

    /**
     * Verifica se può essere modificata
     */
    public function puoEssereModificata()
    {
        return in_array($this->stato, ['emessa', 'scaduta']);
    }

    /**
     * Verifica se può essere eliminata
     */
    public function puoEssereEliminata()
    {
        return in_array($this->stato, ['emessa', 'annullata']);
    }

    /**
     * Accessor per importo residuo calcolato
     */
    public function getImportoResiduoCalcolatoAttribute()
    {
        return ($this->importo_rata ?? $this->importo ?? 0) - ($this->importo_pagato ?? 0);
    }

    /**
     * Accessor per stato formattato
     */
    public function getStatoFormattatoAttribute()
    {
        return match ($this->stato) {
            'emessa' => 'Emessa',
            'pagata' => 'Pagata',
            'parzialmente_pagata' => 'Parzialmente Pagata',
            'scaduta' => 'Scaduta',
            'annullata' => 'Annullata',
            default => ucfirst($this->stato)
        };
    }

    /**
     * Accessor per metodo pagamento formattato
     */
    public function getMetodoPagamentoFormattatoAttribute()
    {
        return match ($this->metodo_pagamento) {
            'bonifico' => 'Bonifico Bancario',
            'bollettino' => 'Bollettino Postale',
            'contanti' => 'Contanti',
            'assegno' => 'Assegno',
            'pos' => 'POS/Carta',
            'altro' => 'Altro',
            default => $this->metodo_pagamento ? ucfirst($this->metodo_pagamento) : 'Non Specificato'
        };
    }

    /**
     * Accessor per giorni alla scadenza
     */
    public function getGiorniAllaScadenzaAttribute()
    {
        return now()->diffInDays($this->data_scadenza, false);
    }

    /**
     * Accessor per percentuale pagata
     */
    public function getPercentualePagataAttribute()
    {
        $importoTotale = $this->importo_rata ?? $this->importo ?? 0;
        if ($importoTotale == 0) {
            return 0;
        }

        return round((($this->importo_pagato ?? 0) / $importoTotale) * 100, 2);
    }

    /**
     * Accessor compatibilità con vecchia struttura
     */
    public function getImportoResiduoAttribute()
    {
        // Se esiste la nuova colonna, usala
        if (isset($this->attributes['importo_residuo'])) {
            return $this->attributes['importo_residuo'];
        }
        
        // Altrimenti calcola
        return $this->getImportoResiduoCalcolatoAttribute();
    }
}