<?php

namespace App\Services;

use App\Commodity;
use App\CommodityBarcode;
use App\Services\common\DataHandlerService;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use App\Traits\ServiceAppAop;


class CommodityBarcodeService
{
    use ServiceAppAop;
    protected $modelClass=CommodityBarcode::class;
    public function getCommodities(array $codes, $owner_id){
        return CommodityBarcode::query()->whereHas('commodity',function ($query)use($owner_id){
            $query->where('owner_id',$owner_id);
        })->select('code','commodity_id')->whereIn('code',$codes)->get();
    }



    public function first(array $params){
        $query = CommodityBarcode::query();
        foreach ($params as $column => $value){
            $query->where($column,$value);
        }
        return $query->first();
    }

    public function get(array $params){
        $query = CommodityBarcode::query()->select('commodity_id','code');
        foreach ($params as $column => $values){
            if (is_array($values)) $query->whereIn($column,$values);
            else $query->where($column,$values);
        }
        return $query->get();
    }

    public function firstOrCreate(array $params, array $value = null)
    {
        if (!$value)$value = $params;
        return CommodityBarcode::query()->firstOrCreate($params,$value);
    }

    public function create(array $params)
    {
        return CommodityBarcode::query()->create($params);
    }

    /**
     * @param array $commoditiesAndBarcodesPacks 格式：[['commodity_id'=>id, barcodes=[str,str,str]], [......]]
     * @return bool
     */
    public function insertMany_onCommodities(array $commoditiesAndBarcodesPacks)
    {
        $commodityBarcodes=[];
        foreach ($commoditiesAndBarcodesPacks as $commoditiesAndBarcodesPack){
            $commodity_id=$commoditiesAndBarcodesPack['commodity_id'];
            $barcodes=$commoditiesAndBarcodesPack['barcodes'];
            foreach ($barcodes as $barcode){
                $commodityBarcodes[]=[
                    'commodity_id'=>$commodity_id,
                    'code'=>$barcode,
                ];
            }
        }
        if(empty($commodityBarcodes))return false;
        return CommodityBarcode::query()->insert($commodityBarcodes);
    }
    public function destroyCollections(Collection $commodityBarcodes)
    {
        $ids=$commodityBarcodes->map(function($commodityBarcode){
            return $commodityBarcode['id'];
        });
        return CommodityBarcode::destroy($ids);
    }

