<?php

namespace App\Services;

use App\Models\RipartizioneSpese;
use App\Models\DettaglioRipartizioneSpese;
use App\Models\PianoRateizzazione;
use App\Models\Rata;
use App\Models\VoceSpesa;
use App\Models\TabellaMillesimale;
use App\Models\UnitaImmobiliare;
use App\Models\AnagraficaCondominiale;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

/**
 * Service per la gestione completa della ripartizione spese
 * e generazione automatica di piani di rateizzazione
 */
class RipartizioneSpesaService
{
    /**
     * Calcola automaticamente la ripartizione spese per uno stabile
     *
     * @param VoceSpesa $voceSpesa
     * @param float $importoTotale
     * @param int|null $tabellaMillesimaleId
     * @param array $opzioni
     * @return RipartizioneSpese
     */
    public function calcolaRipartizione(
        VoceSpesa $voceSpesa,
        float $importoTotale,
        ?int $tabellaMillesimaleId = null,
        array $opzioni = []
    ): RipartizioneSpesa {
        return DB::transaction(function () use ($voceSpesa, $importoTotale, $tabellaMillesimaleId, $opzioni) {
            // Usa la tabella millesimale di default se non specificata
            $tabellaId = $tabellaMillesimaleId ?? $voceSpesa->tabella_millesimale_default_id;
            
            if (!$tabellaId) {
                throw new \InvalidArgumentException('Nessuna tabella millesimale specificata o di default');
            }

            $tabellaMillesimale = TabellaMillesimale::findOrFail($tabellaId);

            // Crea la ripartizione principale
            $ripartizione = RipartizioneSpese::create([
                'voce_spesa_id' => $voceSpesa->id,
                'stabile_id' => $voceSpesa->stabile_id,
                'tabella_millesimale_id' => $tabellaId,
                'importo_totale' => $importoTotale,
                'tipo_ripartizione' => $opzioni['tipo_ripartizione'] ?? 'millesimale',
                'data_ripartizione' => $opzioni['data_ripartizione'] ?? now()->toDateString(),
                'note' => $opzioni['note'] ?? null,
                'creato_da' => auth()->id(),
            ]);

            // Calcola i dettagli per ogni unità immobiliare
            $this->calcolaDettagliRipartizione($ripartizione, $tabellaMillesimale, $importoTotale);

            return $ripartizione;
        });
    }

    /**
     * Calcola i dettagli di ripartizione per ogni unità immobiliare
     */
    protected function calcolaDettagliRipartizione(
        RipartizioneSpese $ripartizione,
        TabellaMillesimale $tabellaMillesimale,
        float $importoTotale
    ): void {
        // Ottieni le unità immobiliari dello stabile con i loro millesimi
        $unitaConMillesimi = UnitaImmobiliare::where('stabile_id', $ripartizione->stabile_id)
            ->with(['dirittiReali.anagrafica'])
            ->get();

        $totaleMillesimi = $tabellaMillesimale->totale_millesimi ?? 1000;

        foreach ($unitaConMillesimi as $unita) {
            // Ottieni i millesimi dell'unità per questa tabella
            $millesimi = $this->getMillesimiUnita($unita, $tabellaMillesimale);
            
            if ($millesimi <= 0) {
                continue; // Salta unità senza millesimi
            }

            // Calcola l'importo proporzionale
            $importoCalcolato = ($importoTotale * $millesimi) / $totaleMillesimi;

            // Ottieni l'anagrafica proprietaria (primo diritto reale attivo)
            $anagrafica = $unita->dirittiReali()
                ->where('attivo', true)
                ->with('anagrafica')
                ->first()?->anagrafica;

            if (!$anagrafica) {
                continue; // Salta unità senza proprietario
            }

            // Crea il dettaglio ripartizione
            DettaglioRipartizioneSpese::create([
                'ripartizione_spese_id' => $ripartizione->id,
                'unita_immobiliare_id' => $unita->id,
                'anagrafica_condominiale_id' => $anagrafica->id,
                'millesimi' => $millesimi,
                'importo_calcolato' => round($importoCalcolato, 2),
            ]);
        }

        // Aggiorna l'importo ripartito
        $importoRipartito = $ripartizione->dettagli()->sum('importo_calcolato');
        $ripartizione->update(['importo_ripartito' => $importoRipartito]);
    }

    /**
     * Ottieni i millesimi di un'unità per una specifica tabella millesimale
     */
    protected function getMillesimiUnita(UnitaImmobiliare $unita, TabellaMillesimale $tabella): float
    {
        // Logica per ottenere i millesimi specifici dalla tabella
        // Per ora usiamo i millesimi di proprietà dell'unità
        return $unita->millesimi_proprieta ?? 0;
    }

