<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Attivita;
use App\Models\Cucina;
use App\Models\Piatto;
use App\Models\Saltacoda;
use App\Models\SaltacodaOrdine;
use App\Models\SaltacodaRigaordine;
use App\Models\VariantePiatto;
use App\Models\SaltacodaRigaOrdineHasVariante;
use Illuminate\Support\Facades\DB;


class SaltacodaController extends Controller
{
    public static $permission_group = "Saltacoda";
    public static $permissions = [
        'view-saltacoda' => 'Vedi',
        'create-saltacoda' => 'Crea',
        'edit-saltacoda' => 'Modifica',
        'delete-saltacoda' => 'Elimina',
    ];

    public static function middleware(): array
    {
        return [
            new Middleware('permission:view-saltacoda', only: ['index']),
            new Middleware('permission:create-saltacoda|edit-saltacoda|delete-saltacoda', only: ['store', 'update', 'destroy']),
        ];
    }

    public function index(Request $request)
    {
        $attivita = Attivita::find(session()->get('attivita_attuale'));
        if(!$attivita) {
            return redirect()->route('dashboard')->with('error', 'Attività non trovata');
        }
        $saltacoda = Saltacoda::where('attivita_id', $attivita->id)->first();
        
        if(!$saltacoda) {
            return view('saltacoda.index', ['attivita' => $attivita]);
        }
        return view('saltacoda.index', compact('attivita', 'saltacoda'));
    }

    public function attiva(Request $request)
    {
        $attivita = Attivita::find(session()->get('attivita_attuale'));
        if(!$attivita) {
            return redirect()->route('dashboard')->with('error', 'Attività non trovata');
        }
        $saltacoda = Saltacoda::where('attivita_id', $attivita->id)->first();
        if(!$saltacoda) {
            $saltacoda = Saltacoda::create([
                'attivita_id' => $attivita->id,
                'is_attivo' => true,
            ]);
    }else{
        $saltacoda->is_attivo = true;
        $saltacoda->save();
    }
        return redirect()->route('saltacoda.index')->with('success', 'Saltacoda abilitato');
    }

    public function store(Request $request)
    {
        // dd($request->all());
        $request->validate([
            'attivita_id' => 'required|exists:attivita,id',
            'is_attivo' => 'required|boolean',
            'max_ordini' => 'nullable|integer|min:0',
            'info' => 'nullable|json',
            'istruzioni' => 'nullable|json',
        ]);

        $saltacoda = Saltacoda::updateOrCreate(
            ['attivita_id' => $request->attivita_id],
            [
                'is_attivo' => $request->is_attivo,
                'max_ordini' => $request->max_ordini,
                'info' => $request->info,
                'istruzioni' => $request->filled('istruzioni')
                    ? Saltacoda::normalizeIstruzioni($request->istruzioni)
                    : Saltacoda::defaultIstruzioni(),
            ]
        );
        return redirect()->route('saltacoda.index')->with('success', 'Saltacoda salvato');
    }

