<?php

declare(strict_types=1);

namespace App\Http\Controllers;

use App\Models\Gruppo;
use App\Models\Individuo;
use App\Models\Diocesi;
use Illuminate\Http\Request;

class GruppoController extends Controller
{
    public function index()
    {
        $this->authorizeRead('gruppi');

        $viewMode = request('view', 'table');
        $user = auth()->user();

        $vista = \App\Models\VistaReport::where('user_id', $user->id)
            ->where('tipo', 'gruppi')
            ->where('is_default', true)
            ->first();

        $allColumns = ['nome', 'descrizione', 'diocesi', 'livello', 'padre', 'membri', 'responsabili', 'indirizzo', 'citta', 'telefono', 'email'];
        $defaultVisible = ['nome', 'livello', 'padre', 'membri', 'responsabili'];

        if ($vista && !empty($vista->colonne_visibili)) {
            $visibleColumns = $vista->colonne_visibili;
        } else {
            $visibleColumns = $defaultVisible;
        }

        $allGruppi = Gruppo::with(['diocesi', 'parent', 'children', 'individui', 'avatar'])
            ->orderBy('nome')
            ->get()
            ->map(function ($gruppo) {
                $depth = 0;
                $parent = $gruppo->parent;
                while ($parent) {
                    $depth++;
                    $parent = $parent->parent;
                }
                $gruppo->depth = $depth;
                return $gruppo;
            });

        if ($viewMode === 'table') {
            $gruppi = $this->sortGruppiHierarchically($allGruppi);
        } else {
            $gruppi = $allGruppi;
        }

        return view('gruppi.index', compact(
            'gruppi',
            'allColumns',
            'visibleColumns',
            'viewMode',
            'vista'
        ));
    }

    protected function sortGruppiHierarchically($gruppi)
    {
        $rootGroups = $gruppi->filter(fn($g) => $g->parent_id === null)->sortBy('nome');
        $sorted = collect();

        foreach ($rootGroups as $root) {
            $sorted->push($root);
            $this->addChildrenRecursive($root, $gruppi, $sorted);
        }

        return $sorted;
    }

    protected function addChildrenRecursive($parent, $allGruppi, &$sorted)
    {
        $children = $allGruppi->filter(fn($g) => $g->parent_id === $parent->id)->sortBy('nome');

        foreach ($children as $child) {
            $sorted->push($child);
            $this->addChildrenRecursive($child, $allGruppi, $sorted);
        }
    }

    public function create(Request $request)
    {
        $this->authorizeWrite('gruppi');
        $diocesi = Diocesi::orderBy('nome')->get();
        $allGruppi = Gruppo::orderBy('nome')->get();
        $selectedParent = $request->query('parent_id') ? Gruppo::find($request->query('parent_id')) : null;
        $individui = Individuo::orderBy('cognome')->orderBy('nome')->get();
        return view('gruppi.create', compact('diocesi', 'allGruppi', 'selectedParent', 'individui'));
    }

    public function store(Request $request)
    {
        $this->authorizeWrite('gruppi');
        $data = $request->validate([
            'nome' => 'required|string|max:255',
            'descrizione' => 'nullable|string',
            'parent_id' => 'nullable|exists:gruppi,id',
            'diocesi_id' => 'nullable|exists:diocesi,id',
            'responsabile_ids' => 'nullable|array',
            'responsabile_ids.*' => 'exists:individui,id',
            'indirizzo_incontro' => 'nullable|string|max:500',
            'cap_incontro' => 'nullable|string|max:10',
            'città_incontro' => 'nullable|string|max:255',
            'sigla_provincia_incontro' => 'nullable|string|max:2',
            'mappa_posizione' => 'nullable|string',
        ]);

        if (!empty($data['responsabile_ids'])) {
            $data['responsabile_ids'] = json_encode(array_values($data['responsabile_ids']));
        }

        $gruppo = Gruppo::create($data);

        if ($request->has('individui')) {
            foreach ($request->individui as $individuoData) {
                if (!empty($individuoData['individuo_id'])) {
                    $gruppo->individui()->attach($individuoData['individuo_id'], [
                        'ruolo_nel_gruppo' => $individuoData['ruolo_nel_gruppo'] ?? null,
                        'data_adesione' => $individuoData['data_adesione'] ?? null,
                    ]);
                }
            }
        }

        return redirect('/gruppi/' . $gruppo->id)->with('success', 'Gruppo creato con successo.');
    }

    public function show($id)
    {
        $this->authorizeRead('gruppi');
        $gruppo = Gruppo::with(['parent', 'children', 'diocesi', 'individui.contatti', 'individui.documenti', 'individui' => function ($q) {
            $q->withPivot('ruolo_ids', 'ruolo_nel_gruppo', 'data_adesione');
        }, 'avatar', 'eventi' => function ($q) {
            $q->where('is_incontro_gruppo', true);
        }, 'eventi.responsabili.contatti'])->findOrFail($id);
        return view('gruppi.show', compact('gruppo'));
    }