    /**
     * Crea un piano di rateizzazione da una ripartizione spese
     */
    public function creaPianoRateizzazione(
        RipartizioneSpese $ripartizione,
        int $numeroRate,
        string $frequenza = 'mensile',
        Carbon $dataPrimaRata = null,
        array $opzioni = []
    ): PianoRateizzazione {
        return DB::transaction(function () use ($ripartizione, $numeroRate, $frequenza, $dataPrimaRata, $opzioni) {
            $dataPrimaRata = $dataPrimaRata ?? now()->addMonth()->startOfMonth();

            $piano = PianoRateizzazione::create([
                'ripartizione_spese_id' => $ripartizione->id,
                'stabile_id' => $ripartizione->stabile_id,
                'descrizione' => $opzioni['descrizione'] ?? "Piano rateizzazione per {$ripartizione->voceSpesa->descrizione}",
                'tipo_piano' => $opzioni['tipo_piano'] ?? 'standard',
                'importo_totale' => $ripartizione->importo_totale,
                'numero_rate' => $numeroRate,
                'data_prima_rata' => $dataPrimaRata,
                'frequenza' => $frequenza,
                'note' => $opzioni['note'] ?? null,
                'creato_da' => auth()->id(),
            ]);

            // Genera le rate automaticamente
            $this->generaRate($piano, $dataPrimaRata, $frequenza);

            return $piano;
        });
    }

    /**
     * Genera automaticamente le rate per un piano di rateizzazione
     */
    protected function generaRate(PianoRateizzazione $piano, Carbon $dataPrimaRata, string $frequenza): void
    {
        $importoRata = round($piano->importo_totale / $piano->numero_rate, 2);
        $dataScadenza = $dataPrimaRata->copy();

        for ($i = 1; $i <= $piano->numero_rate; $i++) {
            // Aggiusta l'ultima rata per eventuali arrotondamenti
            $importoCorrente = ($i == $piano->numero_rate) 
                ? $piano->importo_totale - (($piano->numero_rate - 1) * $importoRata)
                : $importoRata;

            Rata::create([
                'piano_rateizzazione_id' => $piano->id,
                'ripartizione_spese_id' => $piano->ripartizione_spese_id,
                'numero_rata' => $i,
                'importo_rata' => $importoCorrente,
                'data_scadenza' => $dataScadenza->copy(),
            ]);

            // Calcola la prossima scadenza
            $dataScadenza = $this->calcolaProximaScadenza($dataScadenza, $frequenza);
        }
    }

    /**
     * Calcola la prossima data di scadenza in base alla frequenza
     */
    protected function calcolaProximaScadenza(Carbon $dataCorrente, string $frequenza): Carbon
    {
        return match ($frequenza) {
            'mensile' => $dataCorrente->addMonth(),
            'bimestrale' => $dataCorrente->addMonths(2),
            'trimestrale' => $dataCorrente->addMonths(3),
            'semestrale' => $dataCorrente->addMonths(6),
            default => $dataCorrente->addMonth(),
        };
    }

    /**
     * Approva una ripartizione spese
     */
    public function approvaRipartizione(RipartizioneSpese $ripartizione): bool
    {
        return $ripartizione->update([
            'stato' => 'approvata',
            'approvato_at' => now(),
            'approvato_da' => auth()->id(),
        ]);
    }

    /**
     * Contabilizza una ripartizione spese
     */
    public function contabilizzaRipartizione(RipartizioneSpese $ripartizione): bool
    {
        return $ripartizione->update([
            'stato' => 'contabilizzata',
            'contabilizzato_at' => now(),
            'contabilizzato_da' => auth()->id(),
        ]);
    }

    /**
     * Registra il pagamento di una rata
     */
    public function registraPagamento(
        Rata $rata,
        float $importoPagato,
        Carbon $dataPagamento = null,
        string $modalitaPagamento = null,
        string $riferimentoPagamento = null
    ): bool {
        $dataPagamento = $dataPagamento ?? now();

        return $rata->update([
            'stato' => 'pagata',
            'data_pagamento' => $dataPagamento,
            'importo_pagato' => $importoPagato,
            'modalita_pagamento' => $modalitaPagamento,
            'riferimento_pagamento' => $riferimentoPagamento,
            'registrato_da' => auth()->id(),
            'registrato_at' => now(),
        ]);
    }

    /**
     * Calcola le statistiche di una ripartizione
     */
    public function calcolaStatistiche(RipartizioneSpese $ripartizione): array
    {
        $dettagli = $ripartizione->dettagli;
        
        return [
            'numero_unita' => $dettagli->count(),
            'importo_totale' => $ripartizione->importo_totale,
            'importo_ripartito' => $ripartizione->importo_ripartito,
            'differenza' => $ripartizione->importo_totale - $ripartizione->importo_ripartito,
            'importo_medio_unita' => $dettagli->avg('importo_calcolato'),
            'importo_min_unita' => $dettagli->min('importo_calcolato'),
            'importo_max_unita' => $dettagli->max('importo_calcolato'),
            'millesimi_totali' => $dettagli->sum('millesimi'),
        ];
    }
}
