<?php

namespace App\Http\Controllers;

use App\Imports\StoreCheckingReceiveSheets;
use App\Services\CommodityService;
use App\Services\LogService;
use App\Services\OracleDocAsnDetailService;
use App\Services\StoreCheckingReceiveService;
use App\StoreCheckingReceive;
use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Http;
use Maatwebsite\Excel\Facades\Excel;

class StoreCheckingReceiveController extends Controller
{
    public function mission(Request $request){
        if(!Gate::allows('入库管理-盘收一体-盘收-查看')){ return view('store/index');  }
        /** @var StoreCheckingReceiveService $service */
        $service = app('StoreCheckingReceiveService');

        $params = $request->input();
        $storeCheckingReceives = $service->paginate($params);
        $owners = app('OwnerService')->getIntersectPermitting();
        return view('store.checkingReceive.mission',compact('storeCheckingReceives','params','owners'));
    }

    public function import(Request $request){
        if(!Gate::allows('入库管理-盘收一体-盘收-编辑')){ return ['success'=>false, 'data'=>'无权操作！'];  }
        $fileSuffix=$request->file('file')->getClientOriginalExtension();
        if ($fileSuffix != 'xlsx' && $fileSuffix != 'xls' && $fileSuffix != 'csv')
            return ['success'=>false,'data'=>'不支持该文件类型'];
        ini_set('max_execution_time',2500);
        ini_set('memory_limit','1526M');
        $fileSuffix = ucwords($fileSuffix);
        Excel::import(new StoreCheckingReceiveSheets(),$request->file('file')->path(),null,$fileSuffix);
        if (Cache::has('storeCheckingReceive')){
            return Cache::pull('storeCheckingReceive');
        }
        return ["success"=>false, "data"=>"读取导入文件错误"];
    }

    public function show($id,Request $request){
        if(!Gate::allows('入库管理-盘收一体-盘收-查看')){ return redirect(url('/'));  }
        /** @var StoreCheckingReceiveService $service */
        $service = app('StoreCheckingReceiveService');
        $withs = ['owner','storeCheckingReceiveItems'=>function($query){
                    $query->with(['commodity'=>function($builder) {
                        $builder->with('barcodes');
                    }]);
                }];
        $storeCheckingReceive = $service->find($id,$withs);
        $is_show = $request->is_show ?? true;

        if ($storeCheckingReceive->owner ?? false){
            $commodityController = new CommodityController();
            $sku = [];
            foreach ($storeCheckingReceive->storeCheckingReceiveItems as $item){
                $sku[] = $item->commodity->sku;
            }
            $commodityController->syncOwnerCommodities($storeCheckingReceive->owner->id, $storeCheckingReceive->owner->code, $sku);
        }

        return view('store.checkingReceive.show',compact('storeCheckingReceive','is_show'));
    }