    public function edit($id)
    {
        $this->authorizeWrite('gruppi');
        $gruppo = Gruppo::with(['individui.contatti', 'individui.documenti', 'avatar'])->findOrFail($id);
        $diocesi = Diocesi::orderBy('nome')->get();
        $gruppi = Gruppo::where('id', '!=', $gruppo->id)->orderBy('nome')->get();
        $membri = $gruppo->individui()->withPivot('ruolo_ids', 'ruolo_nel_gruppo', 'data_adesione')->orderBy('cognome')->orderBy('nome')->get();
        return view('gruppi.edit', compact('gruppo', 'diocesi', 'gruppi', 'membri'));
    }

    public function update(Request $request, $id)
    {
        $this->authorizeWrite('gruppi');
        $gruppo = Gruppo::findOrFail($id);
        $data = $request->validate([
            'nome' => 'required|string|max:255',
            'descrizione' => 'nullable|string',
            'parent_id' => 'nullable|exists:gruppi,id',
            'diocesi_id' => 'nullable|exists:diocesi,id',
            'responsabile_ids' => 'nullable|array',
            'responsabile_ids.*' => 'exists:individui,id',
            'indirizzo_incontro' => 'nullable|string|max:500',
            'cap_incontro' => 'nullable|string|max:10',
            'città_incontro' => 'nullable|string|max:255',
            'sigla_provincia_incontro' => 'nullable|string|max:2',
            'mappa_posizione' => 'nullable|string',
        ]);

        if (!empty($data['responsabile_ids'])) {
            $data['responsabile_ids'] = json_encode(array_values($data['responsabile_ids']));
        } else {
            $data['responsabile_ids'] = null;
        }

        $gruppo->update($data);

        if ($request->has('individui')) {
            $gruppo->individui()->detach();
            foreach ($request->individui as $individuoData) {
                if (!empty($individuoData['individuo_id'])) {
                    $gruppo->individui()->attach($individuoData['individuo_id'], [
                        'ruolo_ids' => !empty($individuoData['ruolo_ids']) ? json_encode(array_values($individuoData['ruolo_ids'])) : null,
                        'data_adesione' => $individuoData['data_adesione'] ?? null,
                    ]);
                }
            }
        }

        return redirect('/gruppi/' . $gruppo->id)->with('success', 'Gruppo aggiornato.');
    }

    public function destroy($id)
    {
        $this->authorizeDelete('gruppi');
        $gruppo = Gruppo::with('children', 'individui')->findOrFail($id);

        $hasChildren = $gruppo->children()->count() > 0;
        $isSuperAdmin = auth()->user()->isSuperAdmin();

        if ($hasChildren && !$isSuperAdmin) {
            return redirect('/gruppi')->with('error', 'Solo il superamministratore può eliminare un gruppo con sottogruppi.');
        }

        if ($hasChildren && $isSuperAdmin) {
            foreach ($gruppo->children as $child) {
                $this->destroyGruppo($child);
            }
        }

        $this->destroyGruppo($gruppo);

        return redirect('/gruppi')->with('success', 'Gruppo eliminato.');
    }

    protected function destroyGruppo(Gruppo $gruppo): void
    {
        $gruppo->individui()->detach();
        $gruppo->eventi()->detach();
        foreach ($gruppo->documenti as $documento) {
            if ($documento->file_path && file_exists(storage_path('app/public/' . $documento->file_path))) {
                unlink(storage_path('app/public/' . $documento->file_path));
            }
        }
        $gruppo->documenti()->delete();
        $gruppo->delete();
    }

    public function allGruppi()
    {
        $this->authorizeRead('gruppi');
        $gruppi = Gruppo::select('id', 'nome')
            ->orderBy('nome')
            ->get()
            ->map(function($g) {
                return [
                    'id' => $g->id,
                    'nome' => $g->nome,
                    'full_path' => $g->getFullPathAttribute(),
                ];
            });
        return response()->json($gruppi);
    }

    public function individuiEmail(Gruppo $gruppo)
    {
        $this->authorizeRead('gruppi');
        $individui = $gruppo->individui()->with('contatti')->get();
        
        $result = $individui->map(function($ind) {
            $emails = $ind->contatti->where('tipo', 'email')->pluck('valore')->toArray();
            return [
                'id' => $ind->id,
                'codice_id' => $ind->codice_id,
                'cognome' => $ind->cognome,
                'nome' => $ind->nome,
                'emails' => $emails,
            ];
        });
        
        return response()->json($result);
    }

    public function saveVista(Request $request)
    {
        $data = $request->validate([
            'nome' => 'required|string|max:255',
            'colonne_visibili' => 'nullable|array',
            'colonne_visibili.*' => 'string',
            'is_default' => 'nullable|boolean',
        ]);

        if (!empty($data['is_default'])) {
            \App\Models\VistaReport::where('user_id', auth()->id())
                ->where('tipo', 'gruppi')
                ->where('is_default', true)
                ->update(['is_default' => false]);
        }

        $vista = \App\Models\VistaReport::create([
            'user_id' => auth()->id(),
            'nome' => $data['nome'],
            'tipo' => 'gruppi',
            'colonne_visibili' => $data['colonne_visibili'] ?? [],
            'is_default' => !empty($data['is_default']),
        ]);

        return response()->json(['success' => true, 'vista_id' => $vista->id]);
    }

    public function deleteVista($id)
    {
        $vista = \App\Models\VistaReport::where('user_id', auth()->id())
            ->where('id', $id)
            ->firstOrFail();
        $vista->delete();

        return redirect()->route('gruppi.index')->with('success', 'Vista eliminata.');
    }
}