    public function show(Request $request)
    {
        $attivita = Attivita::find($request->get('attivita_id'));
        if(!$attivita) {
            return response()->json([
                'success' => false,
                'message' => 'Attività non trovata'
            ]);
        }
        
        $saltacoda = Saltacoda::where('attivita_id', $attivita->id)
        ->where('is_attivo', true)
        ->first();
        if(!$saltacoda) {
            return abort(404);
        }


        $cucine = Cucina::query()
                ->where('attivita_id', $attivita->id)
                ->where('is_attiva', true)
                ->with(['piatti' => function ($q) use ($attivita) {
                    $q->where('attivita_id', $attivita->id)
                    ->where('is_attivo', true)
                    ->orderBy('nome');
                }])
                ->get();

        $variantiPerPiatto = [];
        $variantiPerCucina = [];
        $varianti = VariantePiatto::query()
            ->where('attivita_id', $attivita->id)
            ->where('is_attivo', true)
            ->orderBy('label')
            ->get(['id', 'piatto_id', 'cucina_id', 'label', 'prezzo']);

        foreach ($varianti as $variante) {
            $entry = [
                'id' => $variante->id,
                'label' => $variante->label,
                'prezzo' => (float) $variante->prezzo,
            ];

            if ($variante->piatto_id) {
                $variantiPerPiatto[$variante->piatto_id][] = $entry;
                continue;
            }

            if ($variante->cucina_id) {
                $variantiPerCucina[$variante->cucina_id][] = $entry;
            }
        }

        $campiInfo = [];
        $rawInfo = $saltacoda->info;
        if (is_string($rawInfo) && $rawInfo !== '') {
            $decoded = json_decode($rawInfo, true);
            if (is_array($decoded)) {
                foreach ($decoded as $key => $value) {
                    if (is_string($value)) {
                        $campiInfo[] = [
                            'key' => (string) $key,
                            'label' => $value,
                            'type' => 'text',
                            'required' => false,
                        ];
                        continue;
                    }

                    if (is_array($value)) {
                        $type = $value['type'] ?? 'text';
                        if (!in_array($type, ['text', 'boolean', 'time'], true)) {
                            $type = 'text';
                        }

                        $campiInfo[] = [
                            'key' => (string) $key,
                            'label' => (string) ($value['label'] ?? $key),
                            'type' => $type,
                            'required' => (bool) ($value['required'] ?? false),
                        ];
                    }
                }
            }
        }

        return view('saltacoda.show', [
            'attivita' => $attivita,
            'cucine' => $cucine,
            'campi_info' => $campiInfo,
            'saltacoda_id' => $saltacoda->id,
            'varianti_per_piatto' => $variantiPerPiatto,
            'varianti_per_cucina' => $variantiPerCucina,
        ]);
    }