    public function insertItem(Request $request){
        if(!Gate::allows('入库管理-盘收一体-盘收-编辑')){ return ['success'=>false, 'data'=>'无权操作！'];  }
        $mission_id = $request->mission_id ?? false;
        $goods = $request->goods ?? false;
        if (!($goods["amount"] ?? false))$goods["amount"] = 1;
        if (!$mission_id || !$goods)return ['success'=>false, 'data'=>'参数传递错误！'];
        $withs = ['owner','storeCheckingReceiveItems'=>function($query){
            $query->with(['commodity'=>function($builder) {
                $builder->with('barcodes');
            }]);
        }];
        $storeCheckingReceive = app('StoreCheckingReceiveService')->find($mission_id,$withs);
        if (!$storeCheckingReceive)return ['success'=>false, 'data'=>'盘收任务不存在'];
        if ($storeCheckingReceive->status == '已收货')return ['success'=>false, 'data'=>'盘收任务已结束'];

        $storeCheckingReceiveItem = null;
        $is_receive_diff = "否";
        $is_asn_diff = "否";
        $is_inventory_complete = true;
        foreach ($storeCheckingReceive->storeCheckingReceiveItems as $item){
            if (!$item->commodity)continue;
            if (count($item->commodity->barcodes) < 1)continue;
            foreach ($item->commodity->barcodes as $barcode){
                if ($barcode->code == $goods['barcode']){
                    if ($goods['batch_number'] == $item->batch_code &&
                        $goods['produce_date'] == $item->produced_at &&
                        $goods['unique_code'] == $item->unique_code &&
                        $goods['valid_date'] == $item->invalid_at){
                        $storeCheckingReceiveItem = $item;
                        break;
                    }
                }
            }
            if ($storeCheckingReceiveItem)continue;
            if ($item->imported_diff_amount > 0)$is_receive_diff = "是";
            if (!$item->counted_amount)$is_inventory_complete = false;
        }

        if ($storeCheckingReceiveItem){
            $counted_amount = $storeCheckingReceiveItem->counted_amount+$goods['amount'];
            $params = ['counted_amount'=>$counted_amount];
            if (!$storeCheckingReceiveItem->imported_amount){
                $params['imported_amount'] = 0;
                $params['imported_diff_amount'] = $counted_amount;
            }else $params['imported_diff_amount'] = $counted_amount-$storeCheckingReceiveItem->imported_amount;
            if ($storeCheckingReceiveItem->asn_amount)$params['asn_diff_amount'] = $counted_amount-$storeCheckingReceiveItem->asn_amount;
            if (!$storeCheckingReceiveItem->bin_number && $goods['bin_number'])$params['bin_number'] = $goods['bin_number'];

            if (isset($params['imported_diff_amount']) && $params['imported_diff_amount'] > 0)$is_receive_diff = "是";
            if (isset($params['asn_diff_amount']) && $params['asn_diff_amount'] > 0)$is_asn_diff = "是";
            $item = app('StoreCheckingReceiveItemService')->updateFind($storeCheckingReceiveItem,$params);
            app('LogService')->log(__METHOD__,"清点数量",json_encode($item,JSON_UNESCAPED_UNICODE));

            switch ($storeCheckingReceive->status){
                case '已导入':
                    $SCR = app('StoreCheckingReceiveService')->updateFind($storeCheckingReceive,['status'=>'清点中']);
                    app('LogService')->log(__METHOD__,"修改盘收任务状态为清点中",json_encode($SCR,JSON_UNESCAPED_UNICODE));
                    break;
                case '清点中':
                    $res = [];
                    if ($is_inventory_complete){
                        $res['status']='已清点';
                    }
                    //差异存在时 判断差异是否变化，变化则更新，差异不存在时 判断差异是否存在 存在则更新
                    if (($storeCheckingReceive->is_receive_diff && $storeCheckingReceive->is_receive_diff != $is_receive_diff)
                        || (!$storeCheckingReceive->is_receive_diff && isset($params['imported_diff_amount'])))
                        $res['is_receive_diff'] = $is_receive_diff;
                    if (($storeCheckingReceive->is_asn_diff && $storeCheckingReceive->is_asn_diff != $is_asn_diff)
                        || (!$storeCheckingReceive->is_asn_diff && isset($params['asn_diff_amount'])))
                        $res['is_receive_diff'] = $is_receive_diff;
                    if (count($res) > 0){
                        $SCR = app('StoreCheckingReceiveService')->updateFind($storeCheckingReceive,$res);
                        app('LogService')->log(__METHOD__,"修改盘收任务",json_encode($SCR,JSON_UNESCAPED_UNICODE));
                    }
                    break;
            }
            return ['success'=>true, 'type'=>"update", 'data'=>$item];
        }
        $commodity = app('CommodityService')->ownerBarcodeSeekCommodityFirst(['id'=>$storeCheckingReceive->owner_id], $goods['barcode']);
        if (!$commodity) {
            if (!$storeCheckingReceive->owner) return ['success'=>false, 'data'=>'未找到货主'];
            $basSku = app('OracleBasSkuService')->first(['customerid'=>$storeCheckingReceive->owner->code, "barcode"=>$goods['barcode']]);
            if ($basSku){
                $commodity = app('CommodityService')->firstOrCreate(['owner_id'=>$storeCheckingReceive->owner_id, 'sku'=>$basSku->sku],[
                    "name"=>$basSku->descr_c,
                    "sku"=>$basSku->sku,
                    "owner_id"=>$storeCheckingReceive->owner_id,
                    'length' => $basSku->skulength,
                    'width' => $basSku->skuwidth,
                    'height' => $basSku->skuhigh,
                    'volumn' => $basSku->cube
                ]);
                if ($commodity) app('CommodityBarcodeService')->firstOrCreate(['commodity_id'=>$commodity->id, 'code'=>$goods['barcode']]);
            }else{
                $commodity = app('CommodityService')->createTemporaryCommodity([
                    "sku"=>$goods['barcode'],
                    "owner_id"=>$storeCheckingReceive->owner_id,
                ]);
                app('CommodityBarcodeService')->create([
                    "commodity_id"=>$commodity->id,
                    "code" => $goods['barcode'],
                ]);
            }
        };
        $item = app('StoreCheckingReceiveItemService')->create([
            'store_checking_receive_id' => $mission_id,
            'bin_number' => $goods['bin_number'],
            'commodity_id' => $commodity->id,
            'imported_amount' => 0,
            'imported_diff_amount' => $goods['amount'],
            'produced_at' => $goods['produce_date'],
            'invalid_at' => $goods['valid_date'],
            'batch_code' => $goods['batch_number'],
            'unique_code' => $goods['unique_code'],
            'counted_amount' => $goods['amount'],
        ]);
        $item->load(['commodity'=>function($query){
            $query->with('barcodes');
        }]);
        switch ($storeCheckingReceive->status){
            case '已导入':
                $SCR = app('StoreCheckingReceiveService')->updateFind($storeCheckingReceive,['status'=>'清点中']);
                app('LogService')->log(__METHOD__,"修改盘收任务状态为清点中",json_encode($SCR,JSON_UNESCAPED_UNICODE));
                break;
            case '清点中':
                $res = [];
                if ($is_inventory_complete){
                    $res['status']='已清点';
                }
                //差异存在时 判断差异是否变化，变化则更新，差异不存在时 判断差异是否存在 存在则更新
                if ($is_receive_diff == "否")$is_receive_diff = $item->imported_diff_amount>0 ? "是" : "否";
                if ($storeCheckingReceive->is_receive_diff != $is_receive_diff)
                    $res['is_receive_diff'] = $is_receive_diff;
                if ($storeCheckingReceive->is_asn_diff && ($storeCheckingReceive->is_asn_diff != $is_asn_diff))
                    $res['is_receive_diff'] = $is_receive_diff;
                if (count($res) > 0){
                    $SCR = app('StoreCheckingReceiveService')->updateFind($storeCheckingReceive,$res);
                    app('LogService')->log(__METHOD__,"修改盘收任务",json_encode($SCR,JSON_UNESCAPED_UNICODE));
                }
                break;
        }
        return ['success'=>true, 'type'=>'create', 'data'=>$item];
    }

