<?php

namespace App\Http\Controllers;

use App\DataTables\PuntoVenditaDataTable;
use App\DataTables\PuntoVenditaDataTableEditor;
use App\DataTables\RigaOrdineDataTable;
use App\Models\Dispositivo;
use App\Models\Ordine;
use App\Models\Pagamento;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cookie;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;

class PuntoVenditaController extends Controller
{
    public static $permission_group = 'Punto di vendita';

    public static $permissions = [
        'view-punto_vendita' => 'Vedi',
        'create-punto_vendita' => 'Crea',
        'edit-punto_vendita' => 'Modifica',
        'delete-punto_vendita' => 'Elimina',
    ];

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

    public function index(PuntoVenditaDataTable $dataTable)
    {
        return $dataTable->render('punto_vendita.index');
    }

    public function dettagli_punto_vendita(Request $request)
    {
        $puntoVendita = Dispositivo::query()
            ->with(['attivita', 'hasCucine'])
            ->find($request->punto_vendita_id);

        if (! $puntoVendita) {
            return redirect()->route('punto-vendita.index')
                ->with('error', 'Punto di vendita non trovato');
        }

        return view('punto_vendita.dettaglio_punto_vendita', compact('puntoVendita'));
    }

    public function edit(Request $request)
    {
        $puntoVendita = Dispositivo::with(['hasCucine', 'attivita.cucine', 'attivita.stampanti'])
            ->find($request->get('punto_vendita_id'));
        if (! $puntoVendita) {
            return redirect()->route('punto-vendita.index')
                ->with('error', 'Punto di vendita non trovato');
        }

        return view('punto_vendita.edit', ['puntoVendita' => $puntoVendita]);
    }

    public function update(Request $request)
    {
        $puntoVendita = Dispositivo::find($request->get('punto_vendita_id'));

        if (! $puntoVendita) {
            return redirect()->route('punto-vendita.index')
                ->with('error', 'Punto di vendita non trovato');
        }

        if (Auth::user()->can('edit-punto_vendita')) {

            $validated = $request->validate([
                'nome' => 'sometimes|required',
                'tipo' => 'sometimes|required',
                'attivita_id' => 'sometimes|required|exists:attivita,id',
                'licenza' => 'sometimes|nullable',
                'url_stampante' => 'sometimes|nullable',
                'ubicazione' => 'sometimes|nullable',
                'note' => 'sometimes|nullable',
                'is_attivo' => 'boolean',
                'pin_sblocco' => 'sometimes|nullable',
                'data_apertura_dispositivo' => 'nullable|date',
                'data_chiusura_dispositivo' => 'nullable|date',
                'endpoint_id' => 'sometimes|nullable|exists:endpoint,id',
                'info' => 'sometimes|nullable|json',
            ], [
                'nome.required' => 'Il nome è richiesto',
                'tipo.required' => 'Il tipo è richiesto',
                'attivita_id.required' => 'La attività è richiesta',
                'licenza.required' => 'La licenza è richiesta',
                'url_stampante.required' => 'L\'URL della stampante è richiesta',
                'ubicazione.required' => 'L\'ubicazione è richiesta',
                'pin_sblocco.required' => 'Il pin di sblocco è richiesto',
                'data_apertura_dispositivo.required' => 'La data di apertura del dispositivo è richiesta',
                'data_chiusura_dispositivo.required' => 'La data di chiusura del dispositivo è richiesta',
                'data_apertura_dispositivo.date' => 'La data di apertura del dispositivo deve essere una data valida',
                'data_chiusura_dispositivo.date' => 'La data di chiusura del dispositivo deve essere una data valida',
                'is_attivo.boolean' => 'Indicare una delle due opzioni',
                'pin_sblocco.string' => 'Il pin di sblocco deve essere una stringa',
                'pin_sblocco.required' => 'Il pin di sblocco è richiesto',
                'pin_sblocco.min' => 'Il pin di sblocco deve essere lungo almeno 4 caratteri',
                'pin_sblocco.max' => 'Il pin di sblocco deve essere lungo al massimo 4 caratteri',
                'pin_sblocco.regex' => 'Il pin di sblocco deve contenere solo numeri',
                'pin_sblocco.unique' => 'Il pin di sblocco deve essere unico',
                'info.json' => 'Il campo info deve essere un JSON valido',
            ]);

            // Esempio di info:
            // {
            //     "campi_ordine" :{
            //             "cliente" :{
            //                 "label" : "Cliente",
            //                 "placeholder" : "Inserisci il tup nome",
            //                 "mostra" : true,
            //                 "required" : false,
            //                 "type" : "text",
            //                 "stampa" : true,
            //             }
            //         }
            // }

            if ($request->has('info')) {
                $validated['info'] = json_decode($request->info, true);
            }
            if ($request->has('url_stampante')) {
                $validated['endpoint_id'] = Dispositivo::where('id', $validated['url_stampante'])
                    ->where('tipo', Dispositivo::STAMPANTE)->first()->endpoint_id ?? null;

            }

            $puntoVendita->update($validated);

            return response()->json(['success' => true, 'message' => 'Punto di vendita aggiornato con successo']);
        } else {
            return response()->json(['success' => false, 'message' => 'Non hai il permesso di accedere a questo punto di vendita']);
        }
    }