    public function pre_ordine_salva(Request $request)
    {
        $request->validate([
            'saltacoda_id' => 'required|exists:saltacoda,id',
            'attivita_id' => 'required|exists:attivita,id',
            'riga_ordine' => 'required|array|min:1',
            'riga_ordine.*.piatto_id' => 'required|exists:piatto,id',
            'riga_ordine.*.qta' => 'required|integer|min:1',
            'riga_ordine.*.note' => 'nullable|string|max:500',
            'riga_ordine.*.varianti' => 'nullable|array',
            'riga_ordine.*.varianti.*' => 'integer|exists:variante_piatto,id',
            'info_cliente' => 'nullable|array',
            'idempotency_key' => 'nullable|string|max:120',
        ]);

        $saltacoda = Saltacoda::where('id', $request->saltacoda_id)
            ->where('attivita_id', $request->attivita_id)
            ->first();
        if (!$saltacoda) {
            return response()->json([
                'success' => false,
                'message' => 'Saltacoda non valida per questa attività.'
            ], 422);
        }

        try {
            $saltacoda_ordine = DB::transaction(function () use ($request) {
                $saltacoda_ordine = SaltacodaOrdine::firstOrNew([
                    'riferimento' => $request->idempotency_key,
                ]);

                if (!$saltacoda_ordine->exists) {
                    $saltacoda_ordine->codice = $this->genera_codice_saltacoda();
                }

                $saltacoda_ordine->fill([
                    'riferimento' => $request->idempotency_key,
                    'attivita_id' => $request->attivita_id,
                    'info' => $request->info_cliente,
                    'prenotazione_id' => null,
                    'stato' => SaltacodaOrdine::PRE_ORDINE,
                    'pagamento_id' => null,
                    'note' => null,
                    'tipo' => null,
                    'prezzo' => 0,
                    'metodo_pagamento_id' => null,
                ]);
                $saltacoda_ordine->save();

                $saltacoda_ordine->saltacoda_riga_ordine()->delete();

                foreach ($request->riga_ordine as $riga) {
                    $piatto = Piatto::query()
                        ->where('id', $riga['piatto_id'])
                        ->where('attivita_id', $request->attivita_id)
                        ->first();

                    if (!$piatto) {
                        throw new \InvalidArgumentException('Piatto non valido per questa attività.');
                    }

                    $qta = (int) $riga['qta'];
                    $varianteIds = collect($riga['varianti'] ?? [])->unique()->values();
                    $varianti = $varianteIds->isEmpty()
                        ? collect()
                        : VariantePiatto::query()
                            ->where('attivita_id', $request->attivita_id)
                            ->where('is_attivo', true)
                            ->whereIn('id', $varianteIds)
                            ->get();

                    if ($varianteIds->count() !== $varianti->count()) {
                        throw new \InvalidArgumentException('Una o più varianti non sono valide per questa attività.');
                    }

                    $prezzoRiga = $this->calcolaPrezzoRigaSaltacoda($piatto, $qta, $varianti);

                    $saltacoda_riga = SaltacodaRigaordine::create([
                        'saltacoda_ordine_id' => $saltacoda_ordine->id,
                        'piatto_id' => $piatto->id,
                        'quantita' => $qta,
                        'note' => $riga['note'] ?? null,
                        'prezzo' => $prezzoRiga,
                    ]);

                    foreach ($varianti as $variante) {
                        SaltacodaRigaOrdineHasVariante::create([
                            'saltacoda_riga_ordine_id' => $saltacoda_riga->id,
                            'variante_id' => $variante->id,
                            'nota' => null,
                        ]);
                    }
                }

                $saltacoda_ordine->prezzo = $saltacoda_ordine->saltacoda_riga_ordine()->sum('prezzo');
                $saltacoda_ordine->save();

                return $saltacoda_ordine->load([
                    'saltacoda_riga_ordine.piatto',
                    'saltacoda_riga_ordine.saltacoda_has_variante.variante_piatto',
                ]);
            });

            return response()->json([
                'success' => true,
                'message' => 'Pre-ordine salvato',
                'data' => $saltacoda_ordine,
            ]);
        } catch (\InvalidArgumentException $exception) {
            return response()->json([
                'success' => false,
                'message' => $exception->getMessage(),
            ], 422);
        }
    }

    public function pre_ordine_show(Request $request)
    {
        $saltacoda_ordine = SaltacodaOrdine::query()
            ->with([
                'saltacoda_riga_ordine.piatto',
                'saltacoda_riga_ordine.saltacoda_has_variante.variante_piatto',
                'attivita',
            ])
            ->where('codice', $request->get('codice'))
            ->first();
        if(!$saltacoda_ordine) {
            return abort(404);
        }
        return view('saltacoda.pre_ordine', ['saltacoda_ordine' => $saltacoda_ordine]);
    }

    private function calcolaPrezzoRigaSaltacoda(Piatto $piatto, int $qta, $varianti): float
    {
        $prezzo = (float) $piatto->prezzo * $qta;

        foreach ($varianti as $variante) {
            $extra = (float) ($variante->prezzo ?? 0);
            if ($extra !== 0.0) {
                $prezzo += $extra * $qta;
            }
        }

        return round($prezzo, 2);
    }

    private function genera_codice_saltacoda()
    {
        $lettereSicure = ['A', 'C', 'E', 'F', 'G', 'L', 'M', 'N', 'R', 'S', 'U', 'Z'];
        $parteLettera = $lettereSicure[rand(0, count($lettereSicure) - 1)];
        $parteCifre2 = str_pad(strval(rand(0, 99)), 2, '0', STR_PAD_LEFT);
        $parteCifre3 = str_pad(strval(rand(0, 999)), 3, '0', STR_PAD_LEFT);
        $codice = strtoupper($parteLettera . $parteCifre2 . '-' . $parteCifre3);

        if (SaltacodaOrdine::where('codice', $codice)->exists()) {
            return $this->genera_codice_saltacoda();
        }

        return $codice;
    }
}
