<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\RipartizioneSpese;
use App\Models\DettaglioRipartizioneSpese;
use App\Models\VoceSpesa;
use App\Models\Stabile;
use App\Models\TabellaMillesimale;
use App\Models\UnitaImmobiliare;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;

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

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

        // Filtro per voce di spesa
        if ($request->filled('voce_spesa_id')) {
            $query->where('voce_spesa_id', $request->voce_spesa_id);
        }

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

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

        $ripartizioni = $query->orderBy('data_ripartizione', 'desc')->paginate(15);

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

        $vociSpesa = VoceSpesa::whereHas('stabile', function($q) {
                                   $q->where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null);
                               })
                               ->orderBy('denominazione')
                               ->get();

        return view('admin.ripartizioni-spesa.index', compact('ripartizioni', 'stabili', 'vociSpesa'));
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create(Request $request)
    {
        $vociSpesa = VoceSpesa::with(['stabile', 'tabellaMillesimaleDefault'])
                             ->whereHas('stabile', function($q) {
                                 $q->where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null);
                             })
                             ->where('stato', 'attiva')
                             ->orderBy('denominazione')
                             ->get();

        $voceSpesaSelezionata = null;
        if ($request->filled('voce_spesa_id')) {
            $voceSpesaSelezionata = $vociSpesa->firstWhere('id', $request->voce_spesa_id);
        }

        return view('admin.ripartizioni-spesa.create', compact('vociSpesa', 'voceSpesaSelezionata'));
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request)
    {
        $request->validate([
            'voce_spesa_id' => 'required|exists:voci_spesa,id',
            'descrizione' => 'required|string|max:255',
            'importo_totale' => 'required|numeric|min:0',
            'data_ripartizione' => 'required|date',
            'tabella_millesimale_id' => 'required|exists:tabelle_millesimali,id',
            'periodo_riferimento' => 'nullable|string|max:100',
            'note' => 'nullable|string',
            'dettagli' => 'nullable|array',
            'dettagli.*.unita_immobiliare_id' => 'required|exists:unita_immobiliari,id',
            'dettagli.*.importo' => 'required|numeric|min:0',
            'dettagli.*.esclusa' => 'nullable|boolean',
            'dettagli.*.note' => 'nullable|string|max:255',
        ]);

        // Verifica che la voce di spesa appartenga all'amministratore
        $voceSpesa = VoceSpesa::whereHas('stabile', function($q) {
                                   $q->where('amministratore_id', Auth::user()->amministratore->id_amministratore ?? null);
                               })
                               ->findOrFail($request->voce_spesa_id);

        // Verifica che la tabella millesimale appartenga allo stabile
        $tabellaMillesimale = TabellaMillesimale::where('id', $request->tabella_millesimale_id)
                                               ->where('stabile_id', $voceSpesa->stabile_id)
                                               ->firstOrFail();

        DB::beginTransaction();

        try {
            // Crea la ripartizione principale
            $ripartizione = RipartizioneSpese::create([
                'codice_ripartizione' => $this->generateCodiceRipartizione(),
                'voce_spesa_id' => $request->voce_spesa_id,
                'descrizione' => $request->descrizione,
                'importo_totale' => $request->importo_totale,
                'data_ripartizione' => $request->data_ripartizione,
                'tabella_millesimale_id' => $request->tabella_millesimale_id,
                'periodo_riferimento' => $request->periodo_riferimento,
                'note' => $request->note,
                'stato' => 'bozza',
                'created_by' => Auth::id(),
            ]);

            // Se non sono stati forniti dettagli, calcola automaticamente
            if (empty($request->dettagli)) {
                $this->calcolaRipartizioneAutomatica($ripartizione);
            } else {
                // Crea i dettagli forniti
                foreach ($request->dettagli as $dettaglio) {
                    DettaglioRipartizioneSpese::create([
                        'ripartizione_spese_id' => $ripartizione->id,
                        'unita_immobiliare_id' => $dettaglio['unita_immobiliare_id'],
                        'importo' => $dettaglio['importo'],
                        'esclusa' => $dettaglio['esclusa'] ?? false,
                        'note' => $dettaglio['note'] ?? null,
                    ]);
                }
            }

            DB::commit();

            return redirect()->route('admin.ripartizioni-spesa.show', $ripartizione)
                           ->with('success', 'Ripartizione spesa creata con successo.');

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

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

        $ripartizioneSpesa->load([
            'voceSpesa.stabile',
            'tabellaMillesimale',
            'dettagli.unitaImmobiliare.anagraficaCondominiale.soggetto',
            'createdBy',
            'updatedBy'
        ]);

        return view('admin.ripartizioni-spesa.show', compact('ripartizioneSpesa'));
    }

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

        // Solo le ripartizioni in bozza possono essere modificate
        if ($ripartizioneSpesa->stato !== 'bozza') {
            return redirect()->route('admin.ripartizioni-spesa.show', $ripartizioneSpesa)
                           ->with('error', 'Impossibile modificare una ripartizione già confermata.');
        }

        $ripartizioneSpesa->load([
            'voceSpesa.stabile',
            'tabellaMillesimale',
            'dettagli.unitaImmobiliare'
        ]);

        $tabelleMillesimali = TabellaMillesimale::where('stabile_id', $ripartizioneSpesa->voceSpesa->stabile_id)
                                               ->where('stato', 'attiva')
                                               ->orderBy('denominazione')
                                               ->get();

        return view('admin.ripartizioni-spesa.edit', compact('ripartizioneSpesa', 'tabelleMillesimali'));
    }

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

        // Solo le ripartizioni in bozza possono essere modificate
        if ($ripartizioneSpesa->stato !== 'bozza') {
            return redirect()->route('admin.ripartizioni-spesa.show', $ripartizioneSpesa)
                           ->with('error', 'Impossibile modificare una ripartizione già confermata.');
        }

        $request->validate([
            'descrizione' => 'required|string|max:255',
            'importo_totale' => 'required|numeric|min:0',
            'data_ripartizione' => 'required|date',
            'tabella_millesimale_id' => 'required|exists:tabelle_millesimali,id',
            'periodo_riferimento' => 'nullable|string|max:100',
            'note' => 'nullable|string',
            'dettagli' => 'nullable|array',
            'dettagli.*.unita_immobiliare_id' => 'required|exists:unita_immobiliari,id',
            'dettagli.*.importo' => 'required|numeric|min:0',
            'dettagli.*.esclusa' => 'nullable|boolean',
            'dettagli.*.note' => 'nullable|string|max:255',
        ]);

        // Verifica che la tabella millesimale appartenga allo stabile
        $tabellaMillesimale = TabellaMillesimale::where('id', $request->tabella_millesimale_id)
                                               ->where('stabile_id', $ripartizioneSpesa->voceSpesa->stabile_id)
                                               ->firstOrFail();

        DB::beginTransaction();

        try {
            // Aggiorna la ripartizione principale
            $ripartizioneSpesa->update([
                'descrizione' => $request->descrizione,
                'importo_totale' => $request->importo_totale,
                'data_ripartizione' => $request->data_ripartizione,
                'tabella_millesimale_id' => $request->tabella_millesimale_id,
                'periodo_riferimento' => $request->periodo_riferimento,
                'note' => $request->note,
                'updated_by' => Auth::id(),
            ]);

            // Elimina i dettagli esistenti
            $ripartizioneSpesa->dettagli()->delete();

            // Se non sono stati forniti dettagli, calcola automaticamente
            if (empty($request->dettagli)) {
                $this->calcolaRipartizioneAutomatica($ripartizioneSpesa);
            } else {
                // Crea i nuovi dettagli
                foreach ($request->dettagli as $dettaglio) {
                    DettaglioRipartizioneSpese::create([
                        'ripartizione_spese_id' => $ripartizioneSpesa->id,
                        'unita_immobiliare_id' => $dettaglio['unita_immobiliare_id'],
                        'importo' => $dettaglio['importo'],
                        'esclusa' => $dettaglio['esclusa'] ?? false,
                        'note' => $dettaglio['note'] ?? null,
                    ]);
                }
            }

            DB::commit();

            return redirect()->route('admin.ripartizioni-spesa.show', $ripartizioneSpesa)
                           ->with('success', 'Ripartizione spesa aggiornata con successo.');

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

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

        // Solo le ripartizioni in bozza possono essere eliminate
        if ($ripartizioneSpesa->stato !== 'bozza') {
            return redirect()->route('admin.ripartizioni-spesa.index')
                           ->with('error', 'Impossibile eliminare una ripartizione già confermata.');
        }

        DB::beginTransaction();

        try {
            // Elimina i dettagli
            $ripartizioneSpesa->dettagli()->delete();
            
            // Elimina la ripartizione
            $ripartizioneSpesa->delete();

            DB::commit();

            return redirect()->route('admin.ripartizioni-spesa.index')
                           ->with('success', 'Ripartizione spesa eliminata con successo.');

        } catch (\Exception $e) {
            DB::rollBack();
            return redirect()->route('admin.ripartizioni-spesa.index')
                           ->with('error', 'Errore durante l\'eliminazione della ripartizione: ' . $e->getMessage());
        }
    }

    /**
     * Conferma una ripartizione spesa
     */
    public function conferma(RipartizioneSpese $ripartizioneSpesa)
    {
        // Verifica autorizzazione
        $this->authorize('update', $ripartizioneSpesa);

        if ($ripartizioneSpesa->stato !== 'bozza') {
            return redirect()->route('admin.ripartizioni-spesa.show', $ripartizioneSpesa)
                           ->with('error', 'La ripartizione è già stata confermata.');
        }

        // Verifica che ci siano dettagli
        if (!$ripartizioneSpesa->dettagli()->exists()) {
            return redirect()->route('admin.ripartizioni-spesa.show', $ripartizioneSpesa)
                           ->with('error', 'Impossibile confermare una ripartizione senza dettagli.');
        }

        // Verifica che la somma dei dettagli corrisponda all'importo totale
        $sommaDettagli = $ripartizioneSpesa->dettagli()->sum('importo');
        if (abs($sommaDettagli - $ripartizioneSpesa->importo_totale) > 0.01) {
            return redirect()->route('admin.ripartizioni-spesa.show', $ripartizioneSpesa)
                           ->with('error', 'La somma dei dettagli non corrisponde all\'importo totale.');
        }

        $ripartizioneSpesa->update([
            'stato' => 'confermata',
            'data_conferma' => now(),
            'confermata_by' => Auth::id(),
        ]);

        return redirect()->route('admin.ripartizioni-spesa.show', $ripartizioneSpesa)
                        ->with('success', 'Ripartizione spesa confermata con successo.');
    }

    /**
     * Calcola automaticamente la ripartizione basata sui millesimi
     */
    private function calcolaRipartizioneAutomatica(RipartizioneSpese $ripartizione)
    {
        $tabella = $ripartizione->tabellaMillesimale;
        $unita = UnitaImmobiliare::where('stabile_id', $ripartizione->voceSpesa->stabile_id)->get();

        foreach ($unita as $unita_immobiliare) {
            $millesimi = $tabella->getMillesimiForUnita($unita_immobiliare->id);
            $importo = ($ripartizione->importo_totale * $millesimi) / 1000;

            DettaglioRipartizioneSpese::create([
                'ripartizione_spese_id' => $ripartizione->id,
                'unita_immobiliare_id' => $unita_immobiliare->id,
                'importo' => round($importo, 2),
                'esclusa' => false,
            ]);
        }
    }

    /**
     * Genera un codice ripartizione univoco
     */
    private function generateCodiceRipartizione(): string
    {
        do {
            $codice = 'RP' . strtoupper(Str::random(6));
        } while (RipartizioneSpese::where('codice_ripartizione', $codice)->exists());

        return $codice;
    }
}
