<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use App\Http\Controllers\Controller;
use App\DTOs\PurchaseOrder\PurchaseOrderCreateDto;
use App\DTOs\PurchaseOrder\PurchaseOrderUpdateDto;
use App\Repositories\Interfaces\IPurchaseOrderRepository;
use Exception;
use App\Models\PurchaseOrderHeader;
use App\Models\PurchaseOrderItems;
use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;

class PurchaseOrderController extends Controller
{

    private $purchaseOrderRepository;
    private $errorConnection = "";

    public function __construct(Request $request, IPurchaseOrderRepository $purchaseOrderRepository)
    {
        if (isset($request['business_information'])) {
            $business_information = $request['business_information'];
            $ruc = $business_information['ruc_number'];

            $existe_conexion = $this->setDBClient($ruc);

            if ($existe_conexion['error']) {
                $this->errorConnection = $existe_conexion['message'];
                return $this->messageError("Se espera un número de RUC válido.", 201);
            } else {
                $this->purchaseOrderRepository = $purchaseOrderRepository;
            }
        } else {
            $this->errorConnection = 'Error en la conexión. Se espera número de RUC';
        }
    }

    public function index(Request $request)
    {
        if ($this->errorConnection != '') {
            return $this->messageError($this->errorConnection, 201);
        }

        $result = $this->purchaseOrderRepository->paginate($request->all());

        if ($result) {
            return $this->successResponse($result, "Ordenes de compra encontradas correctamente", 201);
        } else {
            return $this->errorResponse("No hay Ordenes de compra", 201);
        }
    }

    public function show(int $id, Request $request)
    {
        $business_information = $request['business_information'];
        $business_ruc = $business_information['ruc_number'];
        if ($this->errorConnection != '') {
            return $this->messageError($this->errorConnection, 500);
        }

        $result = $this->purchaseOrderRepository->find($id, $business_ruc);

        if ($result) {
            return $this->successResponse($result, "Orden de compra encontrada correctamente", 200);
        } else {
            return $this->errorResponse("Orden de compra no encontrada", 200);
        }
    }

    public function store(Request $request)
    {
        try {
            if ($this->errorConnection != '') {
                return $this->messageError($this->errorConnection, 500);
            }

            $business_information = $request['business_information'];
            $business_ruc = $business_information['ruc_number'];


            //Validacion para el campo issuance_date en caso de que la data sea (d-m-Y) o (Y-m-d)
            $fecha_original = $request["issuance_date"];
            $fecha_convertida = date_create_from_format('d-m-Y', $fecha_original) ?: date_create_from_format('Y-m-d', $fecha_original);
            if (!$fecha_convertida) {
                return $this->errorResponse('La fecha proporcionada no es válida KENYY.', 422);
            }
            $request['issuance_date'] = $fecha_convertida->format('Y-m-d'); //tkmansilla

            foreach ((array)$request['items'] as $index => $item) {

                $index++;

                $fields = [
                    'igv', 'quantity', 'unit_price', 'affect_price', 'non_affected_price',
                    'exonerated_price', 'price_affected_item', 'price_no_affected_item', 'price_exonerated_item',
                    'item_discount', 'subtotal', 'tax_gratuito', 'tax', 'item_tax', 'quantity_ICBPER', 'tax_ICBPER', 'prr_discount', 'type_of_affectation', 'tax_method'
                ];

                foreach ($fields as $field) {
                    if (!isset($item[$field]) || $item[$field] === null) {
                        return $this->errorResponse("El ítem $index no tiene el campo '$field' definido en el JSON o su valor es nulo.", 422);
                    } elseif (!is_numeric($item[$field])) {
                        return $this->errorResponse("El ítem $index tiene un valor no numérico para el campo '$field' en el JSON.", 422);
                    } elseif (!is_numeric($request['mult_ICBPER'])) {
                        return $this->errorResponse("El campo mult_ICBPER de la cabecera posee un valor no numerico. ", 422);
                    }
                }
            }

            $this->validate(
                $request,
                [

                    'issuance_date' => 'required|date',
                    'num_purchase_order' => 'required|regex:/^[a-zA-Z0-9\-]+$/|max:12',
                    'supplier_id' => 'required|integer',
                    'supplier_name' => 'required|string|max:55',
                    'supplier_ruc' => 'required|integer',
                    'currency' => 'required|string|in:PEN,USD',
                    'exchange' => 'nullable|numeric',
                    'affected' => 'numeric',
                    'non_affected' => 'numeric',
                    'exonerated' => 'numeric',
                    'total' => 'required|numeric',
                    'product_discount' => 'required|numeric',
                    'order_discount_percentage' => 'required|integer',
                    'order_discount_percentage_value' => 'required|numeric',
                    'order_discount_no_percentage_value'  => 'required|numeric',
                    'total_discount' => 'required|numeric',
                    'product_tax' => 'required|nullable|numeric',
                    'order_tax_id' => 'nullable|string|max:20',
                    'order_tax' => 'nullable|numeric',
                    'total_tax' => 'required|numeric',
                    'tax_ICBPER' => 'required|numeric',
                    'mult_ICBPER' => 'required|numeric',
                    'subtotal' => 'required|numeric',
                    'grand_total' => 'required|numeric',
                    'total_items' => 'required|integer',
                    'total_quantity' => 'required|integer',
                    'note' => 'nullable|string|max:1000',
                    'rounding' => 'nullable|numeric',
                    'attachment' => 'nullable|string|max:255',
                    'expiration_date' => 'nullable|date',
                    'canal_id' => 'nullable|integer',
                    'payment_method_id' => 'nullable|integer',
                    'num_quotation' => 'integer',
                    'destination_address' => 'string|max:255',
                    'destination_ubigeo' => 'string|max:11',
                    'supplier_address' => 'string|max:100',
                    'supplier_contact_name' => 'string|max:50',
                    'supplier_contact_phone' => 'string|max:20',
                    'supplier_contact_email' => 'email|max:80',
                    'estado' => 'required|integer',

                    //Detalle
                    'items.*.product_id' => 'integer|nullable', //Este campo debe validarse que exista?
                    'items.*.code' => 'string|nullable|max:50',
                    'items.*.name' => 'string|nullable|max:255',
                    'items.*.quantity' => 'required|integer',
                    'items.*.unit_price' => 'required|numeric',


                    'items.*.affect_price' => [
                        'nullable',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $igv = $request['items'][$index[0]]['igv'];
                            $unit_price = $request['items'][$index[0]]['unit_price'];

                            if ($value != 0) {
                                $expectedAffectPrice = round($unit_price / (1 + ($igv / 100)), 4); // Base = Total / (1 + 0.18) 

                                if ($value != $expectedAffectPrice) {
                                    $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedAffectPrice);
                                }
                            }
                        },
                    ],

                    'items.*.non_affected_price' => [ // Si el campo IGV esta vacio o es 0 el valor es el del campo unit_price.
                        'nullable',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            // Extraer el índice del arreglo de ítems
                            $index = explode('.', str_replace('items.', '', $attribute));

                            // Obtener el valor del campo 'igv' del ítem correspondiente
                            $igv = $request['items'][$index[0]]['igv'];

                            if ($igv != 0) {
                                return;
                            }

                            if ($value != 0) {
                                // Calcular el valor esperado para 'non_affected_price' si 'igv' está vacío o es 0
                                $expectedNonAffectedPrice = empty($igv) || $igv == 0 ? $request['items'][$index[0]]['unit_price'] : null;

                                // Comparar el valor proporcionado con el valor esperado
                                if ($value !== $expectedNonAffectedPrice) {
                                    $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo deberia ser: " . $expectedNonAffectedPrice);
                                }
                            }
                        },
                    ],

                    'items.*.exonerated_price' => [ // Si el campo IGV esta vacio o es 0 el valor es el del campo unit_price.
                        'nullable',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            // Extraer el índice del arreglo de ítems
                            $index = explode('.', str_replace('items.', '', $attribute));

                            // Obtener el valor del campo 'igv' del ítem correspondiente
                            $igv = $request['items'][$index[0]]['igv'];


                            if ($igv != 0) {
                                return;
                            }

                            if ($value != 0) {
                                // Calcular el valor esperado para 'non_affected_price' si 'igv' está vacío o es 0
                                $expectedExoneratedPrice = empty($igv) || $igv == 0 ? $request['items'][$index[0]]['unit_price'] : null;

                                // Comparar el valor proporcionado con el valor esperado
                                if ($value !== $expectedExoneratedPrice) {
                                    $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo deberia ser: " . $expectedExoneratedPrice);
                                }
                            }
                        },
                    ],

                    'items.*.gratuito_price' => [
                        'nullable',
                        'numeric',
                        // function ($attribute, $value, $fail) use ($request) {
                        //     $index = explode('.', str_replace('items.', '', $attribute));
                        //     $unit_price = $request['items'][$index[0]]['unit_price'];


                        //     if ($value != $unit_price) {
                        //         $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $unit_price);
                        //     }
                        // },
                    ],