    public function associa_cucina(Request $request)
    {
        $puntoVendita = Dispositivo::find($request->get('punto_vendita_id'));
        if (! $puntoVendita) {
            return response()->json(['success' => false, 'message' => 'Punto di vendita non trovato']);
        }

        if (Auth::user()->can('edit-punto_vendita')) {
            $cucine_ids = $request->get('cucine_ids');
            $puntoVendita->hasCucine()->sync($cucine_ids);

            return response()->json(['success' => true, 'message' => 'Cucine associate con successo']);
        } else {
            return response()->json(['success' => false, 'message' => 'Non hai il permesso di accedere a questo punto di vendita']);
        }
    }

    public function store(PuntoVenditaDataTableEditor $editor)
    {
        $request = request();
        $input = $request->all();
        if ($request->has('action')) {
            switch ($input['action']) {
                case 'create':
                    if (! Auth::user()->can('create-punto_vendita')) {
                        return;
                    }
                    break;
                case 'edit':
                    if (! Auth::user()->can('edit-punto_vendita')) {
                        return;
                    }
                    break;
                case 'remove':
                    if (! Auth::user()->can('delete-punto_vendita')) {
                        return;
                    }
                    break;
            }
        }

        return $editor->process($request);
    }

    public function show(Request $request, RigaOrdineDataTable $dataTable)
    {
        $isDataTableDrawRequest = $request->has('draw');

        if (! Auth::user()->can('view-punto_vendita')) {
            return redirect()->route('punto-vendita.index')
                ->with('error', 'Non hai il permesso di accedere a questo punto di vendita');
        }

        $puntoVendita = Dispositivo::find(request()->get('punto_vendita_id'));
        if (! $puntoVendita) {
            return redirect()->route('punto-vendita.index')
                ->with('error', 'Punto di vendita non trovato');
        }

        // se non esiste il binding_token nel DB, lo crea
        if ($puntoVendita->binding_token == '' || $puntoVendita->binding_token == null) {
            // $puntoVendita->binding_token = Str::random(32);
            $puntoVendita->binding_token = Str::random(32);
            $puntoVendita->save();
        }

     
        $occupato = $puntoVendita->occupato;
        $CookieBindingToken = Cookie::get('binding_token');
        $BindingTokenPuntoVendita = $puntoVendita->binding_token;
        $stessoDispositivo = $CookieBindingToken == $BindingTokenPuntoVendita;

        switch (true) {
            // nessun cookie e il dispositivo non è occupato ACCEDI
            case ! $CookieBindingToken && $occupato == false:
                Cookie::queue('binding_token', $puntoVendita->binding_token);

                $puntoVendita->occupato = true;
                $puntoVendita->save();
                break;

                // nessun cookie e il dispositivo è occupato 01 NON ACCEDI, c'è qualcun'altro
            case ! $CookieBindingToken && $occupato == true:

                if ($isDataTableDrawRequest) {
                    // Prosegue senza interrompere la risposta DataTable.
                } else {
                    return redirect()->route('punto-vendita.index')->with('error', 'Dispositivo già occupato. Dissociare per potervi accedere.');
                }
                break;

                // cookie esiste e dispositivo non è occupato 10 ACCEDI
            case $CookieBindingToken && $occupato == false:

                if ($stessoDispositivo) {
                    $puntoVendita->occupato = true;
                    $puntoVendita->save();
                    break;

                } else {

                    Dispositivo::where('id', '!=', $puntoVendita->id)
                        ->where('binding_token', $CookieBindingToken)
                        ->update(['occupato' => false]);

                    Cookie::queue('binding_token', $puntoVendita->binding_token);
                    $puntoVendita->occupato = true;
                    $puntoVendita->save();
                }
                break;

                // cookie esiste e dispositivo è occupato 11 ACCEDI SE SEI TU
            case $CookieBindingToken && $occupato == true:

                if ($stessoDispositivo) {
                    break;

                } else {
                    
                    if ($isDataTableDrawRequest) {
                        // Prosegue senza interrompere la risposta DataTable.
                    } else {
                        dd('11, altro dispositivo', json_encode(request()->cookie()));

                        return redirect()->route('punto-vendita.index')->with('error', 'Dispositivo già occupato. Dissociare per potervi accedere.');
                    }
                }
                break;

        }

        // dd(Cookie::get('binding_token'));
        $cucine = $puntoVendita->cucine()
            ->where('is_attiva', true)
            ->with(['piatti' => function ($query) {
                $query->where('is_attivo', true)
                    ->with('allergeni')
                    ->orderBy('nome');
            }])
            ->orderBy('nome')
            ->get();

        $ordine = Ordine::firstOrCreate([
            'stato' => Ordine::CARRELLO,
            'dispositivo_id' => $puntoVendita->id,
            'attivita_id' => $puntoVendita->attivita_id,
        ]);

        Session::put([
            'dispositivo_id' => $puntoVendita->id,
            'attivita_id' => $puntoVendita->attivita->id,
            'attivita_attuale' => $puntoVendita->attivita->id,
        ]);
        // dd(Session::all());

        $dataTable->ordine_id = $ordine->id;

        if ($request->has('vista') && $request->vista == 'catalogo') {
            $dataTable->vista = 'catalogo';
        }

        switch ($puntoVendita->tipo) {
            case Dispositivo::CASSA:
                if ($request->has('vista') && $request->vista == 'catalogo') {
                    return $dataTable->render('punto_vendita.cassa.viste.catalogo.index', ['punto_vendita' => $puntoVendita, 'cucine' => $cucine, 'ordine' => $ordine, 'dataTable_rigaordine' => $dataTable, 'vista' => 'catalogo']);
                } else {
                    return $dataTable->render('punto_vendita.cassa.index', ['punto_vendita' => $puntoVendita, 'cucine' => $cucine, 'ordine' => $ordine, 'dataTable_rigaordine' => $dataTable]);
                }
                // return $dataTable->render('punto_vendita.cassa.vista2', ['punto_vendita' => $puntoVendita , 'cucine' => $cucine, 'ordine' => $ordine, 'dataTable_rigaordine' => $dataTable]);
            case Dispositivo::KIOSK:
                return $dataTable->render('punto_vendita.kiosk.index', ['punto_vendita' => $puntoVendita, 'cucine' => $cucine, 'ordine' => $ordine, 'dataTable_rigaordine' => $dataTable]);
            case Dispositivo::CAMERIERE:
                return $dataTable->render('punto_vendita.cam.index', ['punto_vendita' => $puntoVendita, 'cucine' => $cucine, 'ordine' => $ordine, 'dataTable_rigaordine' => $dataTable]);
        }
    }