    public function export(Request $request){
        if(!Gate::allows('入库管理-盘收一体-盘收-查看')){ return redirect(url('/'));  }
        $id = $request->mission_id ?? false;
        $withs = ['owner','storeCheckingReceiveItems'=>function($query){
            $query->with(['commodity'=>function($builder) {
                $builder->with('barcodes');
            }]);
        }];
        $storeCheckingReceive = app('StoreCheckingReceiveService')->find($id,$withs);

        if (!$storeCheckingReceive) new \Exception('盘收任务不存在');

        $row = ['ID','格口号','商品名','商品条码','导入数量','实盘数量','ASN数量','导入差异数','ASN差异数','生产日期','有效日期','批次号','唯一码'];
        $list = [];
        foreach ($storeCheckingReceive->storeCheckingReceiveItems as $item){
            $code = '';
            foreach ($item->commodity ? $item->commodity->barcodes : [] as $barcode){
                $code .= $barcode->code;
            }
            $list[] = [
                $item->id,
                $item->bin_number,
                $item->commodity ? $item->commodity->name : '',
                $code,
                $item->imported_amount,
                $item->counted_amount,
                $item->asn_amount,
                $item->imported_diff_amount,
                $item->asn_diff_amount,
                $item->produced_at,
                $item->invalid_at,
                $item->batch_code,
                $item->unique_code,
            ];
        }
        $post = Http::post(config('go.export.url'),['type'=>'base','data'=>json_encode([
            'row'=>$row,'list'=>$list
        ],JSON_UNESCAPED_UNICODE)]);
        if ($post->status() == 500){
            throw new Exception($post->header("Msg"));
        }
        return response($post,200, [
            "Content-type"=>"application/octet-stream",
            "Content-Disposition"=>"attachment; filename=盘收任务详情-".date('ymdHis').'.xlsx',
        ]);
    }

    public function resetAmount(Request $request){
        if(!Gate::allows('入库管理-盘收一体-盘收-编辑')){ return ['success'=>false, 'data'=>'无权操作!'];  }
        $id = $request->mission_id ?? false;
        if (!$id) return ['success'=>false, 'data'=>'盘收任务不存在'];

        app('StoreCheckingReceiveItemService')->update(['store_checking_receive_id'=>$id],[
            'counted_amount'=>0,
            'imported_diff_amount'=>null,
            'asn_diff_amount'=>null,
            'bin_number'=>null,
        ]);
        app('LogService')->log(__METHOD__,"重置盘收任务所有数量","store_checking_receive_id:".$id);
        return ['success'=>true];
    }

