<?php

namespace App\Services;

use App\Http\Resources\ProductEntryResource;
use App\Models\IntakeCart;
use App\Models\ProductEntry;
use App\Models\ProductEntryDetail;
use App\Models\StockProduct;
use App\Models\Store;
use App\Traits\HasResponse;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Tymon\JWTAuth\Facades\JWTAuth;

/**
 * Class ProductEntryService
 * @package App\Services
 */
class ProductEntryService
{
    use HasResponse;

    public function list($params, $withPagination)
    {
        try {
            $data = ProductEntry::filters();

            $data = !empty($withPagination)
                ? $data->paginate($withPagination['perPage'], page: $withPagination['page'])
                : $data->get();

            $paginationTotal = null;
            if (!empty($withPagination)) $paginationTotal = $data->total();

            $data = ProductEntryResource::collection($data->load(
                'supplier',
                'details.product.unitMeasure'
            ));

            return $this->successPaginationResponse('Lectura exitosa.', $paginationTotal, $data);
        } catch (\Throwable $th) {
            throw $th;
        }
    }

    public function register($params)
    {
        DB::beginTransaction();
        try {
            # Validar el carrito de ingreso
            $intakeCart = IntakeCart::activeForId($params['idintake_cart'])
                ->where('status_entry', 0)
                ->first()
                ->load('details.product');
            if (!$intakeCart) return $this->errorResponse('Carrito seleccionado no válido.', 400);

            # Si no hay productos en el carrito
            if (count($intakeCart->details) == 0) return $this->errorResponse('El carrito seleccionado no cuenta con productos.', 400);

            # Crear entrada de productos
            $productEntry = ProductEntry::create([
                'idintake_cart'  => $intakeCart->id,
                'iduser_created' => JWTAuth::user()->id,
                'idsupplier' => $intakeCart->idsupplier,
                'idcompany'  => $intakeCart->idcompany,
            ]);

            # Bodega principal
            $store = Store::where('idcompany', $intakeCart->idcompany)
                ->active()
                ->first();

            $cost_total = 0;
            foreach ($intakeCart->details as $row) {
                # Calcular el costo total de la fila
                $row_cost = $row['product']['cost'] * $row['quantity'];

                # Registrar ingreso
                ProductEntryDetail::create([
                    'idproduct_entry' => $productEntry->id,
                    'idproduct' => $row['idproduct'],
                    'quantity' => $row['quantity'],
                    'cost_total' => $row_cost
                ]);

                # Ultimo stock  
                $lastStock = StockProduct::where('idproduct', $row['idproduct'])
                    ->when(
                        $store != null,
                        fn($q) => $q->where('idwarehouse', $store->id)
                    )->active()
                    ->orderBy('id', 'desc')
                    ->first();

                $newStock = $lastStock ? $lastStock->stock_system + $row['quantity'] : $row['quantity'];

                # Actualizar stock
                StockProduct::create([
                    'stock_system'      => $newStock,
                    'registration_date' => Carbon::now()->toDateTimeString(),
                    'last_update'       => $lastStock->registration_date ?? Carbon::now()->toDateTimeString(),
                    'idproduct'         => $row['idproduct'],
                    'idwarehouse'       => $store->id,
                    'idcompany'         => $intakeCart->idcompany,
                    'type_movement'     => 1,
                    'initial_stock'     => $lastStock->stock_system ?? 0,
                    'difference'        => $row['quantity'],
                    'folio'             => $productEntry->id,
                    'type_dte'          => '',
                    'date_dte'          => Carbon::now()->toDateTimeString(),
                ]);

                # Sumar al costo total
                $cost_total += $row_cost;
            }

            $productEntry->update(['cost_total' => $cost_total]);

            $intakeCart->update(['status_entry' => 1]);

            DB::commit();
            return $this->successResponse('Ingreso de productos registrado con éxito.', $productEntry);
        } catch (\Throwable $th) {
            DB::rollBack();
            return $this->externalError('durante la creación del ingreso de productos.', $th->getMessage());
        }
    }
}