    public function dissocia_dispositivo(Request $request)
    {
        $puntoVendita = Dispositivo::find($request->punto_vendita_id);

        if (! $puntoVendita) {
            return response()->json(['success' => false, 'message' => 'Punto di vendita non trovato']);
        }

        Cookie::queue(Cookie::forget('binding_token'));

        $puntoVendita->binding_token = null;
        $puntoVendita->occupato = false;
        $puntoVendita->save();

        return response()->json(['success' => true, 'message' => 'Disassociazione completata']);
    }

    public function riepilogo(Request $request)
    {
        $ordine = Ordine::find($request->ordine_id);
        if (! $ordine) {
            return redirect()->route('punto-vendita.kiosk.index')
                ->with('error', 'Ordine non trovato');
        }

        return view('punto_vendita.kiosk.riepilogo', ['ordine' => $ordine]);
    }

    public function dettagli(Request $request)
    {
        $puntoVendita = Dispositivo::find($request->punto_vendita_id);
        if (! $puntoVendita) {
            return redirect()->route('punto-vendita.index')
                ->with('error', 'Punto di vendita non trovato');
        }

        return view('punto_vendita.dettagli', ['puntoVendita' => $puntoVendita]);
    }

    public function riepilogo_cassa(Request $request)
    {
        $puntoVendita = Dispositivo::find($request->punto_vendita_id);
        if (! $puntoVendita) {
            return redirect()->route('punto-vendita.index')
                ->with('error', 'Punto di vendita non trovato');
        }
        // Calcola la data di oggi
        $oggi = now()->startOfDay();

        // Recupera tutti gli ordini di oggi per il punto vendita
        $ordiniOggi = \App\Models\Ordine::where('dispositivo_id', $puntoVendita->id)
            ->whereDate('created_at', $oggi)
            ->get();

        // Conta il totale ordini di oggi
        $totaleOrdiniOggi = $ordiniOggi->count();

        $ordineIds = $ordiniOggi->pluck('id')->all();

        if ($ordineIds === []) {
            $totaleIncassi = 0;
            $pagamentiPerMetodo = [];
            $pagamentiConteggioPerMetodo = [];
        } else {
            // Somma importi pagamenti legati agli ordini di oggi di questo punto vendita
            $totaleIncassi = (float) Pagamento::query()
                ->whereIn('ordine_id', $ordineIds)
                ->sum('importo');

            // Raggruppa per metodo_pagamento_id (colonna reale su tabella pagamento)
            $pagamentiPerMetodo = Pagamento::query()
                ->whereIn('ordine_id', $ordineIds)
                ->selectRaw('metodo_pagamento_id, SUM(importo) as totale_importo')
                ->groupBy('metodo_pagamento_id')
                ->pluck('totale_importo', 'metodo_pagamento_id')
                ->map(fn ($v) => (float) $v)
                ->all();

            $pagamentiConteggioPerMetodo = Pagamento::query()
                ->whereIn('ordine_id', $ordineIds)
                ->selectRaw('metodo_pagamento_id, COUNT(*) as conteggio')
                ->groupBy('metodo_pagamento_id')
                ->pluck('conteggio', 'metodo_pagamento_id')
                ->map(fn ($v) => (int) $v)
                ->all();
        }

        return view('punto_vendita.cassa.riepilogo_cassa', [
            'puntoVendita' => $puntoVendita,
            'totaleOrdiniOggi' => $totaleOrdiniOggi,
            'totaleIncassi' => $totaleIncassi,
            'pagamentiPerMetodo' => $pagamentiPerMetodo,
            'pagamentiConteggioPerMetodo' => $pagamentiConteggioPerMetodo,
        ]);
    }