    public function matchASN(Request $request){
        if(!Gate::allows('入库管理-快速入库-录入')){ return ['success'=>false, 'data'=>'无权操作!'];  }
        $asn = $request->asn ?? false;
        $id = $request->mission_id ?? false;
        if (!$asn || !$id)return ['success'=>false, 'data'=>'传递参数错误'];

        $withs = ['owner','storeCheckingReceiveItems'=>function($query){
            $query->with(['commodity'=>function($builder) {
                $builder->with('barcodes');
            }]);
        }];
        $storeCheckingReceive = app('StoreCheckingReceiveService')->find($id,$withs);
        if (!$storeCheckingReceive) return ['success'=>false, 'data'=>'未找到此盘点任务!'];
        if ($storeCheckingReceive->status == '已收货')return ['success'=>false, 'data'=>'盘收任务已结束'];

        /** @var OracleDocAsnDetailService $oracleDocAsnDetailService */
        $oracleDocAsnDetailService = app('OracleDocAsnDetailService');
        $docAsnDetails = $oracleDocAsnDetailService->get([
            'asnno'=>$asn,
            'customerid'=>$storeCheckingReceive->owner ? $storeCheckingReceive->owner->code : null],[
                'asnno','customerid','asnlineno','sku','expectedqty'
        ]);
        if (count($docAsnDetails) < 1) return ['success'=>false, 'data'=>'该货主下此ASN号不存在'];

        $diffAmount = null;
        $skus = [];
        foreach ($docAsnDetails as $detail){
            if ($skus[$detail->sku] ?? false) $skus[$detail->sku] += $detail->expectedqty;
            else $skus[$detail->sku] = $detail->expectedqty;
        }
        $deleteItems = [];
        $updateItems = [];
        $updateItems[] = ['id','asn_amount','asn_diff_amount'];
        foreach ($storeCheckingReceive->storeCheckingReceiveItems as $item){
            if (!($item->commodity ? $item->commodity->sku : null))continue;
            if ($storeCheckingReceive->asn && ($item->asn_amount != null)
                && (!($item->counted_amount ?? false))){
                $deleteItems[] = $item->id;
                continue;
            }
            if ($skus[$item->commodity->sku] ?? false){
                $asn_diff_amount = $skus[$item->commodity->sku] - $item->counted_amount;
                $updateItems[] = [
                    'id'=>$item->id,
                    'asn_amount'=>$skus[$item->commodity->sku],
                    'asn_diff_amount'=>$asn_diff_amount,
                ];
                $item->asn_diff_amount = $asn_diff_amount;
                unset($skus[$item->commodity->sku]);
            }
            if ($item->asn_diff_amount)$diffAmount += $item->asn_diff_amount;
        }
        if (count($updateItems) > 0){
            app('StoreCheckingReceiveItemService')->batchUpdate($updateItems);
            app('LogService')->log(__METHOD__,"匹配ASN-批量更新ASN数量",json_encode($updateItems));
        }

        if (count($deleteItems) > 0){
            app('StoreCheckingReceiveItemService')->destroy($deleteItems);
            app('LogService')->log(__METHOD__,"重新匹配ASN-删除原有ASN生成数据",json_encode($updateItems));
        }


        if (count($skus) > 0){
            $skuArr = array_keys($skus);
            /** @var CommodityService $commodityService */
            $commodityService = app('CommodityService');
            $commodities = $commodityService->get(['owner_id'=>$storeCheckingReceive->owner ? $storeCheckingReceive->owner->id : null,'sku'=>$skuArr]);
            $createItems = [];
            foreach ($commodities as $commodity){
                $createItems[] = [
                    'store_checking_receive_id' => $storeCheckingReceive->id,
                    'commodity_id' => $commodity->id,
                    'imported_amount' => 0,
                    'counted_amount' => 0,
                    'asn_amount' => $skus[$commodity->sku],
                    'imported_diff_amount' => 0,
                    'asn_diff_amount' => $skus[$commodity->sku],
                ];
                $diffAmount += $skus[$commodity->sku];
            }

            if (count($createItems) > 0)app('StoreCheckingReceiveItemService')->insert($createItems);
        }
        $data = app('StoreCheckingReceiveService')->updateFind($storeCheckingReceive,[
            'asn'=>$asn,'is_asn_diff'=>$diffAmount===0 ? "否" : "是",'status'=>'已ASN入库'
        ]);
        app('LogService')->log(__METHOD__,"修改盘收任务",json_encode($data,JSON_UNESCAPED_UNICODE));
        return ['success'=>true, 'data'=>$data];
    }

