<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\Profile;
use App\Models\Payment;
use App\Models\Takings;
use App\Models\Turn;
use App\Models\PrepaidCard;
use App\Models\PrepaidSummary;
use App\Models\Vehicle;
use App\Jobs\SendChargePrepaidSmsJob;
use Illuminate\Support\Facades\Cache;
use App\Jobs\CI4;


class TakingsController extends Controller
{
    public function makeTakings(Request $request)
    {
        $operator        = Profile::first();
        $payments        = $request->payments;
        $takings         = $request->takings;
        $turnId          = $request->turnId;
        $workstationName = $request->workstationName;

        $pays = array();
        $cardCode = null;
        $cardBalance = null;

        // \Log::debug($request->all());

        // Prepaid card validation Validations
        $paymentMethod = $request->payments[0]['id'] ?? null;
        if ($paymentMethod == 6) {
            // Validate if a prepaid card has been charged at least 5 seconds ago
            $vti            = $takings['vehicleTypeId'] ?? null; // Vehicle Type Id
            $ti             = $request->turnId;     // Turn Id
            $twentySecondsAgo = new \DateTime();
            $twentySecondsAgo->modify('-20 seconds');

            $validation = Takings::where('vehicle_type_id', $vti)
                                ->where('turn_id', $ti)
                                ->where('created_at', '>', $twentySecondsAgo)
                                ->first();

            if ($validation) {
                return response()->json([
                    "status" => 0,
                    "message" => "Operacion duplicada"
                ]);
            }

            // Validate if the plate and prepaid card has bee charged at least 10 minutes ago
            $card = PrepaidCard::find($takings["prepaidCardId"]);
            if (!$card) {
                return response()->json([
                    "status" => 0,
                    "message" => "Carnet No Encontrado"
                ]);
            }
            $exonerated = $card->exonerated;
            $veh = $card->vehicles()->find($takings["vehicleId"]);
            if (!$veh) {
                return response()->json([
                    "status" => 0,
                    "message" => "Vehiculo no asociado a el carnet o no registrado"
                ]);
            }

            $tenMinutesAgo = new \DateTime();
            $tenMinutesAgo->modify('-10 minutes');

            $newValidation = Takings::where('vehicle_id', $veh->id)
                                ->where('turn_id', $ti)
                                ->where('created_at', '>', $tenMinutesAgo)
                                ->first();

            if ($newValidation) {
                $p = $veh->plate;
                return response()->json([
                    "status" => 0,
                    "message" => "Vehiculo " . $p ." ya facturado hace al menos 10 minutos"
                ]);
            }
        } else {
            $takings["prepaidCardId"] = null;
            $takings["plate"] = null;
            $takings["vehicleId"] = null;
            $exonerated = $request->exonerated;
        }


        try{
            // Begin of the transaction
            DB::beginTransaction();
            // Generate ticket code
            $code = $this->generateTicketCode($operator->id);

            // Create a new Random unique Code
            $ticket = Takings::create([
                'code' => $code,
                'turn_id' => $turnId,
                'vehicle_id' => $takings['vehicleId'],
                'vehicle_type_id' => $takings['vehicleTypeId'],
                'amount' => $exonerated ? 0 : $takings['value']
            ]);
            // Recover the vehicle type
            $ticket->vehicleType;

            // Register all payments associated in the takings
            foreach ($payments as $payment) {
                // Register the payment in the database
                $pay = Payment::create([
                    'last_digits' => array_key_exists('lastDigits', $payment) ? $payment['lastDigits'] : null,
                    'payment_method_id' => $payment['id'],
                    'amount' =>  $exonerated  ? 0 : $payment['amount'],
                ]);

                // Verify if the payment is an prepaid card
                if($payment['id'] == 6){
                    // debit the ammount in the prepaid card
                    $card = PrepaidCard::find($takings['prepaidCardId']);
                    $card->balance -= floatval($payment['amount']);
                    $card->save();
                    $cardCode     = $card->code;
                    $cardBalance  = $card->balance;

                    // the register the summary
                    $summary = PrepaidSummary::create([
                        "prepaid_card_id" => $takings['prepaidCardId'],
                        "code" => $code,
                        "type" => "out",
                        "concept" => "Debito en Caseta " . $workstationName,
                        "amount" =>  $exonerated ? 0 : $payment['amount'],
                        "new_balance" => $card->balance
                    ]);

                    SendChargePrepaidSmsJob::dispatch($card->profile, $summary);

                    // then attach the payment to the summary
                    $summary->payments()->attach($pay);
                }

                // And put in array
                $ticket->payments()->attach($pay);
                array_push($pays, $pay);
            }

            $ticket->cardCode    = $cardCode;
            $ticket->cardBalance = $cardBalance;


            // Now Asociate the ticket to all the payments
            foreach ($pays as $pay) {
                if (count($pays) > 1) {
                    $ticket->paymentType = "Mixto";
                } else if (count($pays) == 1) {
                    $ticket->paymentType = $pay->paymentMethod->name;
                }

            }

            // Write in the database
            DB::commit();
            // Recover the prepaid card asociated to the tag
            $info = new \stdClass();
            $lastTurn = Turn::with('profile')->where('id', $turnId)->orderBy('begin_at', 'desc')->first();
            if(isset($takings["prepaidCardId"])){
                $card = PrepaidCard::with('profile')->find($takings["prepaidCardId"]);
                $info->id = $card->profile->id;
                $info->id_card = $card->profile->id_card;
                $info->user = $card->profile->names. " ".$card->profile->surnames;
                $info->prepaidCardCode = $card->code;
                $info->balance = $card->balance;
            }else{
                $info->id = null;
                $info->id_card = 0;
                $info->user = "General";
            }
             CI4::dispatch(["amount"=>$exonerated ? 0 : $takings['value'],
                            "methodPay"=>$ticket->paymentType,
                            "idClient"=>$info->id_card,
                            "client"=>$info->user,
                            "vin"=>"",
                            "vehicle"=>"",
                            "namePeaje"=>'Cardenalito',
                            "turn"=>$lastTurn->number,
                            "nameCollector"=>$lastTurn->profile->names,
                            "date"=>date("Y-m-d h:i:s"),
                            "typeVehicle"=>$takings["name"],
                            "id_peaje"=>1]);
            // Return Response
            return response()->json([
                "status" => 1,
                "data" => $ticket,
                "message" => "Recaudacion registrada exitosamente"
            ]);
        } catch(\Exception $e) {
            // Make a Rollback
            DB::rollback();
                \Log::debug($e);
            // Return Response
            return response()->json([
                "status" => 00,
                "message" => "Ocurrio un error realizando la Recaudacion, intente en unos segundos por favor"
            ]);
        } catch(\Error $e) {
            // Make a Rollback
            DB::rollback();
                \Log::debug($e);
            // Return Response
            return response()->json([
                "status" => 0,
                "message" => "Ocurrio un error realizando la Recaudacion, intente en unos segundos por favor"
            ]);
        }
    }

    public function delete(Request $request)
    {
        $id = $request->id;
        try{
            $taking = Takings::find($id);
            $taking->delete();
            return response()->json([
                "status" => 1,
                "message" => "Ticket de Recaudacion ". $taking->number . " eliminado exitosamente"
            ]);

        } catch (\Exception $e) {
            return response()->json([
                "status" => 0,
                "message" => "Ocurrio un error, intente mas tarde, si el problema persiste comuniquese con su administrador"
            ]);
        }
    }

    private function generateTicketCode($operatorId): string
    {
        $id = sprintf('%03d', $operatorId);
        $code = microtime();
        $code = explode(' ', $code);
        $code = $code[1] . $id . $code[0];
        $code = str_replace(['0.', ''], '', $code);
        $code = substr($code, 0, -2);
        return $code;
    }
}