    public function createBarcodeByWms($bas_skus)
    {

        if (count($bas_skus)<1)return;
        $owner_sku_map = [];
        $sku = [];
        $bas_skus->each(function ($addBasSku) use (&$owner_sku_map, &$sku) {
            if (!empty($addBasSku['customerid']) && !empty($addBasSku['sku'])) {
                $key = "owner_code_{$addBasSku['customerid']}_sku_{$addBasSku['sku']}";
                $owner_sku_map[$key] = ['owner_code' => $addBasSku['customerid'], 'sku' => $addBasSku['sku']];
                $sku[] = $addBasSku['sku'];
            }
        });
        /**
         * @var OwnerService $ownerService
         * @var DataHandlerService $dataHandlerService
         */
        $ownerService = app(OwnerService::class);
        $dataHandlerService=app(DataHandlerService::class);
        $owner_codes = (function () use ($owner_sku_map) {
            $owner_codes = [];
            if (count($owner_sku_map) == 0) return $owner_codes;
            foreach ($owner_sku_map as $item) {
                $owner_codes[$item['owner_code']] = $item['owner_code'];
            }
            return $owner_codes;
        })();
        $owner_map = (function () use ($ownerService, $owner_codes) {
            $owners = $ownerService->getOwnerByCodes($owner_codes);
            $map = [];
            $owners->each(function ($owner) use (&$map) {
                $map[$owner['code']] = $owner['id'];
            });
            return $map;
        })();
        $owner_id = (function () use ($ownerService, $owner_codes) {
            $owners = $ownerService->getOwnerByCodes($owner_codes);
            $map = [];
            $owners->each(function ($owner) use (&$map) {
                $map[] = $owner['id'];
            });
            return $map;
        })();
        $commodityBarcodes=$this->getByWms($bas_skus);
        $commodityBarcodes_map=$dataHandlerService->dataHeader(['commodity_id','code'], $commodityBarcodes);
        $insert_params=$this->getInsertParams($bas_skus, $commodityBarcodes_map,$owner_id,$sku,$owner_map);
        if (count($insert_params)>0) {
            foreach (array_chunk($insert_params, 1000) as $item) {
                try {
                    $bool = $this->insert($item);
                    if ($bool) {
                        app('LogService')->log(__METHOD__, __FUNCTION__, "批量添加 CommodityBarcode Success " . count($item) . ' || ' . json_encode($item));
                    } else app('LogService')->log(__METHOD__, __FUNCTION__, "批量添加 CommodityBarcode FAILED " . ' || ' . json_encode($item));
                } catch (\Exception $e) {
                    app('LogService')->log(__METHOD__, __FUNCTION__, "批量添加 CommodityBarcode ERROR " . ' || ' . json_encode($insert_params) . ' || ' . json_encode($e->getMessage()) . ' || ' . json_encode($e->getTraceAsString()));
                }
            }
        }

    }
    public function getInsertParams($bas_skus, $commodityBarcodes_map,$owner_id,$sku,$owner_map)
    {
        /**
         * @var DataHandlerService $dataHandlerService
         */
        $dataHandlerService = app(DataHandlerService::class);
        $commodities = Commodity::query()
            ->whereIn('owner_id', array_unique($owner_id))
            ->whereIn('sku', array_unique($sku))
            ->get();
        $commodities_map = $dataHandlerService->dataHeader(['owner_id','sku'], $commodities);
        $params = [];
        foreach ($bas_skus as $bas_sku) {
            $commodity = Cache::get("owner_code_{$bas_sku['customerid']}_sku_{$bas_sku['sku']}");
            if (!$commodity) {
                $commodity = $dataHandlerService->getKeyValue(['owner_id' => $owner_map[$bas_sku['customerid']], 'sku' => $bas_sku['sku']], $commodities_map);
                if (!$commodity) continue;
            }
            if ($bas_sku->alternate_sku1){
                $commodityBarcode1 = $dataHandlerService->getKeyValue(['commodity_id' => $commodity->id, 'code' => $bas_sku->alternate_sku1], $commodityBarcodes_map);
                if(!$commodityBarcode1) $params[]=[
                    'code'=>$bas_sku->alternate_sku1,
                    'commodity_id' => $commodity->id,
                    'created_at'=>$bas_sku->addtime,
                    'updated_at'=>$bas_sku->edittime,
                ];
            }
            if ($bas_sku->alternate_sku2){
                $commodityBarcode2 = $dataHandlerService->getKeyValue(['commodity_id' => $commodity->id, 'code' => $bas_sku->alternate_sku2], $commodityBarcodes_map);
                if(!$commodityBarcode2) $params[]=[
                    'code'=>$bas_sku->alternate_sku2,
                    'commodity_id' => $commodity->id,
                    'created_at'=>$bas_sku->addtime,
                    'updated_at'=>$bas_sku->edittime,
                ];
            }
            if ($bas_sku->alternate_sku3){
                $commodityBarcode3 = $dataHandlerService->getKeyValue(['commodity_id' => $commodity->id, 'code' => $bas_sku->alternate_sku3], $commodityBarcodes_map);
                if(!$commodityBarcode3) $params[]=[
                    'code'=>$bas_sku->alternate_sku3,
                    'commodity_id' => $commodity->id,
                    'created_at'=>$bas_sku->addtime,
                    'updated_at'=>$bas_sku->edittime,
                ];
            }
        }
        return $params;
    }
    public function updateBarcodeByWms($bas_skus)
    {
        if (!$bas_skus || $bas_skus->count() == 0) return;
        $this->createBarcodeByWms($bas_skus);
        $owner_sku_map = [];
        $sku = [];
        $bas_skus->each(function ($addBasSku) use (&$owner_sku_map, &$sku) {
            if (!empty($addBasSku['customerid']) && !empty($addBasSku['sku'])) {
                $key = "owner_code_{$addBasSku['customerid']}_sku_{$addBasSku['sku']}";
                $owner_sku_map[$key] = ['owner_code' => $addBasSku['customerid'], 'sku' => $addBasSku['sku']];
                $sku[] = $addBasSku['sku'];
            }
        });
        /**
         * @var OwnerService $ownerService
         * @var DataHandlerService $dataHandlerService
         */
        $ownerService = app(OwnerService::class);
        $dataHandlerService=app(DataHandlerService::class);
        $owner_codes = (function () use ($owner_sku_map) {
            $owner_codes = [];
            if (count($owner_sku_map) == 0) return $owner_codes;
            foreach ($owner_sku_map as $item) {
                $owner_codes[$item['owner_code']] = $item['owner_code'];
            }
            return $owner_codes;
        })();
        $owner_map = (function () use ($ownerService, $owner_codes) {
            $owners = $ownerService->getOwnerByCodes($owner_codes);
            $map = [];
            $owners->each(function ($owner) use (&$map) {
                $map[$owner['id']] = $owner['code'];
            });
            return $map;
        })();
        $commodityBarcodes=$this->getByWms($bas_skus);
        $bas_skus_map_one = $dataHandlerService->dataHeader(['customerid', 'sku','alternate_sku1',], $bas_skus);
        $bas_skus_map_two = $dataHandlerService->dataHeader(['customerid', 'sku','alternate_sku2',], $bas_skus);
        $bas_skus_map_three = $dataHandlerService->dataHeader(['customerid', 'sku','alternate_sku3',], $bas_skus);
        $delete_Items = [];
        foreach ($commodityBarcodes as $commodityBarcode) {
            $bas_sku_one = $dataHandlerService
                ->getKeyValue(['customerid'=>$owner_map[$commodityBarcode->commodity['owner_id']],'sku'=>$commodityBarcode->commodity['sku'],'alternate_sku1'=>$commodityBarcode->code], $bas_skus_map_one);
            if ($bas_sku_one) continue;
            $bas_sku_two = $dataHandlerService
                ->getKeyValue(['customerid'=>$owner_map[$commodityBarcode->commodity['owner_id']],'sku'=>$commodityBarcode->commodity['sku'],'alternate_sku2'=>$commodityBarcode->code], $bas_skus_map_two);
            if ($bas_sku_two) continue;
            $bas_sku_three = $dataHandlerService
                ->getKeyValue(['customerid'=>$owner_map[$commodityBarcode->commodity['owner_id']],'sku'=>$commodityBarcode->commodity['sku'],'alternate_sku3'=>$commodityBarcode->code], $bas_skus_map_three);
            if ($bas_sku_three) continue;
            if (!$bas_sku_one&& !$bas_sku_two&& !$bas_sku_three){
                $delete_Items[]=$commodityBarcode;
            }
        }
        if (count($delete_Items)>0) $this->deleteCommodityBarcode($delete_Items);
    }
    public function getByWms($bas_skus)
    {
        if (!$bas_skus) return null;
        $owner_sku_map = [];
        $sku = [];
        $bas_skus->each(function ($addBasSku) use (&$owner_sku_map, &$sku) {
            if (!empty($addBasSku['customerid']) && !empty($addBasSku['sku'])) {
                $key = "owner_code_{$addBasSku['customerid']}_sku_{$addBasSku['sku']}";
                $owner_sku_map[$key] = ['owner_code' => $addBasSku['customerid'], 'sku' => $addBasSku['sku']];
                $sku[] = $addBasSku['sku'];
            }
        });
        /**
         * @var OwnerService $ownerService
         */
        $ownerService = app(OwnerService::class);
        $owner_codes = (function () use ($owner_sku_map) {
            $owner_codes = [];
            if (count($owner_sku_map) == 0) return $owner_codes;
            foreach ($owner_sku_map as $item) {
                $owner_codes[$item['owner_code']] = $item['owner_code'];
            }
            return $owner_codes;
        })();
        $owner_id = (function () use ($ownerService, $owner_codes) {
            $owners = $ownerService->getOwnerByCodes($owner_codes);
            $map = [];
            $owners->each(function ($owner) use (&$map) {
                $map[] = $owner['id'];
            });
            return $map;
        })();
        return CommodityBarcode::query()->with('commodity')->whereIn('commodity_id', function ($query) use ($owner_id,$sku) {
            $query->from('commodities')->select('id')->whereIn('owner_id', array_unique($owner_id))->whereIn('sku',array_unique($sku));
        })->get();
    }
    public function deleteCommodityBarcode(array $delete_params)
    {
        $itemIds = [];
        foreach ($delete_params as $item) {
            array_push($itemIds, $item->id);
        }
        try {
            CommodityBarcode::query()->whereIn('id', $itemIds)->delete();
            LogService::log(__METHOD__, __FUNCTION__, '删除多余CommodityBarcode ' . count($delete_params) . json_encode($delete_params), null);
        } catch (\Exception $e) {
            LogService::log(__METHOD__, __FUNCTION__, '删除多余CommodityBarcode error' . count($delete_params) . json_encode($delete_params) . $e->getMessage() . $e->getTraceAsString(), null);
        }
    }
}