    public function receipt(Request $request){
        if(!Gate::allows('入库管理-快速入库-录入')){ return redirect(url('/'));  }
        $id = $request->id ?? false;

        /** @var StoreCheckingReceiveService $storeCheckingReceiveService */
        $storeCheckingReceiveService = app('StoreCheckingReceiveService');
        /** @var StoreCheckingReceive $storeCheckingReceive */
        $storeCheckingReceive = $storeCheckingReceiveService->find($id);
        if (!$storeCheckingReceive)return ['success'=>false, 'data'=>'盘收任务不存在'];
        if ($storeCheckingReceive->status == '已收货')return ['success'=>false, 'data'=>'盘收任务已结束'];

        $storeController = new StoreController();
        $result = $storeController->quickStorage($storeCheckingReceive->asn,"正品",null,false);
        if ($result['success']) $data = $storeCheckingReceiveService->updateFind($storeCheckingReceive,['status'=>"已收货"]);
        else{
            $data = $storeCheckingReceiveService->updateFind($storeCheckingReceive,['status'=>"收货失败"]);
            app('LogService')->log(__METHOD__,"盘收快速收货失败",json_encode($result['data'],JSON_UNESCAPED_UNICODE)." | ".json_encode($data,JSON_UNESCAPED_UNICODE));
        }
        return ['success'=>true, 'data'=>$data];
    }

    //修改实盘数量
    public function updateCountedAmount(Request $request){
        if(!Gate::allows('入库管理-盘收一体-盘收-编辑')){ return ['success'=>false, 'data'=>'无权操作!'];  }
        $id = $request->id ?? null;
        $counted_amount = $request->counted_amount ?? null;
        if (!$id)return ['success'=>false, 'data'=>'参数传递错误！'];
        $item = app('StoreCheckingReceiveItemService')->find($id);
        if (!$item)return ['success'=>false, 'data'=>'被盘项不存在'];
        $params = ["counted_amount"=>$counted_amount];
        $data = [];
        if ($item->imported_amount){
            $params["imported_diff_amount"] = (int)$counted_amount - (int)$item->imported_amount;
            $data["imported_diff_amount"] = $params["imported_diff_amount"];
        }
        if ($item->asn_amount){
            $params["asn_diff_amount"] = (int)$counted_amount - (int)$item->asn_diff_amount;
            $data["asn_diff_amount"] = $params["asn_diff_amount"];
        }
        //修改差异状态
        if ($item->imported_amount || $item->asn_amount){
            $withs = ['storeCheckingReceiveItems'];
            $storeCheckingReceive = app('StoreCheckingReceiveService')->find($item->store_checking_receive_id,$withs);
            if ($storeCheckingReceive)$this->updateDiffStatus($storeCheckingReceive);
        }
        app('StoreCheckingReceiveItemService')->updateFind($item,$params);
        app('LogService')->log(__METHOD__,"盘点修改实盘数",'item：'.json_encode($item)."update：",$counted_amount);
        return ['success'=>true,"data"=>$data];
    }

    //修改差异状态
    private function updateDiffStatus(StoreCheckingReceive $scr){
        $items = $scr->storeCheckingReceiveItems ?? [];
        $is_receive_diff = "否";
        $is_asn_diff = "否";
        foreach ($items as $item){
            if ($item->imported_diff_amount)$is_receive_diff = "是";
            if ($item->asn_diff_amount)$is_asn_diff = "是";
        }
        $update = [];
        if ($scr->is_receive_diff != $is_receive_diff){
            $update["is_receive_diff"] = $is_receive_diff;
        }
        if ($scr->is_asn_diff != $is_asn_diff){
            $update["is_asn_diff"] = $is_asn_diff;
        }
        if (count($update) > 0){
            $scr->update($update);
            app('LogService')->log(__METHOD__,"修改差异状态",json_encode($scr,JSON_UNESCAPED_UNICODE));
        }
    }

    public function destroyItem(Request $request)
    {
        if (app("StoreCheckingReceiveItemService")->destroy($request->input("id")))return ["success"=>true];
        return ["success"=>false,"data"=>"删除失败"];
    }
}
