<?php

namespace App\Services;

use App\Batch;
use App\Exceptions\ErrorException;
use App\Jobs\BatchTaskJob;
use App\OracleActAllocationDetails;
use App\Order;
use App\OrderCommodity;
use App\Owner;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use App\Traits\ServiceAppAop;


class BatchService
{
    use ServiceAppAop;
    protected $modelClass=Batch::class;
    /** @var StationTaskBatchService $stationTaskBatchService */
    private $stationTaskBatchService;
    /** @var StationRuleBatchService $stationRuleBatchService */
    private $stationRuleBatchService;
    /** @var StationTaskMaterialBoxService $stationTaskMaterialBoxService */
    private $stationTaskMaterialBoxService;
    /** @var StationTaskCommodityService $stationTaskCommodityService */
    private $stationTaskCommodityService;
    /** @var StationTaskService $stationTaskService */
    private $stationTaskService;
    public function __construct(){
        $this->stationTaskBatchService=null;
        $this->stationRuleBatchService=null;
        $this->stationTaskMaterialBoxService=null;
        $this->stationTaskCommodityService=null;
        $this->stationTaskService=null;
    }

    public function get(array $params)
    {
        $query = Batch::query();
        foreach ($params as $column=>$param){
            if (is_array($param))$query->whereIn($column,$param);
            else $query->where($column,$param);
        }
        return $query->get();
    }




    public function updateWhereIn($key,$values,$updateKeyValues){
        Batch::query()->whereIn($key,$values)->update($updateKeyValues);
    }

    /**
     * 为波次附加任务，已附加的重复任务不影响
     * @param $batches
     * @throws Exception
     */
    public function assignTasks($batches)
    {
        try{
            LogService::log(__METHOD__,'assignTasks','波次任务分配1：'.json_encode($batches));
            $batches = collect($batches);

            $this->instant($this->stationTaskBatchService,'StationTaskBatchService');
            $this->instant($this->stationRuleBatchService,'StationRuleBatchService');
            $this->instant($this->stationTaskService,'StationTaskService');
            $this->instant($this->stationTaskCommodityService,'StationTaskCommodityService');
            $this->instant($this->stationTaskMaterialBoxService,'StationTaskMaterialBoxService');

            $stationTaskBatches=null;
            $batches_shouldProcess = $this->stationRuleBatchService->getBatches_shouldProcess($batches); //按规则过滤需要的波次
            if($batches_shouldProcess->isEmpty()) return;
            LogService::log(__METHOD__,'assignTasks','波次任务分配2：'.json_encode($batches));
            $stationTaskMaterialBoxes_occupied = $this->stationTaskMaterialBoxService->getOccupied_byBatches($batches_shouldProcess); //按规则过滤需要的波次
            LogService::log(__METHOD__,'assignTasks','波次任务分配2b：'.json_encode($batches));
            if($stationTaskMaterialBoxes_occupied->isNotEmpty()) {
                foreach ($batches_shouldProcess as $batch){
                    Cache::tags(['波次防重叠'.$batch['id']])->flush();
                }
                BatchTaskJob::dispatch($batches_shouldProcess)
                    ->delay(now()->addMinutes(1));    //因为料箱被占用了，所以将任务推迟1分钟后尝试
                return;
            }
            DB::transaction(function ()use($batches,&$stationTaskBatches,&$batches_shouldProcess){
                $stationTasks =  $this->stationTaskService->create($batches_shouldProcess->count()); //生成总任务
                LogService::log(__METHOD__,'assignTasks','波次任务分配3：'.json_encode($batches));
                $stationTaskBatches=$this->stationTaskBatchService->createByBatches($batches_shouldProcess,$stationTasks); //注册波次任务
                LogService::log(__METHOD__,'assignTasks','波次任务分配4：'.json_encode($batches));
                $stationTaskMaterialBoxes=$this->stationTaskMaterialBoxService->createByBatches($batches_shouldProcess,$stationTasks); //注册料箱任务
                LogService::log(__METHOD__,'assignTasks','波次任务分配5：'.json_encode($stationTaskMaterialBoxes).json_encode($batches));
                $stationTaskCommodities=$this->stationTaskCommodityService->createByBatches($batches_shouldProcess,$stationTasks); //注册商品任务
                LogService::log(__METHOD__,'assignTasks','波次任务分配6：'.json_encode($batches));
            });

//            $ran=$this->stationTaskBatchService->runMany($stationTaskBatches);//执行波次任务
            LogService::log(__METHOD__,'assignTasks','波次任务分配7：'.json_encode($batches));
        }catch(Exception $e){
            $batchesJson='';
            foreach ($batches as $batch){
                $batchesJson.=json_encode($batch);
                Cache::tags(['波次防重叠'.$batch['id']])->flush();
            }
            throw new ErrorException('注册任务失败: '. $batchesJson . $e->getMessage().json_encode($e->getTrace()));
        }
    }

    public function getBatchByCodes($codes)
    {
        if(empty($codes))return collect();
        if(count($codes) == 0)return collect();
        return Batch::query()->whereIn('code',$codes)->get();
    }


    /**
     * 检查批次订单信息,存在库位异常 直接删除所有所属商品 重新拉取
     *
     * @param Collection|array $batches
     */
    public function checkBatchOrderInfo($batches)
    {
        if (!is_array($batches))$batches = $batches->toArray();
        $ids = array_column($batches,"id");
        $batches = Batch::query()->whereIn("id",$ids)->with("orders.orderCommodities")->get();
        foreach ($batches as $batch){
            if (!$batch->orders)continue;
            foreach ($batch->orders as $order){
                if (!$order->orderCommodities)app("OrderService")->notExistToRecover($order);
                else{
                    $mark = false;
                    foreach ($order->orderCommodities as $orderCommodity){
                        if (!$orderCommodity->location){
                            $mark = true;break;
                        }
                    }
                    if ($mark){
                        OrderCommodity::query()->where("order_id",$order->id)->delete();
                        app("OrderService")->notExistToRecover($order);
                    }
                }
            }
        }
    }
}
