<?php


namespace App\Services;


use App\Batch;
use App\OrderCommodity;
use App\StationTask;
use App\StationTaskBatch;
use App\StationTaskCommodity;
use App\StationTaskMaterialBox;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use App\Traits\ServiceAppAop;


class StationTaskCommodityService
{
    use ServiceAppAop;
    protected $modelClass=StationTaskCommodity::class;
    /** @var StationService $stationService */
    private $stationService;
    /** @var StationTypeService $stationTypeService */
    private $stationTypeService;
    /** @var StationTaskService $stationTaskService */
    private $stationTaskService;
    /** @var MaterialBoxService $materialBoxService */
    private $materialBoxService;
    /** @var StationTaskBatchService $stationTaskBatchService */
    private $stationTaskBatchService;
    public function __construct(){
        $this->stationService=null;
        $this->stationTypeService=null;
        $this->stationTaskService=null;
        $this->materialBoxService=null;
    }

    function get(array $kvPairs){
        ksort($kvPairs);
        return Cache::remember('stationTaskChild_'.md5(json_encode($kvPairs)), config('cache.expirations.oftenChange'), function ()use($kvPairs) {
            $query = StationTaskCommodity::query();
            foreach ($kvPairs as $column => $value){
                if (is_array($value))$query->whereIn($column,$value);
                else $query->where($column,$value);
            }
            return $query->get();
        });
    }

    function createByBatches(Collection $batches,Collection $stationTasks_toAttach): Collection
    {
        $this->instant($this->stationTaskService,'StationTaskService');
        $stationTaskCommodities_listByBatch=new Collection();
        $stationTaskCommodities=new Collection();
        foreach ($batches as $batch){
            $taskCommodities = $this->createByBatch($batch);
            $stationTaskCommodities= $stationTaskCommodities->merge($taskCommodities);
            $stationTaskCommodities_listByBatch->push($taskCommodities);
        }
//        $stationTaskCommodities=$this->getAndAttachIds($stationTaskCommodities);
        $this->stationTaskService->registerSubTasks(
            $stationTasks_toAttach,
            $stationTaskCommodities_listByBatch);
        return $stationTaskCommodities;

    }



//    function getAndAttachIds($taskCommodities): Collection
//    {
//        $md5=is_array($taskCommodities)
//            ?$md5=md5(json_encode($taskCommodities)):null;
//
//        return Cache::remember(
//            'StationTaskCommodity_'.$md5??md5(json_encode($taskCommodities->toArray()))
//            ,config('cache.expirations.rarelyChange')
//            ,function()use($taskCommodities){
//                $a=data_get($taskCommodities,'*.status');
//                $a2=data_get($taskCommodities,'*.station_task_batch_id');
//                $a3=data_get($taskCommodities,'*.commodity_id');
//                $a4=StationTaskCommodity::query()
//                    ->whereIn('status',data_get($taskCommodities,'*.status'))
//                    ->whereIn('station_task_batch_id',data_get($taskCommodities,'*.station_task_batch_id'))
//                    ->whereIn('commodity_id',data_get($taskCommodities,'*.commodity_id'))
//                    ->get();
//                $a5=1;
//            return StationTaskCommodity::query()
//                ->whereIn('status',data_get($taskCommodities,'*.status'))
//                ->whereIn('station_task_batch_id',data_get($taskCommodities,'*.station_task_batch_id'))
//                ->whereIn('commodity_id',data_get($taskCommodities,'*.commodity_id'))
//                ->get();
//        });
//    }

