<?php

namespace App\Services;

use App\Order;
use App\OrderPackage;
use App\Services\common\BatchUpdateService;
use App\Services\common\DataHandlerService;
use App\Traits\ServiceAppAop;
use App\OrderPackageCommoditySerialNumber;
use Illuminate\Support\Carbon;

class OrderPackageCommoditySerialNumberService
{
    use ServiceAppAop;

    protected $modelClass = OrderPackageCommoditySerialNumber::class;

    public function batchUpdate(array $params)
    {
        return app(BatchUpdateService::class)->batchUpdate('order_packages_commodity_serial_numbers',$params);
    }

    public function syncOrderPackageCommoditySerialNumbers($orderHeaders)
    {
        $orderQuery = Order::query()->selectRaw('id')->whereIn('code', data_get($orderHeaders, '*.orderno'));
        $orderPackages = OrderPackage::query()->with(['commodities' => function ($query) {
            $query->with('commodity', 'serialNumbers');
        }])->whereIn('order_id', $orderQuery)->get();

        $createdModels = $this->getCreateModelBy($orderHeaders, $orderPackages);

        $regroupParams = $this->regroupOrderPackage($orderPackages);

        $this->deletedModelBy($createdModels,$regroupParams);
        $this->createdModelBy($createdModels,$regroupParams);
    }

    public function regroupOrderPackage($orderPackages): array
    {
        $regroupArr = [];
        if (!$orderPackages) return $regroupArr;
        foreach ($orderPackages as $orderPackage) {
            $logistic_number = $orderPackage['logistic_number'];
            $regroupArr[$logistic_number] = [];
            foreach ($orderPackage['commodities'] as $commodity) {
                $sku = $commodity['commodity']['sku'] ?? null;
                $regroupArr[$logistic_number][$sku] = [];
                foreach ($commodity['serialNumbers'] as $serialNumber) {
                    $serial_number = $serialNumber['serial_number'];
                    $id = $serialNumber['id'];
                    $regroupArr[$logistic_number][$sku][$serial_number]
                        = ['id'=>$id,'order_package_commodity_id' => $commodity['id'], 'serial_number' => $serial_number];
                }
            }
        }
        return $regroupArr;
    }

    public function createdModelBy($createdModels, $regroupParams)
    {
        $innerParams = [];
        foreach ($createdModels as $key => $createdParams) {
            foreach ($createdParams as $sku => $params) {
                foreach ($params as $serialNumber =>$param) {
                    if(!isset($regroupParams[$key][$sku][$serialNumber])){
                        $innerParams[] = $param;
                    }
                }
            }
        }
        OrderPackageCommoditySerialNumber::query()->insert($innerParams);
    }

//    public function updatedModelBy($createdModels, $regroupParams)
//    {
//        $updateParams = [['id','serial_number']];
//        if (count($updateParams) == 0) return;
//        $this->batchUpdate($updateParams);
//    }

    public function deletedModelBy($createdModels, $regroupParams)
    {
        $deleteParams = [];
        foreach ($regroupParams as $key => $params) {
            if (!isset($regroupParams[$key])) continue;
            foreach ($params as $sku => $items) {
                foreach ($items as $serialNumber=>$item) {
                    if (!isset($createdModels[$key][$sku][$serialNumber])){
                        $deleteParams[] = $item;
                    }
                }
            }
        }
        if (count($deleteParams)==0) return;
        $delete = OrderPackageCommoditySerialNumber::query()->whereIn('id',data_get($deleteParams,'*.id'))->delete();
        if($delete>0)LogService::log(__CLASS__,'Delete OrderPackageCommoditySerialNumber',json_encode($deleteParams));
    }

    public function getCreateModelBy($orderHeaders, $orderPackages): array
    {
        /** @var DataHandlerService $dataHandlerService */
        $dataHandlerService = app(DataHandlerService::class);

        $orderPackageMaps = $dataHandlerService->dataHeader(['logistic_number'], $orderPackages);

        $orderPackageSerialNumbers = [];

        foreach ($orderHeaders as $orderHeader) {
            if(!isset($orderHeader['actAllocationDetails']))continue;
            foreach ($orderHeader['actAllocationDetails'] as $actAllocationDetail) {
                $logisticNumber = $actAllocationDetail['picktotraceid'];

                if (!$logisticNumber) continue;
                $orderPackage = $dataHandlerService->getKeyValue(['logistic_number' => $logisticNumber], $orderPackageMaps) ??
                    $dataHandlerService->getKeyValue(['logistic_number' => $orderHeader['soreference5']], $orderPackageMaps);

                if (!$orderPackage) continue;
                $orderPackageCommodityMap = [];
                if(!isset($orderPackage['commodities']))continue;
                foreach ($orderPackage['commodities'] as $orderPackageCommodity) {
                    $sku = $orderPackageCommodity['commodity']['sku'] ?? '';
                    if($sku === '')continue;
                    $orderPackageCommodityMap[$sku] = $orderPackageCommodity;
                }
                foreach ($actAllocationDetail['oracleDocOrderSerialNos'] as $oracleDocOrderSerialNo) {
                    $sku = $oracleDocOrderSerialNo['sku'];
                    $createParams = $this->getCreateModel($oracleDocOrderSerialNo, $orderPackageCommodityMap);
                    if (count($createParams) == 0) continue;
                    if (!isset($orderPackageSerialNumbers[$logisticNumber])) $orderPackageSerialNumbers[$logisticNumber] = [];
                    if (!isset($orderPackageSerialNumbers[$logisticNumber][$sku])) $orderPackageSerialNumbers[$logisticNumber][$sku] = [];
                    $orderPackageSerialNumbers[$logisticNumber][$sku][$createParams['serial_number']] = $createParams;
                }
            }
        }
        return $orderPackageSerialNumbers;
    }

    public function getCreateModel($oracleDocOrderSerialNo, $orderPackageCommodityMap)
    {
        $orderPackageCommodity = $orderPackageCommodityMap[$oracleDocOrderSerialNo['sku']] ?? null;
        if (!$orderPackageCommodity) return [];
        $created_At = Carbon::now()->format(Carbon::DEFAULT_TO_STRING_FORMAT);
        return [
            'order_package_commodity_id' => $orderPackageCommodity['id'],
            'serial_number' => $oracleDocOrderSerialNo['serialno'],
            'created_at' => $created_At,
            'updated_at' => $created_At
        ];
    }


}
