<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\PianoRateizzazione;
use App\Models\Rata;
use App\Models\RipartizioneSpese;
use App\Models\DettaglioRipartizioneSpese;
use App\Models\UnitaImmobiliare;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Carbon\Carbon;

class PianoRateizzazioneController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(Request $request)
    {
        $query = PianoRateizzazione::with(['ripartizioneSpese.voceSpesa.stabile', 'unitaImmobiliare'])
                                  ->whereHas('ripartizioneSpese.voceSpesa.stabile', function($q) {
                                      $q->where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null);
                                  });

        // Filtro per stabile
        if ($request->filled('stabile_id')) {
            $query->whereHas('ripartizioneSpese.voceSpesa', function($q) use ($request) {
                $q->where('stabile_id', $request->stabile_id);
            });
        }

        // Filtro per unità immobiliare
        if ($request->filled('unita_immobiliare_id')) {
            $query->where('unita_immobiliare_id', $request->unita_immobiliare_id);
        }

        // Filtro per stato
        if ($request->filled('stato')) {
            $query->where('stato', $request->stato);
        }

        // Filtro per data
        if ($request->filled('data_da')) {
            $query->where('data_inizio', '>=', $request->data_da);
        }
        if ($request->filled('data_a')) {
            $query->where('data_inizio', '<=', $request->data_a);
        }

        $pianiRateizzazione = $query->orderBy('data_inizio', 'desc')->paginate(15);

        // Dati per i filtri
        $stabili = \App\Models\Stabile::where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null)
                                     ->orderBy('denominazione')
                                     ->get();

        return view('admin.piani-rateizzazione.index', compact('pianiRateizzazione', 'stabili'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(Request $request)
    {
        $ripartizioneSpesa = null;
        $dettaglioRipartizione = null;

        // Se arriva da una ripartizione specifica
        if ($request->filled('ripartizione_spesa_id')) {
            $ripartizioneSpesa = RipartizioneSpese::with(['voceSpesa.stabile', 'dettagli.unitaImmobiliare'])
                                                 ->whereHas('voceSpesa.stabile', function($q) {
                                                     $q->where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null);
                                                 })
                                                 ->findOrFail($request->ripartizione_spesa_id);
        }

        // Se arriva da un dettaglio specifico
        if ($request->filled('dettaglio_ripartizione_id')) {
            $dettaglioRipartizione = DettaglioRipartizioneSpese::with(['ripartizioneSpese.voceSpesa.stabile', 'unitaImmobiliare'])
                                                               ->whereHas('ripartizioneSpese.voceSpesa.stabile', function($q) {
                                                                   $q->where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null);
                                                               })
                                                               ->findOrFail($request->dettaglio_ripartizione_id);
            
            $ripartizioneSpesa = $dettaglioRipartizione->ripartizioneSpese;
        }

        // Ripartizioni disponibili
        $ripartizioni = RipartizioneSpese::with(['voceSpesa.stabile'])
                                        ->whereHas('voceSpesa.stabile', function($q) {
                                            $q->where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null);
                                        })
                                        ->where('stato', 'confermata')
                                        ->orderBy('data_ripartizione', 'desc')
                                        ->get();

        return view('admin.piani-rateizzazione.create', compact('ripartizioni', 'ripartizioneSpesa', 'dettaglioRipartizione'));
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $request->validate([
            'ripartizione_spese_id' => 'required|exists:ripartizioni_spese,id',
            'unita_immobiliare_id' => 'required|exists:unita_immobiliari,id',
            'denominazione' => 'required|string|max:255',
            'importo_totale' => 'required|numeric|min:0',
            'numero_rate' => 'required|integer|min:1|max:60',
            'data_inizio' => 'required|date',
            'frequenza' => 'required|in:mensile,bimestrale,trimestrale,semestrale',
            'importo_prima_rata' => 'nullable|numeric|min:0',
            'note' => 'nullable|string',
            'applica_interessi' => 'nullable|boolean',
            'tasso_interesse' => 'nullable|numeric|min:0|max:100',
        ]);

        // Verifica che la ripartizione appartenga all'amministratore
        $ripartizioneSpesa = RipartizioneSpese::whereHas('voceSpesa.stabile', function($q) {
                                                  $q->where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null);
                                              })
                                              ->where('stato', 'confermata')
                                              ->findOrFail($request->ripartizione_spese_id);

        // Verifica che l'unità immobiliare appartenga al stabile della ripartizione
        $unitaImmobiliare = UnitaImmobiliare::where('id', $request->unita_immobiliare_id)
                                           ->where('stabile_id', $ripartizioneSpesa->voceSpesa->stabile_id)
                                           ->firstOrFail();

        // Verifica che l'unità abbia un dettaglio nella ripartizione
        $dettaglioRipartizione = DettaglioRipartizioneSpese::where('ripartizione_spese_id', $request->ripartizione_spese_id)
                                                           ->where('unita_immobiliare_id', $request->unita_immobiliare_id)
                                                           ->firstOrFail();

        // Verifica che l'importo totale non superi l'importo del dettaglio
        if ($request->importo_totale > $dettaglioRipartizione->importo) {
            return redirect()->back()
                           ->withInput()
                           ->with('error', 'L\'importo totale del piano non può superare l\'importo della ripartizione (' . number_format($dettaglioRipartizione->importo, 2) . ' €).');
        }

        DB::beginTransaction();

        try {
            // Crea il piano di rateizzazione
            $pianoRateizzazione = PianoRateizzazione::create([
                'codice_piano' => $this->generateCodicePiano(),
                'ripartizione_spese_id' => $request->ripartizione_spese_id,
                'unita_immobiliare_id' => $request->unita_immobiliare_id,
                'denominazione' => $request->denominazione,
                'importo_totale' => $request->importo_totale,
                'numero_rate' => $request->numero_rate,
                'data_inizio' => $request->data_inizio,
                'frequenza' => $request->frequenza,
                'importo_prima_rata' => $request->importo_prima_rata,
                'note' => $request->note,
                'applica_interessi' => $request->boolean('applica_interessi'),
                'tasso_interesse' => $request->tasso_interesse,
                'stato' => 'bozza',
                'created_by' => Auth::id(),
            ]);

            // Calcola e crea le rate
            $this->calcolaRate($pianoRateizzazione);

            DB::commit();

            return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                           ->with('success', 'Piano di rateizzazione creato con successo.');

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()
                           ->withInput()
                           ->with('error', 'Errore durante la creazione del piano: ' . $e->getMessage());
        }
    }

    /**
     * Display the specified resource.
     */
    public function show(PianoRateizzazione $pianoRateizzazione)
    {
        // Verifica autorizzazione
        $this->authorize('view', $pianoRateizzazione);

        $pianoRateizzazione->load([
            'ripartizioneSpese.voceSpesa.stabile',
            'unitaImmobiliare.anagraficaCondominiale.soggetto',
            'rate' => function($query) {
                $query->orderBy('numero_rata');
            },
            'createdBy',
            'updatedBy'
        ]);

        return view('admin.piani-rateizzazione.show', compact('pianoRateizzazione'));
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(PianoRateizzazione $pianoRateizzazione)
    {
        // Verifica autorizzazione
        $this->authorize('update', $pianoRateizzazione);

        // Solo i piani in bozza possono essere modificati
        if ($pianoRateizzazione->stato !== 'bozza') {
            return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                           ->with('error', 'Impossibile modificare un piano già attivato.');
        }

        $pianoRateizzazione->load([
            'ripartizioneSpese.voceSpesa.stabile',
            'unitaImmobiliare',
            'rate' => function($query) {
                $query->orderBy('numero_rata');
            }
        ]);

        return view('admin.piani-rateizzazione.edit', compact('pianoRateizzazione'));
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, PianoRateizzazione $pianoRateizzazione)
    {
        // Verifica autorizzazione
        $this->authorize('update', $pianoRateizzazione);

        // Solo i piani in bozza possono essere modificati
        if ($pianoRateizzazione->stato !== 'bozza') {
            return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                           ->with('error', 'Impossibile modificare un piano già attivato.');
        }

        $request->validate([
            'denominazione' => 'required|string|max:255',
            'importo_totale' => 'required|numeric|min:0',
            'numero_rate' => 'required|integer|min:1|max:60',
            'data_inizio' => 'required|date',
            'frequenza' => 'required|in:mensile,bimestrale,trimestrale,semestrale',
            'importo_prima_rata' => 'nullable|numeric|min:0',
            'note' => 'nullable|string',
            'applica_interessi' => 'nullable|boolean',
            'tasso_interesse' => 'nullable|numeric|min:0|max:100',
        ]);

        // Verifica che l'importo totale non superi l'importo del dettaglio
        $dettaglioRipartizione = DettaglioRipartizioneSpese::where('ripartizione_spese_id', $pianoRateizzazione->ripartizione_spese_id)
                                                           ->where('unita_immobiliare_id', $pianoRateizzazione->unita_immobiliare_id)
                                                           ->firstOrFail();

        if ($request->importo_totale > $dettaglioRipartizione->importo) {
            return redirect()->back()
                           ->withInput()
                           ->with('error', 'L\'importo totale del piano non può superare l\'importo della ripartizione (' . number_format($dettaglioRipartizione->importo, 2) . ' €).');
        }

        DB::beginTransaction();

        try {
            // Aggiorna il piano
            $pianoRateizzazione->update([
                'denominazione' => $request->denominazione,
                'importo_totale' => $request->importo_totale,
                'numero_rate' => $request->numero_rate,
                'data_inizio' => $request->data_inizio,
                'frequenza' => $request->frequenza,
                'importo_prima_rata' => $request->importo_prima_rata,
                'note' => $request->note,
                'applica_interessi' => $request->boolean('applica_interessi'),
                'tasso_interesse' => $request->tasso_interesse,
                'updated_by' => Auth::id(),
            ]);

            // Elimina le rate esistenti
            $pianoRateizzazione->rate()->delete();

            // Ricalcola le rate
            $this->calcolaRate($pianoRateizzazione);

            DB::commit();

            return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                           ->with('success', 'Piano di rateizzazione aggiornato con successo.');

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->back()
                           ->withInput()
                           ->with('error', 'Errore durante l\'aggiornamento del piano: ' . $e->getMessage());
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function destroy(PianoRateizzazione $pianoRateizzazione)
    {
        // Verifica autorizzazione
        $this->authorize('delete', $pianoRateizzazione);

        // Solo i piani in bozza possono essere eliminati
        if ($pianoRateizzazione->stato !== 'bozza') {
            return redirect()->route('admin.piani-rateizzazione.index')
                           ->with('error', 'Impossibile eliminare un piano già attivato.');
        }

        DB::beginTransaction();

        try {
            // Elimina le rate
            $pianoRateizzazione->rate()->delete();
            
            // Elimina il piano
            $pianoRateizzazione->delete();

            DB::commit();

            return redirect()->route('admin.piani-rateizzazione.index')
                           ->with('success', 'Piano di rateizzazione eliminato con successo.');

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->route('admin.piani-rateizzazione.index')
                           ->with('error', 'Errore durante l\'eliminazione del piano: ' . $e->getMessage());
        }
    }

    /**
     * Attiva un piano di rateizzazione
     */
    public function attiva(PianoRateizzazione $pianoRateizzazione)
    {
        // Verifica autorizzazione
        $this->authorize('update', $pianoRateizzazione);

        if ($pianoRateizzazione->stato !== 'bozza') {
            return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                           ->with('error', 'Il piano è già stato attivato.');
        }

        // Verifica che ci siano rate
        if (!$pianoRateizzazione->rate()->exists()) {
            return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                           ->with('error', 'Impossibile attivare un piano senza rate.');
        }

        $pianoRateizzazione->update([
            'stato' => 'attivo',
            'data_attivazione' => now(),
            'attivato_by' => Auth::id(),
        ]);

        return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                        ->with('success', 'Piano di rateizzazione attivato con successo.');
    }

    /**
     * Sospende un piano di rateizzazione
     */
    public function sospendi(PianoRateizzazione $pianoRateizzazione)
    {
        // Verifica autorizzazione
        $this->authorize('update', $pianoRateizzazione);

        if ($pianoRateizzazione->stato !== 'attivo') {
            return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                           ->with('error', 'Il piano non è attivo.');
        }

        $pianoRateizzazione->update([
            'stato' => 'sospeso',
            'data_sospensione' => now(),
            'sospeso_by' => Auth::id(),
        ]);

        return redirect()->route('admin.piani-rateizzazione.show', $pianoRateizzazione)
                        ->with('success', 'Piano di rateizzazione sospeso con successo.');
    }

    /**
     * Calcola le rate per un piano di rateizzazione
     */
    private function calcolaRate(PianoRateizzazione $piano)
    {
        $dataScadenza = Carbon::parse($piano->data_inizio);
        $importoRata = $piano->importo_totale / $piano->numero_rate;
        $importoPrimaRata = $piano->importo_prima_rata ?? $importoRata;

        // Calcola gli interessi se applicabili
        $importoTotaleConInteressi = $piano->importo_totale;
        if ($piano->applica_interessi && $piano->tasso_interesse > 0) {
            $importoTotaleConInteressi = $piano->importo_totale * (1 + ($piano->tasso_interesse / 100));
            $importoRata = $importoTotaleConInteressi / $piano->numero_rate;
        }

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

            Rata::create([
                'piano_rateizzazione_id' => $piano->id,
                'numero_rata' => $i,
                'importo' => round($importoCorrente, 2),
                'data_scadenza' => $dataScadenza->copy(),
                'stato' => 'da_pagare',
            ]);

            // Calcola la prossima data di scadenza
            switch ($piano->frequenza) {
                case 'mensile':
                    $dataScadenza->addMonth();
                    break;
                case 'bimestrale':
                    $dataScadenza->addMonths(2);
                    break;
                case 'trimestrale':
                    $dataScadenza->addMonths(3);
                    break;
                case 'semestrale':
                    $dataScadenza->addMonths(6);
                    break;
            }
        }
    }

    /**
     * Genera un codice piano univoco
     */
    private function generateCodicePiano(): string
    {
        do {
            $codice = 'PR' . strtoupper(Str::random(6));
        } while (PianoRateizzazione::where('codice_piano', $codice)->exists());

        return $codice;
    }
}