    function createByBatch(Batch $batch): Collection
    {
        $this->instant($this->stationTypeService,'StationTypeService');
        $this->instant($this->stationService,'StationService');
        $this->instant($this->materialBoxService,'MaterialBoxService');
        $this->instant($this->stationTaskBatchService,'StationTaskBatchService');
        $stationTaskCommodities_toCreate=new Collection();
        $order_ids=data_get($batch['orders'],'*.id');
        $orderCommodities=OrderCommodity::query()->with('orderBin')->whereIn('order_id',$order_ids)->get();
        $stationTaskBatch=$this->stationTaskBatchService->get(['batch_id'=>$batch['id']])->first();
        foreach ($orderCommodities as $orderCommodity){
            $stationType=$this->stationTypeService->getForCommodity();
            $station=$this->stationService->getStation_byType($stationType['name']);
            $materialBox=$this->materialBoxService->firstOrCreate(['code' => $orderCommodity['location']]);
            $stationTaskMaterialBoxId=StationTaskMaterialBox::query()->where('station_task_batch_id',$batch['id'])->where('material_box_id',$materialBox['id'])->get('id');
            $stationTaskCommodities_toCreate->push(
                new StationTaskCommodity([
                    'station_id'=>$station['id'],
                    'material_box_id'=>$materialBox['id'],
                    'material_box_position'=>$orderCommodity['material_box_position'],
                    'commodity_id'=>$orderCommodity['commodity_id'],
                    'amount'=>$orderCommodity['amount'],
                    'bin_number'=>$orderCommodity['orderBin']['number']??'',
                    'order_id'=>$orderCommodity['order_id'],
                    'station_task_batch_id'=>$stationTaskBatch['id'],
                    'station_task_material_box_id'=>$stationTaskMaterialBoxId,
                    'status'=>'待处理',
                ])
            );
        }
        return $this->insert($stationTaskCommodities_toCreate->toArray(),true);
    }

    function markProcessing($stationTaskCommodity_orCollection)
    {
        $stationTaskCommodities =
            (function()use($stationTaskCommodity_orCollection){
                if (get_class($stationTaskCommodity_orCollection)==StationTaskCommodity::class){
                    return collect([$stationTaskCommodity_orCollection]);
                }
                return collect($stationTaskCommodity_orCollection);
            })();

        $stationTaskCommodities_grouped=
            ($按时间从前往后排出顺序=function ()use(&$stationTaskCommodities){
                return $stationTaskCommodities
                    ->sortBy('id')
                    ->groupBy('station_task_batch_id');
            })();

        $stationTaskCommodities_grouped->each(function(&$groupByBatch){
            ($标记本波次内是处理中或处理队列=function()use(&$groupByBatch){
                $stationId=$groupByBatch[0]['station_id'];
                $processingIds=data_get($this->getProcessings_byStationId($stationId),'*.id')??[];
                $groupByBatch->each(function(&$stationTaskCommodity)use($processingIds){
                    if(in_array($stationTaskCommodity['id'],$processingIds))
                        $stationTaskCommodity['status']='处理中';
                    else
                        $stationTaskCommodity['status']='处理队列';
                });
                if(count($processingIds)==0){
                    foreach($groupByBatch as &$stationTaskCommodity){
                        if($stationTaskCommodity['material_box_id']==$groupByBatch[0]['material_box_id']){
                            $stationTaskCommodity['status']='处理中';
                        }
                    }
                }
            })();
        });
        ($持久化处理队列的记录=function()use(&$stationTaskCommodities_grouped){
            $toArray = $stationTaskCommodities_grouped->collapse();
            $toQueue=$toArray->where('status','处理队列');
            $toProcess=$toArray->where('status','处理中');
            $ids_toQueue_toUpdate = data_get($toQueue, '*.id');
            if(count($ids_toQueue_toUpdate))
                StationTaskCommodity::query()->whereIn('id',$ids_toQueue_toUpdate)->update(['status'=>'处理队列']);
            $ids_toProcess_toUpdate = data_get($toProcess, '*.id');
            if(count($ids_toProcess_toUpdate))
                StationTaskCommodity::query()->whereIn('id',$ids_toProcess_toUpdate)->update(['status'=>'处理中']);
        })();

    }

    function getProcessings_byStationId($stationTaskBatch_id)
    {
        //这里不好用缓存，因为更新会非常快
        return StationTaskCommodity::query()
            ->where('station_id',$stationTaskBatch_id)
            ->where('status','处理中')
            ->get();
    }


    function markProcessed(Collection $stationTaskCommodities){
        StationTaskCommodity::query()
            ->whereIn('id',data_get($stationTaskCommodities,'*.id'))
            ->update(['status'=>'完成']);
//        $station_id=$stationTaskCommodities[0]['station_id'];
//        $stationTaskCommodities_next=StationTaskCommodity::query()
//            ->where('station_id',$station_id)
//            ->where('status','处理队列')
//            ->orderBy('updated_at')
//            ->get();
//        if($stationTaskCommodities_next->isNotEmpty()){
//            $stationTaskCommodities_toUpdate=$stationTaskCommodities_next->where(
//                'material_box_id', $stationTaskCommodities_next->first()['material_box_id']);
//            StationTaskCommodity::query()
//                ->whereIn('id',data_get($stationTaskCommodities_toUpdate,'*.id'))
//                ->update(['status'=>'处理中']);
//        }
    }
}