                    'items.*.price_affected_item' => [ // items.affect_price * quantity
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));
                            $affectPrice = $request['items'][$index[0]]['affect_price'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedPriceAffectedItem = round($affectPrice * $quantity, 4);

                            if ($value != $expectedPriceAffectedItem) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedPriceAffectedItem);
                            }
                        },
                    ],

                    'items.*.price_no_affected_item' => [ // non_affected_price * quantity
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));
                            $nonAffectedPrice = $request['items'][$index[0]]['non_affected_price'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedPriceNoAffectedItem = round($nonAffectedPrice * $quantity, 4);

                            if ($value != $expectedPriceNoAffectedItem) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedPriceNoAffectedItem);
                            }
                        },
                    ],
                    'items.*.price_exonerated_item' => [ // exonerated_price * quantity
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));
                            $exoneratedPrice = $request['items'][$index[0]]['exonerated_price'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedPriceExoneratedItem = round($exoneratedPrice * $quantity, 4);

                            if ($value != $expectedPriceExoneratedItem) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedPriceExoneratedItem);
                            }
                        },
                    ],

                    'items.*.tax_gratuito' => [
                        'numeric',
                        'nullable',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            // Verificar si el ítem existe en la solicitud
                            if (isset($request['items'][$index[0]])) {
                                $exoneratedPrice = $request['items'][$index[0]]['exonerated_price'];
                                $nonAffectedPrice = $request['items'][$index[0]]['non_affected_price'];
                                $affectPrice = $request['items'][$index[0]]['affect_price'];

                                // Si alguno de los campos 'exonerated_price', 'non_affected_price', o 'affect_price' es diferente de 0 no validar.
                                if ($exoneratedPrice != 0 || $nonAffectedPrice != 0 || $affectPrice != 0) {
                                    return;
                                }

                                $igv = $request['items'][$index[0]]['igv'];
                                $unitPrice = $request['items'][$index[0]]['unit_price'];

                                // Calcular el valor esperado para 'tax_gratuito' en función de 'unit_price' e 'igv'
                                $expectedTaxGratuito = round($unitPrice * ($igv / 100), 4);

                                // Comparar el valor proporcionado con el valor esperado, permitiendo una pequeña diferencia (0.01)
                                if (abs($value - $expectedTaxGratuito) > 0.01) {
                                    $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedTaxGratuito);
                                }
                            }
                        },
                    ],

                    'items.*.discount' => 'string|nullable|max:20',
                    'items.*.item_discount' => 'integer|nullable', //Porcentaje de descuento, valor entero.

                    'items.*.prr_discount' => [
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $discount = $request['items'][$index[0]]['item_discount'];
                            $subtotal = $request['items'][$index[0]]['subtotal'];

                            $expectedDiscountValueItem = round($subtotal * ($discount / 100), 4);

                            if (abs($value - $expectedDiscountValueItem) > 0.01) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedDiscountValueItem);
                            }
                        },
                    ],

                    'items.*.tax' => [
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));


                            $unitPrice = $request['items'][$index[0]]['unit_price'];
                            $TaxAffectPrice = $request['items'][$index[0]]['affect_price'];
                            // $TaxGratuito = $request['items'][$index[0]]['gratuito_price'];

                            $expectedTax = 0;

                            if ($TaxAffectPrice != 0) {
                                $expectedTax = round($unitPrice - $TaxAffectPrice, 4);
                            }
                            // if ($TaxGratuito != 0) {
                            //     $expectedTax = round($unitPrice - $TaxGratuito, 4);
                            // }

                            // Comparar el valor proporcionado con el valor esperado, permitiendo una pequeña diferencia (0.01)
                            if (abs($value - $expectedTax) > 0.01) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedTax);
                            }
                        },
                    ],

                    'items.*.item_tax' => [ // tax * quantity
                        'numeric',
                        'nullable',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $tax = $request['items'][$index[0]]['tax'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedItemTax = round($tax * $quantity, 4);

                            if ($value != $expectedItemTax) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo deberia ser: " . $expectedItemTax);
                            }
                        },
                    ],

                    'items.*.item_tax_gratuito' => [ // tax_gratuito * quantity
                        'numeric',
                        'nullable',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $tax = $request['items'][$index[0]]['tax_gratuito'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedItemTaxGratuitous = round($tax * $quantity, 4);

                            if ($value != $expectedItemTaxGratuitous) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo deberia ser: " . $expectedItemTaxGratuitous);
                            }
                        },
                    ],

                    'items.*.igv' => 'required|integer|max:20', //Valor en porcentaje. Ejemplo: 18

                    'items.*.tax_ICBPER' => [ // Impuesto a las bolsas plasticas, 50 centimos (Impuesto o costo de la bolsa )
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));
                            $ICBPERquantity = $request['items'][$index[0]]['quantity_ICBPER'];
                            $ICBPERvalue = $request['mult_ICBPER'];


                            $taxICBPER = $ICBPERvalue * $ICBPERquantity;

                            if (round($value, 2) != round($taxICBPER, 2)) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $taxICBPER);
                            }
                        }
                    ],


                    'items.*.quantity_ICBPER' => 'required|integer', //Cantidad de bolsas plasticas que llevas x item

                    'items.*.subtotal' => [ // Suma de los 3 campos, price_affected_item, price_no_affected_item, price_exonerated_item, (tax_ICBPER * quantity_ICBPER) y item_tax o item_tax_gratuito en el caso de un item gratuito
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $affectItem = $request['items'][$index[0]]['price_affected_item'];
                            $noAffectItem = $request['items'][$index[0]]['price_no_affected_item'];
                            $exoneratedItem = $request['items'][$index[0]]['price_exonerated_item'];
                            $itemTax = $request['items'][$index[0]]['item_tax'];
                            $itemTax_ICBPER = $request['items'][$index[0]]['tax_ICBPER'];
                            $prrDiscount = $request['items'][$index[0]]['prr_discount'];

                            $subtotal = round(($affectItem + $noAffectItem + $exoneratedItem + $itemTax + $itemTax_ICBPER) - $prrDiscount, 4);

                            if (abs($value - $subtotal) > 0.01) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $subtotal);
                            }
                        }
                    ],

                    'items.*.real_unit_price' => 'numeric|nullable', // -
                    'items.*.cost' => 'numeric|nullable', // -
                    'items.*.tax_method' => 'required|integer', // - 
                    'items.*.type_of_affectation' => 'required|integer', // - 
                ],
                [   //Mensajes para las validaciones:
                    'issuance_date.required' => 'El campo de fecha es obligatorio.',
                    'issuance_date.date' => 'El formato del campo de fecha no es válido.',
                    'num_purchase_order.required' => 'El campo num_purchase_order es obligatorio.',
                    'num_purchase_order.regex' => 'El campo num_purchase_order debe contener solo letras, números y guiones.',
                    'num_purchase_order.max' => 'El campo num_purchase_order no puede tener más de :max caracteres.',
                    'supplier_id.required' => 'El campo supplier_id es obligatorio.',
                    'supplier_id.integer' => 'El campo supplier_id debe ser un número entero.',
                    'supplier_name.required' => 'El campo supplier_name es obligatorio.',
                    'supplier_name.string' => 'El campo supplier_name debe ser una cadena de texto.',
                    'supplier_name.max' => 'El campo supplier_name no puede tener más de :max caracteres.',
                    'supplier_ruc.required' => 'El campo supplier_ruc es obligatorio.',
                    'supplier_ruc.integer' => 'El campo supplier_ruc debe ser un numero entero.',
                    'supplier_ruc.max' => 'El campo supplier_ruc no puede tener más de :max caracteres.',
                    'currency.required' => 'El campo currency es obligatorio.',
                    'currency.string' => 'El campo currency debe ser una cadena de texto.',
                    'currency.in' => 'El campo currency debe ser PEN o USD.',
                    'exchange.numeric' => 'El campo exchange debe ser un número.',
                    'affected.numeric' => 'El campo affected debe ser un número.',
                    'non_affected.numeric' => 'El campo non_affected debe ser un número.',
                    'exonerated.numeric' => 'El campo exonerated debe ser un número.',
                    'total.required' => 'El campo total es obligatorio.',
                    'total.numeric' => 'El campo total debe ser un número.',
                    'product_discount.required' => 'El campo product_discount es obligatorio.',
                    'product_discount.numeric' => 'El campo product_discount debe ser un número.',
                    'order_discount_percentage.required' => 'El campo order_discount_percentage es obligatorio.',
                    'order_discount_percentage.integer' => 'El campo order_discount_percentage debe ser un número entero.',
                    'order_discount_percentage_value.required' => 'El campo order_discount_percentage_value es obligatorio.',
                    'order_discount_percentage_value.numeric' => 'El campo order_discount_percentage_value debe ser un número.',
                    'order_discount_no_percentage_value.required' => 'El campo order_discount_no_percentage_value es obligatorio.',
                    'order_discount_no_percentage_value.numeric' => 'El campo order_discount_no_percentage_value debe ser un número.',
                    'total_discount.required' => 'El campo total_discount es obligatorio.',
                    'total_discount.numeric' => 'El campo total_discount debe ser un número.',
                    'product_tax.required' => 'El campo product_tax es obligatorio.',
                    'product_tax.numeric' => 'El campo product_tax debe ser un número.',
                    'order_tax_id.required' => 'El campo order_tax_id es obligatorio.',
                    'order_tax_id.string' => 'El campo order_tax_id debe ser una cadena de texto.',
                    'order_tax_id.max' => 'El campo order_tax_id no puede tener más de :max caracteres.',
                    'order_tax.numeric' => 'El campo order_tax debe ser un número.',
                    'total_tax.required' => 'El campo total_tax es obligatorio.',
                    'total_tax.numeric' => 'El campo total_tax debe ser un número.',
                    'tax_ICBPER.required' => 'El campo tax_ICBPER es obligatorio.',
                    'tax_ICBPER.numeric' => 'El campo tax_ICBPER debe ser un número.',
                    'mult_ICBPER.required' => 'El campo mult_ICBPER es obligatorio.',
                    'mult_ICBPER.numeric' => 'El campo mult_ICBPER debe ser un número.',
                    'subtotal.required' => 'El campo subtotal es obligatorio.',
                    'subtotal.numeric' => 'El campo subtotal debe ser un número.',
                    'grand_total.required' => 'El campo grand_total es obligatorio.',
                    'grand_total.numeric' => 'El campo grand_total debe ser un número.',
                    'total_items.required' => 'El campo total_items es obligatorio.',
                    'total_items.integer' => 'El campo total_items debe ser un número entero.',
                    'total_quantity.required' => 'El campo total_quantity es obligatorio.',
                    'total_quantity.integer' => 'El campo total_quantity debe ser un número entero.',
                    'note.string' => 'El campo note debe ser una cadena de texto.',
                    'note.max' => 'El campo note no puede tener más de :max caracteres.',
                    'rounding.numeric' => 'El campo rounding debe ser un número.',
                    'attachment.string' => 'El campo attachment debe ser una cadena de texto.',
                    'attachment.max' => 'El campo attachment no puede tener más de :max caracteres.',
                    'expiration_date.date' => 'El campo expiration_date no es válido.',
                    'canal_id.integer' => 'El campo canal_id debe ser un número entero.',
                    'payment_method_id.integer' => 'El campo payment_method_id debe ser un número entero.',
                    'num_quotation.integer' => 'El campo num_quotation debe ser un número entero.',
                    'destination_address.string' => 'El campo destination_address debe ser una cadena de texto.',
                    'destination_address.max' => 'El campo destination_address no puede tener más de :max caracteres.',
                    'destination_ubigeo.string' => 'El campo destination_ubigeo debe ser una cadena de texto.',
                    'destination_ubigeo.max' => 'El campo destination_ubigeo no puede tener más de :max caracteres.',
                    'supplier_contact_name.string' => 'El campo supplier_contact_name debe ser una cadena de texto.',
                    'supplier_contact_name.max' => 'El campo supplier_contact_name no puede tener más de :max caracteres.',
                    'supplier_address.string' => 'El campo supplier_address debe ser una cadena de texto.',
                    'supplier_address.max' => 'El campo supplier_address no puede tener más de :max caracteres.',
                    'supplier_contact_phone.string' => 'El campo supplier_contact_phone debe ser una cadena de texto.',
                    'supplier_contact_phone.max' => 'El campo supplier_contact_phone no puede tener más de :max caracteres.',
                    'supplier_contact_email.email' => 'El campo supplier_contact_email no es válido.',
                    'supplier_contact_email.max' => 'El campo supplier_contact_email no puede tener más de :max caracteres.',
                    'estado.required' => 'El campo estado es obligatorio.',
                    'estado.integer' => 'El campo estado debe ser un número entero.',

                    //Mensajes de validacion para items:
                    'items.*.purchase_order_header_id.required' => 'El campo ID de compra es obligatorio para todos los elementos.',
                    'items.*.product_id.integer' => 'El campo ID de producto debe ser un número entero para todos los elementos.',
                    'items.*.code.string' => 'El campo Código debe ser una cadena de texto para todos los elementos.',
                    'items.*.code.max' => 'El campo Código no debe superar los 50 caracteres para todos los elementos.',
                    'items.*.name.string' => 'El campo Nombre debe ser una cadena de texto para todos los elementos.',
                    'items.*.name.max' => 'El campo Nombre no debe superar los 255 caracteres para todos los elementos.',
                    'items.*.quantity.required' => 'El campo Cantidad es obligatorio para todos los elementos.',
                    'items.*.quantity.integer' => 'El campo Cantidad debe ser un valor entero para todos los elementos.',
                    'items.*.unit_price.required' => 'El campo Precio unitario es obligatorio para todos los elementos.',
                    'items.*.unit_price.numeric' => 'El campo Precio unitario debe ser un valor numérico para todos los elementos.',
                    'items.*.affect_price.required' => 'El campo Precio afectado es obligatorio para todos los elementos.',
                    'items.*.affect_price.numeric' => 'El campo Precio afectado debe ser un valor numérico para todos los elementos.',
                    'items.*.non_affected_price.required' => 'El campo Precio no afectado es obligatorio para todos los elementos.',
                    'items.*.non_affected_price.numeric' => 'El campo Precio no afectado debe ser un valor numérico para todos los elementos.',
                    'items.*.exonerated_price.required' => 'El campo Precio exonerado es obligatorio para todos los elementos.',
                    'items.*.exonerated_price.numeric' => 'El campo Precio exonerado debe ser un valor numérico para todos los elementos.',
                    'items.*.gratuito_price.numeric' => 'El campo Precio gratuito debe ser un valor numérico para todos los elementos.',
                    'items.*.price_affected_item.required' => 'El campo Precio afectado por ítem es obligatorio para todos los elementos.',
                    'items.*.price_affected_item.numeric' => 'El campo Precio afectado por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.price_no_affected_item.required' => 'El campo Precio no afectado por ítem es obligatorio para todos los elementos.',
                    'items.*.price_no_affected_item.numeric' => 'El campo Precio no afectado por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.price_exonerated_item.required' => 'El campo Precio exonerado por ítem es obligatorio para todos los elementos.',
                    'items.*.price_exonerated_item.numeric' => 'El campo Precio exonerado por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.price_gratuito_item.numeric' => 'El campo Precio gratuito por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.discount.string' => 'El campo Descuento debe ser una cadena de texto para todos los elementos.',
                    'items.*.discount.max' => 'El campo Descuento no debe superar los 20 caracteres para todos los elementos.',
                    'items.*.item_discount.integer' => 'El campo Descuento por ítem debe ser un valor entero para todos los elementos.',
                    'items.*.prr_discount.required' => 'El campo Descuento PRR es obligatorio para todos los elementos.',
                    'items.*.prr_discount.numeric' => 'El campo Descuento PRR debe ser un valor numérico para todos los elementos.',
                    'items.*.tax.required' => 'El campo Impuesto es obligatorio para todos los elementos.',
                    'items.*.tax.numeric' => 'El campo Impuesto debe ser un valor numérico para todos los elementos.',
                    'items.*.item_tax.numeric' => 'El campo Impuesto por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.tax_gratuito.numeric' => 'El campo Impuesto gratuito debe ser un valor numérico para todos los elementos.',
                    'items.*.item_tax_gratuito.numeric' => 'El campo Impuesto por ítem gratuito debe ser un valor numérico para todos los elementos.',
                    'items.*.igv.required' => 'El campo IGV es obligatorio para todos los elementos.',
                    'items.*.igv.max' => 'El campo IGV no debe superar los 20 caracteres para todos los elementos.',
                    'items.*.tax_ICBPER.required' => 'El campo Impuesto ICBPER es obligatorio para todos los elementos.',
                    'items.*.tax_ICBPER.numeric' => 'El campo Impuesto ICBPER debe ser un valor numérico para todos los elementos.',
                    'items.*.quantity_ICBPER.required' => 'El campo Cantidad ICBPER es obligatorio para todos los elementos.',
                    'items.*.quantity_ICBPER.integer' => 'El campo Cantidad ICBPER debe ser un número entero para todos los elementos.',
                    'items.*.subtotal.required' => 'El campo Subtotal es obligatorio para todos los elementos.',
                    'items.*.subtotal.numeric' => 'El campo Subtotal debe ser un valor numérico para todos los elementos.',
                    'items.*.real_unit_price.numeric' => 'El campo Precio unitario real debe ser un valor numérico para todos los elementos.',
                    'items.*.cost.numeric' => 'El campo Costo debe ser un valor numérico para todos los elementos.',
                    'items.*.tax_method.required' => 'El campo Método de impuesto es obligatorio para todos los elementos.',
                    'items.*.tax_method.integer' => 'El campo Método de impuesto debe ser un número entero para todos los elementos.',
                    'items.*.type_of_affectation.required' => 'El campo tipo de afectacion es obligatorio para todos los elementos.',
                    'items.*.type_of_affectation.integer' => 'El campo tipo de afectacion debe ser un número entero para todos los elementos.',
                    'items.*.status.numeric' => 'El campo Estado debe ser un valor numérico para todos los elementos.',
                ]
            );


            $store = new PurchaseOrderCreateDto();

            $store->ruc = $business_ruc;

            $store->issuance_date = $request["issuance_date"];
            $store->num_purchase_order = $request["num_purchase_order"];
            $store->supplier_id = $request["supplier_id"];
            $store->supplier_name = $request["supplier_name"];
            $store->supplier_ruc = $request["supplier_ruc"];
            $store->currency = $request["currency"]; //USD o PEN
            $store->exchange = $request["exchange"];
            $store->affected = $request["affected"];
            $store->non_affected = $request["non_affected"];
            $store->exonerated = $request["exonerated"];
            $store->total = $request["total"];
            $store->product_discount = $request["product_discount"];
            $store->order_discount_percentage = $request["order_discount_percentage"];
            $store->order_discount_percentage_value = $request["order_discount_percentage_value"];
            $store->order_discount_no_percentage_value = $request["order_discount_no_percentage_value"];
            $store->total_discount = $request["total_discount"];
            $store->product_tax = $request["product_tax"];
            $store->order_tax_id = $request["order_tax_id"];
            $store->order_tax = $request["order_tax"];
            $store->total_tax = $request["total_tax"];
            $store->tax_ICBPER = $request["tax_ICBPER"];
            $store->mult_ICBPER = $request["mult_ICBPER"];
            $store->subtotal = $request["subtotal"];
            $store->grand_total = $request["grand_total"];
            $store->total_items = $request["total_items"];
            $store->total_quantity = $request["total_quantity"];
            $store->note = $request["note"];
            $store->rounding = $request["rounding"];
            $store->attachment = $request["attachment"];
            $store->expiration_date = $request["expiration_date"];
            $store->canal_id = $request["canal_id"];
            $store->payment_method_id = $request["payment_method_id"];
            $store->num_quotation = $request["num_quotation"];
            $store->destination_address = $request["destination_address"];
            $store->destination_ubigeo = $request["destination_ubigeo"];
            $store->supplier_address = $request["supplier_address"];
            $store->supplier_contact_name = $request["supplier_contact_name"];
            $store->supplier_contact_phone = $request["supplier_contact_phone"];
            $store->supplier_contact_email = $request["supplier_contact_email"];
            $store->estado = $request["estado"];
            $store->created_by = $request['created_by'];
            $store->created_at = date('Y-m-d h:m:s');
            $store->status = 1;

            //ITEMS
            $items = (array)$request['items']; // Convirtiendo en array el objeto items

            //DETALLE// Asignando el valor 1 por defecto al campo STATUS de auditoria de los items al registrarlos.
            foreach ($items as &$item) {
                $item['status'] = $item['status'] ?? '1';
            }
            $store->items = $items;

            //CABECERA// Validando si el campo 'total_quantity' de la cabecera es correcto o no.
            $totalQuantity = array_sum(array_column($items, 'quantity'));

            if ($totalQuantity != $request['total_quantity']) {
                return $this->errorResponse('El valor proporcionado en el campo total_quantity de la cabecera no es correcto. El valor del campo deberia ser: ' . $totalQuantity, 422);
            }

            //CABECERA// Validando si el campo 'total_quantity' de la cabecera es correcto o no.
            $totalQuantityItems = count((array)$request['items']);

            if ($totalQuantityItems != $request['total_items']) {
                return $this->errorResponse('El valor proporcionado en el campo total_items de la cabecera no es correcto. El valor del campo deberia ser: ' . $totalQuantityItems, 422);
            }

            //VALIDACION EN CASO DE QUE SE HAYE UN DESCUENTO GLOBAL

            $totalDiscount = $request['total_discount'];


            if ($totalDiscount > 0) {

                $totalAfectado = array_sum(array_column($items, 'price_affected_item'));
                $totalTax = ($totalAfectado - $totalDiscount) * (18 / 100); //18 TIENE QUE SER REMPLAZADO POR EL VALOR DEL IGV TRAIDO DIRECTAMENTE DESDE SETTINGS

            } else {

                $totalTax = array_sum(array_column($items, 'item_tax'));

            }

            //CABECERA//Validando si el valor del campo 'total_tax' de la cabecera es correcto o no.

            if (round($totalTax, 4) != round($request['total_tax'], 4)) {
                return $this->errorResponse('El valor proporcionado en el campo total_tax de la cabecera no es correcto. El valor del campo debería ser: ' . $totalTax, 422);
            }




            //CABECERA// Validando si el valor de los campos 'price_affected', 'non_affected' y 'exonerated' de la cabecera son correctos o no.


            $totalAfectado = array_sum(array_column($items, 'price_affected_item'));

            $totalNoAfectado = array_sum(array_column($items, 'price_no_affected_item'));
            $totalExonerado = array_sum(array_column($items, 'price_exonerated_item'));

            if ($totalDiscount > 0) {

                $nuevoTotalAfectado = $totalAfectado - $totalDiscount;

                if (round($nuevoTotalAfectado, 4) != round($request['affected'], 4)) {
                    return $this->errorResponse('El valor proporcionado en el campo affected de la cabecera no es correcto. El valor del campo debería ser: ' . $nuevoTotalAfectado, 422);
                }
            } else {

                if (round($totalAfectado, 4) != round($request['affected'], 4)) {
                    return $this->errorResponse('El valor proporcionado en el campo affected de la cabecera no es correcto. El valor del campo debería ser: ' . $totalAfectado, 422);
                }
            }


            if (round($totalNoAfectado, 4) != round($request['non_affected'], 4)) {
                return $this->errorResponse('El valor proporcionado en el campo non_affected de la cabecera no es correcto. El valor del campo debería ser: ' . $totalNoAfectado, 422);
            }

            if (round($totalExonerado, 4) != round($request['exonerated'], 4)) {
                return $this->errorResponse('El valor proporcionado en el campo exonerated de la cabecera no es correcto. El valor del campo debería ser: ' . $totalExonerado, 422);
            }



            //CABECERA//Validando si el valor del campo 'tax_ICBPER' de la cabecera es correcto o no.

            $calculatedTaxICBPER = array_sum(array_column($items, 'tax_ICBPER'));  // Valida que 'tax_ICBPER' de la cabecera sea la suma correcta de los productos de tax_ICBPER y quantity_ICBPER para cada elemento en el array $items.


            if (round($calculatedTaxICBPER, 4) != round($request['tax_ICBPER'], 4)) {
                return $this->errorResponse('El valor proporcionado en el campo tax_ICBPER de la cabecera no es correcto. El valor del campo debería ser: ' . $calculatedTaxICBPER, 422);
            }



            //CABERCERA// Validando si el campo 'product_discount' de la cabecera es correcto o no.

            $productoDiscount = array_sum(array_column($items, 'prr_discount'));

            if ($productoDiscount != $request['product_discount']) {
                return $this->errorResponse('El valor proporcionado en el campo product_discount de la cabecera no es correcto. El valor del campo debería ser: ' . $productoDiscount, 422);
            }

            //CABECERA// Validando si el campo 'subtotal' de la cabecera es correcto o no.

            $calculatedSubtotal = array_sum(array_column($items, 'subtotal'));

            if (round($calculatedSubtotal, 4) != round($request['subtotal'], 4)) {
                return $this->errorResponse('El valor proporcionado en el campo subtotal de la cabecera no es correcto. El valor del campo debería ser: ' . $calculatedSubtotal, 422);
            }


            //CABECERA// Validando si el campo 'total' de la cabecera es correcto o no.

            $total = $request['affected'] + $request['non_affected'] + $request['exonerated'] + $request['total_tax'] + $request['tax_ICBPER'];

            if (round($total, 4) != round($request['total'], 4)) {
                return $this->errorResponse('El valor proporcionado en el campo total de la cabecera no es correcto. El valor del campo debería ser: ' . $total, 422);
            }

            //CABERCERA// Validando si el campo 'order_discount_percentage_value' de la cabecera es correcto o no.

            $orderDiscountPercentage = $request['order_discount_percentage']; //Este es un valor entero, el porcentaje usado para realizar las operaciones.
            $orderDiscountNoPercentageValue  = $request['order_discount_no_percentage_value'];

            if ($orderDiscountPercentage > 0 && $orderDiscountNoPercentageValue > 0) {

                return $this->errorResponse('Solo se puede aplicar el descuento ya sea mediante un porcentaje o restando un valor, pero no ambos al mismo tiempo.', 422);
            }

            $orderDiscountPercentageValue = ($total * ($orderDiscountPercentage / 100));

            if ($orderDiscountPercentageValue != $request['order_discount_percentage_value']) {
                return $this->errorResponse('El valor proporcionado en el campo order_discount_percentage_value de la cabecera no es correcto. El valor del campo debería ser: ' . $orderDiscountPercentageValue, 422);
            }



            //CABERCERA// Validando si el campo 'total_discount' de la cabecera es correcto o no.

            $totalDiscount = $orderDiscountPercentageValue + $productoDiscount + $orderDiscountNoPercentageValue;

            if ($totalDiscount != $request['total_discount']) {
                return $this->errorResponse('El valor proporcionado en el campo total_discount de la cabecera no es correcto. El valor del campo debería ser: ' . $totalDiscount, 422);
            }


            //CABECERA// Validando si el campo 'grand_total' de la cabecera es correcto o no.

            $grandTotal = $request['total'];

            if (round($grandTotal, 4) != round($request['grand_total'], 4)) {
                return $this->errorResponse('El valor proporcionado en el campo grand_total de la cabecera no es correcto. El valor del campo debería ser: ' . $grandTotal, 422);
            }

            $result = $this->purchaseOrderRepository->store($store);

            return $this->successResponse($result, "La orden de compra se agrego correctamente.", 201);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return $this->errorResponse($e->response->original, 422);
        }
    }

    public function update(int $id, Request $request)
    {
        try {
            if ($this->errorConnection != '') {
                return $this->messageError($this->errorConnection, 500);
            }

            $business_information = $request['business_information'];
            $business_ruc = $business_information['ruc_number'];

            //Validacion para el campo issuance_date en caso de que la data sea (d-m-Y) o (Y-m-d)
            $fecha_original = $request["issuance_date"];
            $fecha_convertida = date_create_from_format('d-m-Y', $fecha_original) ?: date_create_from_format('Y-m-d', $fecha_original);
            if (!$fecha_convertida) {
                return $this->errorResponse('La fecha proporcionada no es válida.', 422);
            }
            $request['issuance_date'] = $fecha_convertida->format('Y-m-d'); //tkmansilla

            foreach ((array)$request['items'] as $index => $item) {

                $index++;

                $fields = [
                    'igv', 'quantity', 'unit_price', 'affect_price', 'non_affected_price',
                    'exonerated_price', 'price_affected_item', 'price_no_affected_item', 'price_exonerated_item',
                    'item_discount', 'subtotal', 'tax_gratuito', 'tax', 'item_tax', 'quantity_ICBPER', 'tax_ICBPER', 'prr_discount', 'type_of_affectation', 'tax_method'
                ];

                foreach ($fields as $field) {
                    if (!isset($item[$field]) || $item[$field] === null) {
                        return $this->errorResponse("El ítem $index no tiene el campo '$field' definido en el JSON o su valor es nulo.", 422);
                    } elseif (!is_numeric($item[$field])) {
                        return $this->errorResponse("El ítem $index tiene un valor no numérico para el campo '$field' en el JSON.", 422);
                    } elseif (!is_numeric($request['mult_ICBPER'])) {
                        return $this->errorResponse("El campo mult_ICBPER de la cabecera posee un valor no numerico. ", 422);
                    }
                }
            }

            $this->validate(
                $request,
                [

                    'issuance_date' => 'required|date',
                    'num_purchase_order' => 'required|regex:/^[a-zA-Z0-9\-]+$/|max:12',
                    'supplier_id' => 'required|integer',
                    'supplier_name' => 'required|string|max:55',
                    'supplier_ruc' => 'required|integer',
                    'currency' => 'required|string|in:PEN,USD',
                    'exchange' => 'nullable|numeric',
                    'affected' => 'numeric',
                    'non_affected' => 'numeric',
                    'exonerated' => 'numeric',
                    'total' => 'required|numeric',
                    'product_discount' => 'required|numeric',
                    'order_discount_percentage' => 'required|integer',
                    'order_discount_percentage_value' => 'required|numeric',
                    'order_discount_no_percentage_value'  => 'required|numeric',
                    'total_discount' => 'required|numeric',
                    'product_tax' => 'required|nullable|numeric',
                    'order_tax_id' => 'nullable|string|max:20',
                    'order_tax' => 'nullable|numeric',
                    'total_tax' => 'required|numeric',
                    'tax_ICBPER' => 'required|numeric',
                    'mult_ICBPER' => 'required|numeric',
                    'subtotal' => 'required|numeric',
                    'grand_total' => 'required|numeric',
                    'total_items' => 'required|integer',
                    'total_quantity' => 'required|integer',
                    'note' => 'nullable|string|max:1000',
                    'rounding' => 'nullable|numeric',
                    'attachment' => 'nullable|string|max:255',
                    'expiration_date' => 'nullable|date',
                    'canal_id' => 'nullable|integer',
                    'payment_method_id' => 'nullable|integer',
                    'num_quotation' => 'integer',
                    'destination_address' => 'string|max:255',
                    'destination_ubigeo' => 'string|max:11',
                    'supplier_address' => 'string|max:100',
                    'supplier_contact_name' => 'string|max:50',
                    'supplier_contact_phone' => 'string|max:20',
                    'supplier_contact_email' => 'email|max:80',
                    'estado' => 'required|integer',

                    //Detalle
                    'items.*.product_id' => 'integer|nullable', //Este campo debe validarse que exista?
                    'items.*.code' => 'string|nullable|max:50',
                    'items.*.name' => 'string|nullable|max:255',
                    'items.*.quantity' => 'required|integer',
                    'items.*.unit_price' => 'required|numeric',


                    'items.*.affect_price' => [
                        'nullable',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $igv = $request['items'][$index[0]]['igv'];
                            $unit_price = $request['items'][$index[0]]['unit_price'];

                            if ($value != 0) {
                                $expectedAffectPrice = round($unit_price / (1 + ($igv / 100)), 4); // Base = Total / (1 + 0.18) 

                                if ($value != $expectedAffectPrice) {
                                    $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedAffectPrice);
                                }
                            }
                        },
                    ],

                    'items.*.non_affected_price' => [ // Si el campo IGV esta vacio o es 0 el valor es el del campo unit_price.
                        'nullable',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            // Extraer el índice del arreglo de ítems
                            $index = explode('.', str_replace('items.', '', $attribute));

                            // Obtener el valor del campo 'igv' del ítem correspondiente
                            $igv = $request['items'][$index[0]]['igv'];

                            if ($igv != 0) {
                                return;
                            }

                            if ($value != 0) {
                                // Calcular el valor esperado para 'non_affected_price' si 'igv' está vacío o es 0
                                $expectedNonAffectedPrice = empty($igv) || $igv == 0 ? $request['items'][$index[0]]['unit_price'] : null;

                                // Comparar el valor proporcionado con el valor esperado
                                if ($value !== $expectedNonAffectedPrice) {
                                    $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo deberia ser: " . $expectedNonAffectedPrice);
                                }
                            }
                        },
                    ],

                    'items.*.exonerated_price' => [ // Si el campo IGV esta vacio o es 0 el valor es el del campo unit_price.
                        'nullable',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            // Extraer el índice del arreglo de ítems
                            $index = explode('.', str_replace('items.', '', $attribute));

                            // Obtener el valor del campo 'igv' del ítem correspondiente
                            $igv = $request['items'][$index[0]]['igv'];


                            if ($igv != 0) {
                                return;
                            }

                            if ($value != 0) {
                                // Calcular el valor esperado para 'non_affected_price' si 'igv' está vacío o es 0
                                $expectedExoneratedPrice = empty($igv) || $igv == 0 ? $request['items'][$index[0]]['unit_price'] : null;

                                // Comparar el valor proporcionado con el valor esperado
                                if ($value !== $expectedExoneratedPrice) {
                                    $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo deberia ser: " . $expectedExoneratedPrice);
                                }
                            }
                        },
                    ],

                    'items.*.gratuito_price' => [
                        'nullable',
                        'numeric',
                        // function ($attribute, $value, $fail) use ($request) {
                        //     $index = explode('.', str_replace('items.', '', $attribute));
                        //     $unit_price = $request['items'][$index[0]]['unit_price'];


                        //     if ($value != $unit_price) {
                        //         $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $unit_price);
                        //     }
                        // },
                    ],

                    'items.*.price_affected_item' => [ // items.affect_price * quantity
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));
                            $affectPrice = $request['items'][$index[0]]['affect_price'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedPriceAffectedItem = round($affectPrice * $quantity, 4);

                            if ($value != $expectedPriceAffectedItem) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedPriceAffectedItem);
                            }
                        },
                    ],

                    'items.*.price_no_affected_item' => [ // non_affected_price * quantity
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));
                            $nonAffectedPrice = $request['items'][$index[0]]['non_affected_price'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedPriceNoAffectedItem = round($nonAffectedPrice * $quantity, 4);

                            if ($value != $expectedPriceNoAffectedItem) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedPriceNoAffectedItem);
                            }
                        },
                    ],
                    'items.*.price_exonerated_item' => [ // exonerated_price * quantity
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));
                            $exoneratedPrice = $request['items'][$index[0]]['exonerated_price'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedPriceExoneratedItem = round($exoneratedPrice * $quantity, 4);

                            if ($value != $expectedPriceExoneratedItem) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedPriceExoneratedItem);
                            }
                        },
                    ],

                    'items.*.tax_gratuito' => [
                        'numeric',
                        'nullable',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            // Verificar si el ítem existe en la solicitud
                            if (isset($request['items'][$index[0]])) {
                                $exoneratedPrice = $request['items'][$index[0]]['exonerated_price'];
                                $nonAffectedPrice = $request['items'][$index[0]]['non_affected_price'];
                                $affectPrice = $request['items'][$index[0]]['affect_price'];

                                // Si alguno de los campos 'exonerated_price', 'non_affected_price', o 'affect_price' es diferente de 0 no validar.
                                if ($exoneratedPrice != 0 || $nonAffectedPrice != 0 || $affectPrice != 0) {
                                    return;
                                }

                                $igv = $request['items'][$index[0]]['igv'];
                                $unitPrice = $request['items'][$index[0]]['unit_price'];

                                // Calcular el valor esperado para 'tax_gratuito' en función de 'unit_price' e 'igv'
                                $expectedTaxGratuito = round($unitPrice * ($igv / 100), 4);

                                // Comparar el valor proporcionado con el valor esperado, permitiendo una pequeña diferencia (0.01)
                                if (abs($value - $expectedTaxGratuito) > 0.01) {
                                    $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedTaxGratuito);
                                }
                            }
                        },
                    ],

                    'items.*.discount' => 'string|nullable|max:20',
                    'items.*.item_discount' => 'integer|nullable', //Porcentaje de descuento, valor entero.

                    'items.*.prr_discount' => [
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $discount = $request['items'][$index[0]]['item_discount'];
                            $subtotal = $request['items'][$index[0]]['subtotal'];

                            $expectedDiscountValueItem = round($subtotal * ($discount / 100), 4);

                            if (abs($value - $expectedDiscountValueItem) > 0.01) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedDiscountValueItem);
                            }
                        },
                    ],

                    'items.*.tax' => [
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));


                            $unitPrice = $request['items'][$index[0]]['unit_price'];
                            $TaxAffectPrice = $request['items'][$index[0]]['affect_price'];
                            // $TaxGratuito = $request['items'][$index[0]]['gratuito_price'];

                            $expectedTax = 0;

                            if ($TaxAffectPrice != 0) {
                                $expectedTax = round($unitPrice - $TaxAffectPrice, 4);
                            }
                            // if ($TaxGratuito != 0) {
                            //     $expectedTax = round($unitPrice - $TaxGratuito, 4);
                            // }

                            // Comparar el valor proporcionado con el valor esperado, permitiendo una pequeña diferencia (0.01)
                            if (abs($value - $expectedTax) > 0.01) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $expectedTax);
                            }
                        },
                    ],

                    'items.*.item_tax' => [ // tax * quantity
                        'numeric',
                        'nullable',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $tax = $request['items'][$index[0]]['tax'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedItemTax = round($tax * $quantity, 4);

                            if ($value != $expectedItemTax) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo deberia ser: " . $expectedItemTax);
                            }
                        },
                    ],

                    'items.*.item_tax_gratuito' => [ // tax_gratuito * quantity
                        'numeric',
                        'nullable',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $tax = $request['items'][$index[0]]['tax_gratuito'];
                            $quantity = $request['items'][$index[0]]['quantity'];

                            $expectedItemTaxGratuitous = round($tax * $quantity, 4);

                            if ($value != $expectedItemTaxGratuitous) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo deberia ser: " . $expectedItemTaxGratuitous);
                            }
                        },
                    ],

                    'items.*.igv' => 'required|integer|max:20', //Valor en porcentaje. Ejemplo: 18

                    'items.*.tax_ICBPER' => [ // Impuesto a las bolsas plasticas, 50 centimos (Impuesto o costo de la bolsa )
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));
                            $ICBPERquantity = $request['items'][$index[0]]['quantity_ICBPER'];
                            $ICBPERvalue = $request['mult_ICBPER'];


                            $taxICBPER = $ICBPERvalue * $ICBPERquantity;

                            if (round($value, 2) != round($taxICBPER, 2)) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $taxICBPER);
                            }
                        }
                    ],


                    'items.*.quantity_ICBPER' => 'required|integer', //Cantidad de bolsas plasticas que llevas x item

                    'items.*.subtotal' => [ // Suma de los 3 campos, price_affected_item, price_no_affected_item, price_exonerated_item, (tax_ICBPER * quantity_ICBPER) y item_tax o item_tax_gratuito en el caso de un item gratuito
                        'required',
                        'numeric',
                        function ($attribute, $value, $fail) use ($request) {
                            $index = explode('.', str_replace('items.', '', $attribute));

                            $affectItem = $request['items'][$index[0]]['price_affected_item'];
                            $noAffectItem = $request['items'][$index[0]]['price_no_affected_item'];
                            $exoneratedItem = $request['items'][$index[0]]['price_exonerated_item'];
                            $itemTax = $request['items'][$index[0]]['item_tax'];
                            $itemTax_ICBPER = $request['items'][$index[0]]['tax_ICBPER'];
                            $prrDiscount = $request['items'][$index[0]]['prr_discount'];

                            $subtotal = round(($affectItem + $noAffectItem + $exoneratedItem + $itemTax + $itemTax_ICBPER) - $prrDiscount, 4);

                            if (abs($value - $subtotal) > 0.01) {
                                $fail("El valor proporcionado en el campo '$attribute' no es correcto. El valor del campo debería ser: " . $subtotal);
                            }
                        }
                    ],

                    'items.*.real_unit_price' => 'numeric|nullable', // -
                    'items.*.cost' => 'numeric|nullable', // -
                    'items.*.tax_method' => 'required|integer', // - 
                    'items.*.type_of_affectation' => 'required|integer', // - 
                ],
                [   //Mensajes para las validaciones:
                    'issuance_date.required' => 'El campo de fecha es obligatorio.',
                    'issuance_date.date' => 'El formato del campo de fecha no es válido.',
                    'num_purchase_order.required' => 'El campo num_purchase_order es obligatorio.',
                    'num_purchase_order.regex' => 'El campo num_purchase_order debe contener solo letras, números y guiones.',
                    'num_purchase_order.max' => 'El campo num_purchase_order no puede tener más de :max caracteres.',
                    'supplier_id.required' => 'El campo supplier_id es obligatorio.',
                    'supplier_id.integer' => 'El campo supplier_id debe ser un número entero.',
                    'supplier_name.required' => 'El campo supplier_name es obligatorio.',
                    'supplier_name.string' => 'El campo supplier_name debe ser una cadena de texto.',
                    'supplier_name.max' => 'El campo supplier_name no puede tener más de :max caracteres.',
                    'supplier_ruc.required' => 'El campo supplier_ruc es obligatorio.',
                    'supplier_ruc.integer' => 'El campo supplier_ruc debe ser un numero entero.',
                    'supplier_ruc.max' => 'El campo supplier_ruc no puede tener más de :max caracteres.',
                    'currency.required' => 'El campo currency es obligatorio.',
                    'currency.string' => 'El campo currency debe ser una cadena de texto.',
                    'currency.in' => 'El campo currency debe ser PEN o USD.',
                    'exchange.numeric' => 'El campo exchange debe ser un número.',
                    'affected.numeric' => 'El campo affected debe ser un número.',
                    'non_affected.numeric' => 'El campo non_affected debe ser un número.',
                    'exonerated.numeric' => 'El campo exonerated debe ser un número.',
                    'total.required' => 'El campo total es obligatorio.',
                    'total.numeric' => 'El campo total debe ser un número.',
                    'product_discount.required' => 'El campo product_discount es obligatorio.',
                    'product_discount.numeric' => 'El campo product_discount debe ser un número.',
                    'order_discount_percentage.required' => 'El campo order_discount_percentage es obligatorio.',
                    'order_discount_percentage.integer' => 'El campo order_discount_percentage debe ser un número entero.',
                    'order_discount_percentage_value.required' => 'El campo order_discount_percentage_value es obligatorio.',
                    'order_discount_percentage_value.numeric' => 'El campo order_discount_percentage_value debe ser un número.',
                    'order_discount_no_percentage_value.required' => 'El campo order_discount_no_percentage_value es obligatorio.',
                    'order_discount_no_percentage_value.numeric' => 'El campo order_discount_no_percentage_value debe ser un número.',
                    'total_discount.required' => 'El campo total_discount es obligatorio.',
                    'total_discount.numeric' => 'El campo total_discount debe ser un número.',
                    'product_tax.required' => 'El campo product_tax es obligatorio.',
                    'product_tax.numeric' => 'El campo product_tax debe ser un número.',
                    'order_tax_id.required' => 'El campo order_tax_id es obligatorio.',
                    'order_tax_id.string' => 'El campo order_tax_id debe ser una cadena de texto.',
                    'order_tax_id.max' => 'El campo order_tax_id no puede tener más de :max caracteres.',
                    'order_tax.numeric' => 'El campo order_tax debe ser un número.',
                    'total_tax.required' => 'El campo total_tax es obligatorio.',
                    'total_tax.numeric' => 'El campo total_tax debe ser un número.',
                    'tax_ICBPER.required' => 'El campo tax_ICBPER es obligatorio.',
                    'tax_ICBPER.numeric' => 'El campo tax_ICBPER debe ser un número.',
                    'mult_ICBPER.required' => 'El campo mult_ICBPER es obligatorio.',
                    'mult_ICBPER.numeric' => 'El campo mult_ICBPER debe ser un número.',
                    'subtotal.required' => 'El campo subtotal es obligatorio.',
                    'subtotal.numeric' => 'El campo subtotal debe ser un número.',
                    'grand_total.required' => 'El campo grand_total es obligatorio.',
                    'grand_total.numeric' => 'El campo grand_total debe ser un número.',
                    'total_items.required' => 'El campo total_items es obligatorio.',
                    'total_items.integer' => 'El campo total_items debe ser un número entero.',
                    'total_quantity.required' => 'El campo total_quantity es obligatorio.',
                    'total_quantity.integer' => 'El campo total_quantity debe ser un número entero.',
                    'note.string' => 'El campo note debe ser una cadena de texto.',
                    'note.max' => 'El campo note no puede tener más de :max caracteres.',
                    'rounding.numeric' => 'El campo rounding debe ser un número.',
                    'attachment.string' => 'El campo attachment debe ser una cadena de texto.',
                    'attachment.max' => 'El campo attachment no puede tener más de :max caracteres.',
                    'expiration_date.date' => 'El campo expiration_date no es válido.',
                    'canal_id.integer' => 'El campo canal_id debe ser un número entero.',
                    'payment_method_id.integer' => 'El campo payment_method_id debe ser un número entero.',
                    'num_quotation.integer' => 'El campo num_quotation debe ser un número entero.',
                    'destination_address.string' => 'El campo destination_address debe ser una cadena de texto.',
                    'destination_address.max' => 'El campo destination_address no puede tener más de :max caracteres.',
                    'destination_ubigeo.string' => 'El campo destination_ubigeo debe ser una cadena de texto.',
                    'destination_ubigeo.max' => 'El campo destination_ubigeo no puede tener más de :max caracteres.',
                    'supplier_contact_name.string' => 'El campo supplier_contact_name debe ser una cadena de texto.',
                    'supplier_contact_name.max' => 'El campo supplier_contact_name no puede tener más de :max caracteres.',
                    'supplier_address.string' => 'El campo supplier_address debe ser una cadena de texto.',
                    'supplier_address.max' => 'El campo supplier_address no puede tener más de :max caracteres.',
                    'supplier_contact_phone.string' => 'El campo supplier_contact_phone debe ser una cadena de texto.',
                    'supplier_contact_phone.max' => 'El campo supplier_contact_phone no puede tener más de :max caracteres.',
                    'supplier_contact_email.email' => 'El campo supplier_contact_email no es válido.',
                    'supplier_contact_email.max' => 'El campo supplier_contact_email no puede tener más de :max caracteres.',
                    'estado.required' => 'El campo estado es obligatorio.',
                    'estado.integer' => 'El campo estado debe ser un número entero.',

                    //Mensajes de validacion para items:
                    'items.*.purchase_order_header_id.required' => 'El campo ID de compra es obligatorio para todos los elementos.',
                    'items.*.product_id.integer' => 'El campo ID de producto debe ser un número entero para todos los elementos.',
                    'items.*.code.string' => 'El campo Código debe ser una cadena de texto para todos los elementos.',
                    'items.*.code.max' => 'El campo Código no debe superar los 50 caracteres para todos los elementos.',
                    'items.*.name.string' => 'El campo Nombre debe ser una cadena de texto para todos los elementos.',
                    'items.*.name.max' => 'El campo Nombre no debe superar los 255 caracteres para todos los elementos.',
                    'items.*.quantity.required' => 'El campo Cantidad es obligatorio para todos los elementos.',
                    'items.*.quantity.integer' => 'El campo Cantidad debe ser un valor entero para todos los elementos.',
                    'items.*.unit_price.required' => 'El campo Precio unitario es obligatorio para todos los elementos.',
                    'items.*.unit_price.numeric' => 'El campo Precio unitario debe ser un valor numérico para todos los elementos.',
                    'items.*.affect_price.required' => 'El campo Precio afectado es obligatorio para todos los elementos.',
                    'items.*.affect_price.numeric' => 'El campo Precio afectado debe ser un valor numérico para todos los elementos.',
                    'items.*.non_affected_price.required' => 'El campo Precio no afectado es obligatorio para todos los elementos.',
                    'items.*.non_affected_price.numeric' => 'El campo Precio no afectado debe ser un valor numérico para todos los elementos.',
                    'items.*.exonerated_price.required' => 'El campo Precio exonerado es obligatorio para todos los elementos.',
                    'items.*.exonerated_price.numeric' => 'El campo Precio exonerado debe ser un valor numérico para todos los elementos.',
                    'items.*.gratuito_price.numeric' => 'El campo Precio gratuito debe ser un valor numérico para todos los elementos.',
                    'items.*.price_affected_item.required' => 'El campo Precio afectado por ítem es obligatorio para todos los elementos.',
                    'items.*.price_affected_item.numeric' => 'El campo Precio afectado por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.price_no_affected_item.required' => 'El campo Precio no afectado por ítem es obligatorio para todos los elementos.',
                    'items.*.price_no_affected_item.numeric' => 'El campo Precio no afectado por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.price_exonerated_item.required' => 'El campo Precio exonerado por ítem es obligatorio para todos los elementos.',
                    'items.*.price_exonerated_item.numeric' => 'El campo Precio exonerado por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.price_gratuito_item.numeric' => 'El campo Precio gratuito por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.discount.string' => 'El campo Descuento debe ser una cadena de texto para todos los elementos.',
                    'items.*.discount.max' => 'El campo Descuento no debe superar los 20 caracteres para todos los elementos.',
                    'items.*.item_discount.integer' => 'El campo Descuento por ítem debe ser un valor entero para todos los elementos.',
                    'items.*.prr_discount.required' => 'El campo Descuento PRR es obligatorio para todos los elementos.',
                    'items.*.prr_discount.numeric' => 'El campo Descuento PRR debe ser un valor numérico para todos los elementos.',
                    'items.*.tax.required' => 'El campo Impuesto es obligatorio para todos los elementos.',
                    'items.*.tax.numeric' => 'El campo Impuesto debe ser un valor numérico para todos los elementos.',
                    'items.*.item_tax.numeric' => 'El campo Impuesto por ítem debe ser un valor numérico para todos los elementos.',
                    'items.*.tax_gratuito.numeric' => 'El campo Impuesto gratuito debe ser un valor numérico para todos los elementos.',
                    'items.*.item_tax_gratuito.numeric' => 'El campo Impuesto por ítem gratuito debe ser un valor numérico para todos los elementos.',
                    'items.*.igv.required' => 'El campo IGV es obligatorio para todos los elementos.',
                    'items.*.igv.max' => 'El campo IGV no debe superar los 20 caracteres para todos los elementos.',
                    'items.*.tax_ICBPER.required' => 'El campo Impuesto ICBPER es obligatorio para todos los elementos.',
                    'items.*.tax_ICBPER.numeric' => 'El campo Impuesto ICBPER debe ser un valor numérico para todos los elementos.',
                    'items.*.quantity_ICBPER.required' => 'El campo Cantidad ICBPER es obligatorio para todos los elementos.',
                    'items.*.quantity_ICBPER.integer' => 'El campo Cantidad ICBPER debe ser un número entero para todos los elementos.',
                    'items.*.subtotal.required' => 'El campo Subtotal es obligatorio para todos los elementos.',
                    'items.*.subtotal.numeric' => 'El campo Subtotal debe ser un valor numérico para todos los elementos.',
                    'items.*.real_unit_price.numeric' => 'El campo Precio unitario real debe ser un valor numérico para todos los elementos.',
                    'items.*.cost.numeric' => 'El campo Costo debe ser un valor numérico para todos los elementos.',
                    'items.*.tax_method.required' => 'El campo Método de impuesto es obligatorio para todos los elementos.',
                    'items.*.tax_method.integer' => 'El campo Método de impuesto debe ser un número entero para todos los elementos.',
                    'items.*.type_of_affectation.required' => 'El campo tipo de afectacion es obligatorio para todos los elementos.',
                    'items.*.type_of_affectation.integer' => 'El campo tipo de afectacion debe ser un número entero para todos los elementos.',
                    'items.*.status.numeric' => 'El campo Estado debe ser un valor numérico para todos los elementos.',
                ]
            );

            $entry = new PurchaseOrderUpdateDto();

            $entry->ruc = $business_ruc;
            $entry->id = $id;

            $entry->issuance_date = $request["issuance_date"];
            $entry->num_purchase_order = $request["num_purchase_order"];
            $entry->supplier_id = $request["supplier_id"];
            $entry->supplier_name = $request["supplier_name"];
            $entry->supplier_ruc = $request["supplier_ruc"];
            $entry->currency = $request["currency"]; //USD o PEN
            $entry->exchange = $request["exchange"];
            $entry->affected = $request["affected"]; //Valor total 
            $entry->non_affected = $request["non_affected"];
            $entry->exonerated = $request["exonerated"];
            $entry->total = $request["total"];
            $entry->product_discount = $request["product_discount"];
            $entry->order_discount_percentage = $request["order_discount_percentage"]; // PORCENTAJE
            $entry->order_discount_percentage_value = $request["order_discount_percentage_value"]; // RESULTADO DE APLICAR EL DESCUENTO PORCENTUAL AL SUBTOTAL DE LA CABECERA
            $entry->order_discount_no_percentage_value = $request["order_discount_no_percentage_value"]; //VALOR DEL DESCUENTO A APLICAR 
            $entry->total_discount = $request["total_discount"]; // LA SUMA DE ORDER DISCOUNT + PRR DISCUENTO
            $entry->product_tax = $request["product_tax"];
            $entry->order_tax_id = $request["order_tax_id"];
            $entry->order_tax = $request["order_tax"];
            $entry->total_tax = $request["total_tax"];
            $entry->tax_ICBPER = $request["tax_ICBPER"];
            $entry->mult_ICBPER = $request["mult_ICBPER"];
            $entry->subtotal = $request["subtotal"];
            $entry->grand_total = $request["grand_total"];
            $entry->total_items = $request["total_items"];
            $entry->total_quantity = $request["total_quantity"];
            $entry->note = $request["note"];
            $entry->rounding = $request["rounding"];
            $entry->attachment = $request["attachment"];
            $entry->expiration_date = $request["expiration_date"];
            $entry->canal_id = $request["canal_id"];
            $entry->payment_method_id = $request["payment_method_id"];
            $entry->num_quotation = $request["num_quotation"];
            $entry->destination_address = $request["destination_address"];
            $entry->destination_ubigeo = $request["destination_ubigeo"];
            $entry->supplier_address = $request["supplier_address"];
            $entry->supplier_contact_name = $request["supplier_contact_name"];
            $entry->supplier_contact_phone = $request["supplier_contact_phone"];
            $entry->supplier_contact_email = $request["supplier_contact_email"];
            $entry->estado = $request["estado"];
            $entry->created_by = $request['created_by'];
            $entry->created_at = date('Y-m-d h:m:s');

            $entry->status = 1;

            //ITEMS
           //ITEMS
           $items = (array)$request['items']; // Convirtiendo en array el objeto items

           //DETALLE// Asignando el valor 1 por defecto al campo STATUS de auditoria de los items al registrarlos.
           foreach ($items as &$item) {
               $item['status'] = $item['status'] ?? '1';
           }
           $entry->items = $items;

           //CABECERA// Validando si el campo 'total_quantity' de la cabecera es correcto o no.
           $totalQuantity = array_sum(array_column($items, 'quantity'));

           if ($totalQuantity != $request['total_quantity']) {
               return $this->errorResponse('El valor proporcionado en el campo total_quantity de la cabecera no es correcto. El valor del campo deberia ser: ' . $totalQuantity, 422);
           }

           //CABECERA// Validando si el campo 'total_quantity' de la cabecera es correcto o no.
           $totalQuantityItems = count((array)$request['items']);

           if ($totalQuantityItems != $request['total_items']) {
               return $this->errorResponse('El valor proporcionado en el campo total_items de la cabecera no es correcto. El valor del campo deberia ser: ' . $totalQuantityItems, 422);
           }

           //VALIDACION EN CASO DE QUE SE HAYE UN DESCUENTO GLOBAL

           $totalDiscount = $request['total_discount'];


           if ($totalDiscount > 0) {

               $totalAfectado = array_sum(array_column($items, 'price_affected_item'));
               $totalTax = ($totalAfectado - $totalDiscount) * (18 / 100); //18 TIENE QUE SER REMPLAZADO POR EL VALOR DEL IGV TRAIDO DIRECTAMENTE DESDE SETTINGS

           } else {

               $totalTax = array_sum(array_column($items, 'item_tax'));

           }

           //CABECERA//Validando si el valor del campo 'total_tax' de la cabecera es correcto o no.

           if (round($totalTax, 4) != round($request['total_tax'], 4)) {
               return $this->errorResponse('El valor proporcionado en el campo total_tax de la cabecera no es correcto. El valor del campo debería ser: ' . $totalTax, 422);
           }




           //CABECERA// Validando si el valor de los campos 'price_affected', 'non_affected' y 'exonerated' de la cabecera son correctos o no.


           $totalAfectado = array_sum(array_column($items, 'price_affected_item'));

           $totalNoAfectado = array_sum(array_column($items, 'price_no_affected_item'));
           $totalExonerado = array_sum(array_column($items, 'price_exonerated_item'));

           if ($totalDiscount > 0) {

               $nuevoTotalAfectado = $totalAfectado - $totalDiscount;

               if (round($nuevoTotalAfectado, 4) != round($request['affected'], 4)) {
                   return $this->errorResponse('El valor proporcionado en el campo affected de la cabecera no es correcto. El valor del campo debería ser: ' . $nuevoTotalAfectado, 422);
               }
           } else {

               if (round($totalAfectado, 4) != round($request['affected'], 4)) {
                   return $this->errorResponse('El valor proporcionado en el campo affected de la cabecera no es correcto. El valor del campo debería ser: ' . $totalAfectado, 422);
               }
           }


           if (round($totalNoAfectado, 4) != round($request['non_affected'], 4)) {
               return $this->errorResponse('El valor proporcionado en el campo non_affected de la cabecera no es correcto. El valor del campo debería ser: ' . $totalNoAfectado, 422);
           }

           if (round($totalExonerado, 4) != round($request['exonerated'], 4)) {
               return $this->errorResponse('El valor proporcionado en el campo exonerated de la cabecera no es correcto. El valor del campo debería ser: ' . $totalExonerado, 422);
           }



           //CABECERA//Validando si el valor del campo 'tax_ICBPER' de la cabecera es correcto o no.

           $calculatedTaxICBPER = array_sum(array_column($items, 'tax_ICBPER'));  // Valida que 'tax_ICBPER' de la cabecera sea la suma correcta de los productos de tax_ICBPER y quantity_ICBPER para cada elemento en el array $items.


           if (round($calculatedTaxICBPER, 4) != round($request['tax_ICBPER'], 4)) {
               return $this->errorResponse('El valor proporcionado en el campo tax_ICBPER de la cabecera no es correcto. El valor del campo debería ser: ' . $calculatedTaxICBPER, 422);
           }



           //CABERCERA// Validando si el campo 'product_discount' de la cabecera es correcto o no.

           $productoDiscount = array_sum(array_column($items, 'prr_discount'));

           if ($productoDiscount != $request['product_discount']) {
               return $this->errorResponse('El valor proporcionado en el campo product_discount de la cabecera no es correcto. El valor del campo debería ser: ' . $productoDiscount, 422);
           }

           //CABECERA// Validando si el campo 'subtotal' de la cabecera es correcto o no.

           $calculatedSubtotal = array_sum(array_column($items, 'subtotal'));

           if (round($calculatedSubtotal, 4) != round($request['subtotal'], 4)) {
               return $this->errorResponse('El valor proporcionado en el campo subtotal de la cabecera no es correcto. El valor del campo debería ser: ' . $calculatedSubtotal, 422);
           }


           //CABECERA// Validando si el campo 'total' de la cabecera es correcto o no.

           $total = $request['affected'] + $request['non_affected'] + $request['exonerated'] + $request['total_tax'] + $request['tax_ICBPER'];

           if (round($total, 4) != round($request['total'], 4)) {
               return $this->errorResponse('El valor proporcionado en el campo total de la cabecera no es correcto. El valor del campo debería ser: ' . $total, 422);
           }

           //CABERCERA// Validando si el campo 'order_discount_percentage_value' de la cabecera es correcto o no.

           $orderDiscountPercentage = $request['order_discount_percentage']; //Este es un valor entero, el porcentaje usado para realizar las operaciones.
           $orderDiscountNoPercentageValue  = $request['order_discount_no_percentage_value'];

           if ($orderDiscountPercentage > 0 && $orderDiscountNoPercentageValue > 0) {

               return $this->errorResponse('Solo se puede aplicar el descuento ya sea mediante un porcentaje o restando un valor, pero no ambos al mismo tiempo.', 422);
           }

           $orderDiscountPercentageValue = ($total * ($orderDiscountPercentage / 100));

           if ($orderDiscountPercentageValue != $request['order_discount_percentage_value']) {
               return $this->errorResponse('El valor proporcionado en el campo order_discount_percentage_value de la cabecera no es correcto. El valor del campo debería ser: ' . $orderDiscountPercentageValue, 422);
           }



           //CABERCERA// Validando si el campo 'total_discount' de la cabecera es correcto o no.

           $totalDiscount = $orderDiscountPercentageValue + $productoDiscount + $orderDiscountNoPercentageValue;

           if ($totalDiscount != $request['total_discount']) {
               return $this->errorResponse('El valor proporcionado en el campo total_discount de la cabecera no es correcto. El valor del campo debería ser: ' . $totalDiscount, 422);
           }


           //CABECERA// Validando si el campo 'grand_total' de la cabecera es correcto o no.

           $grandTotal = $request['total'];

           if (round($grandTotal, 4) != round($request['grand_total'], 4)) {
               return $this->errorResponse('El valor proporcionado en el campo grand_total de la cabecera no es correcto. El valor del campo debería ser: ' . $grandTotal, 422);
           }

            $entry->items = (array)$request['items']; // ¿Esto funciona?

            //ITEMS
            $items = (array)$request['items']; // Convirtiendo en array el objeto items

            //DETALLE// Asignando el valor 1 por defecto al campo STATUS de auditoria de los items al registrarlos.
            foreach ($items as &$item) {
                $item['status'] = $item['status'] ?? '1';
            }
            $entry->items = $items;

            $this->purchaseOrderRepository->update($entry);

            $result = $this->purchaseOrderRepository->find($id, $business_ruc);

            return $this->successResponse($result, "La orden de compra se actualizo correctamente.", 201);
        } catch (\Illuminate\Validation\ValidationException $e) {
            return $this->errorResponse($e->response->original, 422);
        }
    }

    public function change_estado(int $id, Request $request)
    {

        if ($this->errorConnection != '') {
            return $this->messageError($this->errorConnection, 500);
        }
        $business_information = $request['business_information'];
        $business_ruc = $business_information['ruc_number'];

        $result = $this->purchaseOrderRepository->find($id, $business_ruc);

        if ($result) {
            $this->purchaseOrderRepository->change_estado($id);

            return $this->successResponse($id, "La orden se finalizo correctamente.", 200);
        } else {
            return $this->errorResponse("Orden de compra inexistente.", 404);
        }
    }

    public function destroy(int $id, Request $request)
    {

        if ($this->errorConnection != '') {
            return $this->messageError($this->errorConnection, 500);
        }
        $business_information = $request['business_information'];
        $business_ruc = $business_information['ruc_number'];

        $result = $this->purchaseOrderRepository->find($id, $business_ruc);

        if ($result) {
            $this->purchaseOrderRepository->destroy($id);

            return $this->successResponse($id, "Orden de compra eliminado correctamente.", 200);
        } else {
            return $this->errorResponse("Orden de compra inexistente.", 404);
        }
    }
}