    public function cerca_pre_ordine(Request $request)
    {
        $codice = $request->get('codice');
        // $pre_ordine = \App\Models\SaltacodaOrdine::where('codice' , $codice)->first();
        $pre_ordine = \App\Models\SaltacodaOrdine::where('codice', 'like', '%PRE_'.strtoupper($codice).'%')->first();

        // Se non trovato, prova con "PRE_" come prefisso se non già presente
        if (! $pre_ordine && stripos($codice, 'PRE_') !== 0) {
            $pre_ordine = \App\Models\SaltacodaOrdine::where('codice', 'like', '%PRE_'.strtoupper($codice).'%')->first();
        }

        if (! $pre_ordine) {
            return response()->json(['success' => false, 'message' => 'Pre-ordine non trovato']);
        }

        if (! (Session::has('attivita_attuale') && Session::get('attivita_attuale') != null && (int) Session::get('attivita_attuale') == (int) $pre_ordine->attivita_id)) {
            return response()->json(['success' => false, 'message' => 'Pre-ordine non trovato']);
        }

        return view('punto_vendita.cassa._partials.pre_ordine', ['pre_ordine' => $pre_ordine]);

    }

    public function importa_pre_ordine(Request $request)
    {

        // dd($request->all());
        $codice = $request->get('codice');
        $pre_ordine = \App\Models\SaltacodaOrdine::where('codice', $codice)->first();
        if (! $pre_ordine) {
            return response()->json(['success' => false, 'message' => 'Pre-ordine non trovato']);
        }

        if (! (Session::has('attivita_attuale') && Session::get('attivita_attuale') != null && (int) Session::get('attivita_attuale') == (int) $pre_ordine->attivita_id)) {
            return response()->json(['success' => false, 'message' => 'Attività non trovata']);
        }

        // $ordine = Ordine::where('id', $request->ordine_id)
        // ->where('stato', Ordine::CARRELLO)
        // ->where('dispositivo_id', $request->dispositivo_id)
        // ->where('attivita_id', $request->attivita_id)
        // ->first();

        $ordine = Ordine::find($request->ordine_id);

        if (! $ordine) {
            return response()->json(['success' => false, 'message' => 'Ordine non trovato']);
        }

        if ($ordine->stato != Ordine::CARRELLO) {
            return response()->json(['success' => false, 'message' => 'Ordine non è in carrello']);
        }

        // compila ordine con i dati del pre-ordine
        $ordine->info = $pre_ordine->info;
        $ordine->save();

        foreach ($pre_ordine->riga_ordine as $riga_ordine) {
            \App\Models\RigaOrdine::create([
                'ordine_id' => $ordine->id,
                'piatto_id' => $riga_ordine->piatto_id,
                'quantita' => $riga_ordine->quantita,
                'prezzo' => $riga_ordine->prezzo,
                'note' => $riga_ordine->note,
            ]);
        }

        // elimina pre-ordine
        $pre_ordine->stato = \App\Models\SaltacodaOrdine::IMPORTATO;
        $pre_ordine->save();

        return response()->json(['success' => true, 'message' => 'Pre-ordine importato', 'data' => $pre_ordine]);
    }
}
