<?php

namespace App\Models;

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

/**
 * Class PianoRateizzazione
 * 
 * Gestisce i piani di rateizzazione per i pagamenti condominiali
 * 
 * @package App\Models
 */
class PianoRateizzazione extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'piano_rateizzazione';

    protected $fillable = [
        'codice_piano',
        'stabile_id',
        'descrizione',
        'tipo_piano',
        'importo_totale',
        'numero_rate',
        'data_prima_rata',
        'frequenza',
        'stato',
        'configurazione_rate',
        'note',
        'creato_da',
        'attivato_at',
        'attivato_da'
    ];

    protected $casts = [
        'importo_totale' => 'decimal:2',
        'numero_rate' => 'integer',
        'data_prima_rata' => 'date',
        'configurazione_rate' => 'array',
        'attivato_at' => 'datetime'
    ];

    protected $dates = [
        'data_prima_rata',
        'attivato_at',
        'created_at',
        'updated_at',
        'deleted_at'
    ];

    /**
     * Boot method per generare automaticamente il codice piano
     */
    protected static function boot()
    {
        parent::boot();
        
        static::creating(function ($model) {
            if (empty($model->codice_piano)) {
                $model->codice_piano = self::generaCodicePiano();
            }
        });
    }

    /**
     * Genera un codice univoco per il piano
     */
    public static function generaCodicePiano()
    {
        do {
            $codice = 'PR' . strtoupper(Str::random(6));
        } while (self::where('codice_piano', $codice)->exists());
        
        return $codice;
    }

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

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

    /**
     * Relazione con User (attivato da)
     */
    public function attivatoDa()
    {
        return $this->belongsTo(User::class, 'attivato_da');
    }

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

    /**
     * Relazione con Rate
     */
    public function rate()
    {
        return $this->hasMany(Rata::class, 'piano_rateizzazione_id');
    }

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

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

    /**
     * Scope per tipo piano
     */
    public function scopePerTipo($query, $tipo)
    {
        return $query->where('tipo_piano', $tipo);
    }

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

    /**
     * Metodo per attivare il piano
     */
    public function attiva($userId = null)
    {
        $this->update([
            'stato' => 'attivo',
            'attivato_at' => now(),
            'attivato_da' => $userId ?? auth()->id()
        ]);

        // Genera le rate se non esistono
        if ($this->rate()->count() == 0) {
            $this->generaRate();
        }

        return $this;
    }

    /**
     * Metodo per sospendere il piano
     */
    public function sospendi()
    {
        $this->update(['stato' => 'sospeso']);
        return $this;
    }

    /**
     * Metodo per annullare il piano
     */
    public function annulla()
    {
        $this->update(['stato' => 'annullato']);
        
        // Annulla tutte le rate non pagate
        $this->rate()->whereIn('stato', ['emessa', 'scaduta'])->update(['stato' => 'annullata']);
        
        return $this;
    }

    /**
     * Metodo per completare il piano
     */
    public function completa()
    {
        $this->update(['stato' => 'completato']);
        return $this;
    }

    /**
     * Verifica se può essere modificato
     */
    public function puoEssereModificato()
    {
        return in_array($this->stato, ['bozza']);
    }

    /**
     * Verifica se può essere eliminato
     */
    public function puoEssereEliminato()
    {
        return in_array($this->stato, ['bozza', 'annullato']);
    }

    /**
     * Genera le rate del piano
     */
    public function generaRate()
    {
        if ($this->numero_rate <= 0) {
            throw new \Exception('Numero rate deve essere maggiore di 0');
        }

        // Elimina le rate esistenti se ci sono
        $this->rate()->delete();

        $unitaImmobiliari = $this->stabile->unitaImmobiliari;
        $importoPerRata = $this->importo_totale / $this->numero_rate;

        for ($numeroRata = 1; $numeroRata <= $this->numero_rate; $numeroRata++) {
            $dataScadenza = $this->calcolaDataScadenzaRata($numeroRata);

            foreach ($unitaImmobiliari as $unita) {
                $this->rate()->create([
                    'codice_rata' => Rata::generaCodiceRata(),
                    'unita_immobiliare_id' => $unita->id,
                    'anagrafica_condominiale_id' => $unita->anagrafiche()->where('tipo_diritto', 'proprietario')->first()?->id,
                    'numero_rata' => $numeroRata,
                    'descrizione' => "{$this->descrizione} - Rata {$numeroRata}/{$this->numero_rate}",
                    'importo_rata' => $importoPerRata,
                    'data_scadenza' => $dataScadenza,
                    'importo_residuo' => $importoPerRata,
                    'stato' => 'emessa'
                ]);
            }
        }

        return $this;
    }

    /**
     * Calcola la data di scadenza per una rata specifica
     */
    public function calcolaDataScadenzaRata($numeroRata)
    {
        $dataBase = Carbon::parse($this->data_prima_rata);
        
        $mesiDaAggiungere = match ($this->frequenza) {
            'mensile' => ($numeroRata - 1) * 1,
            'bimestrale' => ($numeroRata - 1) * 2,
            'trimestrale' => ($numeroRata - 1) * 3,
            'semestrale' => ($numeroRata - 1) * 6,
            'annuale' => ($numeroRata - 1) * 12,
            'personalizzata' => $this->calcolaIntervalloPersonalizzato($numeroRata),
            default => ($numeroRata - 1) * 1
        };

        return $dataBase->addMonths($mesiDaAggiungere);
    }

    /**
     * Calcola intervallo personalizzato (da implementare in base alla configurazione)
     */
    private function calcolaIntervalloPersonalizzato($numeroRata)
    {
        $config = $this->configurazione_rate;
        
        if (isset($config['intervalli']) && is_array($config['intervalli'])) {
            return $config['intervalli'][$numeroRata - 1] ?? 0;
        }
        
        return ($numeroRata - 1) * 1; // Default mensile
    }

    /**
     * Ottieni statistiche del piano
     */
    public function getStatistiche()
    {
        $rateQuery = $this->rate();
        
        return [
            'totale_rate' => $rateQuery->count(),
            'rate_pagate' => $rateQuery->where('stato', 'pagata')->count(),
            'rate_scadute' => $rateQuery->where('stato', 'scaduta')->count(),
            'importo_pagato' => $rateQuery->sum('importo_pagato'),
            'importo_residuo' => $rateQuery->sum('importo_residuo'),
            'percentuale_completamento' => $this->getPercentualeCompletamento(),
            'prossima_scadenza' => $rateQuery->where('stato', 'emessa')->min('data_scadenza')
        ];
    }

    /**
     * Calcola percentuale di completamento
     */
    public function getPercentualeCompletamento()
    {
        if ($this->importo_totale == 0) {
            return 0;
        }

        $importoPagato = $this->rate()->sum('importo_pagato');
        return round(($importoPagato / $this->importo_totale) * 100, 2);
    }

    /**
     * Verifica se il piano è completato
     */
    public function isCompletato()
    {
        return $this->rate()->where('stato', '!=', 'pagata')->count() == 0;
    }

    /**
     * Verifica se ci sono rate scadute
     */
    public function hasRateScadute()
    {
        return $this->rate()
            ->where('stato', 'emessa')
            ->where('data_scadenza', '<', now()->toDateString())
            ->exists();
    }

    /**
     * Aggiorna automaticamente lo stato del piano
     */
    public function aggiornaStato()
    {
        if ($this->stato === 'attivo') {
            if ($this->isCompletato()) {
                $this->completa();
            } elseif ($this->hasRateScadute()) {
                // Aggiorna le rate scadute
                $this->rate()
                    ->where('stato', 'emessa')
                    ->where('data_scadenza', '<', now()->toDateString())
                    ->update(['stato' => 'scaduta']);
            }
        }

        return $this;
    }

    /**
     * Accessor per tipo piano formattato
     */
    public function getTipoPianoFormattatoAttribute()
    {
        return match ($this->tipo_piano) {
            'ordinario' => 'Piano Ordinario',
            'straordinario' => 'Piano Straordinario',
            'conguaglio' => 'Piano Conguaglio',
            'personalizzato' => 'Piano Personalizzato',
            default => ucfirst($this->tipo_piano)
        };
    }

    /**
     * Accessor per frequenza formattata
     */
    public function getFrequenzaFormattataAttribute()
    {
        return match ($this->frequenza) {
            'mensile' => 'Mensile',
            'bimestrale' => 'Bimestrale',
            'trimestrale' => 'Trimestrale',
            'semestrale' => 'Semestrale',
            'annuale' => 'Annuale',
            'personalizzata' => 'Personalizzata',
            default => ucfirst($this->frequenza)
        };
    }

    /**
     * Accessor per stato formattato
     */
    public function getStatoFormattatoAttribute()
    {
        return match ($this->stato) {
            'bozza' => 'Bozza',
            'attivo' => 'Attivo',
            'completato' => 'Completato',
            'sospeso' => 'Sospeso',
            'annullato' => 'Annullato',
            default => ucfirst($this->stato)
        };
    }
}
