<?php

namespace App\models\Logistic\Pri;

use \Service_Receiving;
use \Service_ReceivingDetail;
use \Service_Product;
use \Service_BgPriEntryData;
use \Service_BgPriEntryDataDetail;
use \Common_GetNumbers;
use \Service_BgPriEntryDataDetailBodyHead;
use \Service_BgPriEntryDataDetailBodyDetail;
use \Service_BgPriEntryDataDetailLog;
use \Service_HsUom;
use \Service_HsUomMap;
use \Service_BillBook;
use \Service_BillBookProduct;
use \Service_BgCompany;

class PriEnter
{
    public $receivingCode = [];
    protected $receivingInfo = [];
    protected $priEnterDataDetailBodyDetail = [];
    protected $priEnterHead = [];
    protected $priEntryDataDetail = [];
    protected $splitNumber = 50;
    protected $currentNumber = 0;//当前详情的数量
    protected $spliteDetail = [];//合并后的receiving_detail
    protected $productList = [];//商品信息
    protected $ptCode;
    protected $params;//需要的参数
    protected $companyInfo;//公司代码
    protected $companyCode = 'ZH';
    protected $error; //错误信息
    protected $weightArr; //重量数据
    protected $cfnumber; //计算多少拼数
    protected $defaultArr; //没有的数据暂时给个默认。先写到文件有必要在开放给业务人员配置

    public function setReceivingCode($receivingCode)
    {
        $this->receivingCode[] = $receivingCode;
        $this->getReceivingInfo($receivingCode);
    }
    public function getError(){
        return $this->error;
    }

    public function setDefaultArr()
    {
        $defaultArr = array(
            'declare_port' => '5349',
            'enty_port_code' => '470001',
            'traf_mode' => '4',
            //'duty_mode'=>'3'
        );
        $formType = \Service_FormType::getByField($this->params['pt_code'],'form_type');
        if($formType['default_value']!=''){
            $rowdefault = json_decode($formType['default_value'],true);

            if(!empty($rowdefault)){
                $defaultArr = array_merge($defaultArr,$rowdefault);
            }
        }


        $this->defaultArr = $defaultArr;
    }

    public function setCompanyCode($companyCode)
    {
        if ($companyCode) {
            $this->companyCode = $companyCode;
        }
        $companyInfo = Service_BgCompany::getByField($this->companyCode, 'company_code');
        $this->companyInfo = $companyInfo;
    }

    public function getCompanyInfo()
    {
        $companyInfo = Service_BgCompany::getByField($this->companyCode, 'company_code');
        return $companyInfo;
    }

    public function getReceivingInfo($receivingCode)
    {
        if ($this->receivingInfo[$receivingCode]) {
            return $this->receivingInfo[$receivingCode];
        }
        $receivingInfo = Service_Receiving::getByField($receivingCode, 'receiving_code');
        $receivingDetail = Service_ReceivingDetail::getByCondition([
            'receiving_code' => $receivingCode
        ]);
        $receivingInfo['detail'] = $receivingDetail;
        $this->receivingInfo[$receivingCode] = $receivingInfo;
        return $this->receivingInfo[$receivingCode];
    }

    public function getParams()
    {
        $this->params = [];
    }

    /**
     * @date 2022/7/3
     * @param $key
     * @param $value
     * @todo
     * @auther 46935
     */
    public function setParam($key, $value)
    {
        $this->params[$key] = $value;
    }

    /**
     * @date 2022/7/2
     * @param array $params
     * @todo 设置一些必要的参数
     * @auther 46935
     */
    public function setParams(array $params)
    {
        $this->params = $params;
    }

    public function makePriEnter()
    {
        $this->validate();
        $this->receivingSplitPre();
        $this->receivingSplitPreNumber();
        $this->receivingSplit();
        $this->setDefaultArr(); //设置一些没有的默认参数
        //生成
        $this->addPriEntryData();
    }

    protected function addPriEntryData()
    {
        $add = [
            'ref_no' => $this->params['ref_no'],
            'declare_port' => $this->defaultArr['declare_port'],
            'ie_port' => $this->params['ie_port'],
            'pre_status' => '-1',
            'pt_code' => $this->params['pt_code'],
            'ie_flag' => $this->params['ie_flag'],
            'pack_number' => '',
            'net_weight' => '',
            'gross_weight' => '',
            'add_time' => date("Y-m-d H:i:s"),
            'company_code' => $this->companyCode
        ];
        $allPackNumber = 0;
        $allNetWeight = 0;
        $allGrossWeight = 0;
        foreach ($this->priEnterHead as $detail) {
            $allPackNumber += $detail['bpdd_pack_number'];
            $allNetWeight += $detail['net_weight'];
            $allGrossWeight += $detail['gross_weight'];
        }
        $add['net_weight'] = $allNetWeight;
        $add['gross_weight'] = $allGrossWeight;
        $add['pack_number'] = $allPackNumber;
        $priEntryDataId = Service_BgPriEntryData::add($add);

        $num = count($this->priEnterHead); //计算拼数

        foreach ($this->priEnterHead as $k => $detail) {
            $wrap_type = '';
            $trade_mode = ''; //监管方式
            $trans_mode = ''; //成交方式
            if ($detail['bpd_ref_no'] != '') {
                $bpdNumber = $detail['bpd_ref_no'];
                $recCode = explode("-", $detail['bpd_ref_no']);
                $receving_code = $recCode[0];
                if (!empty($receving_code)) {
                    $receiving = Service_Receiving::getByField($receving_code, 'receiving_code');
                    if (!empty($receiving)) {
                        $wrap_type = $receiving['wrap_type'];
                        $trade_mode = $receiving['trade_mode'];
                        $trans_mode = $receiving['trans_mode'];
                        if($this->defaultArr['trade_mode']){
                            $trade_mode = $this->defaultArr['trade_mode'];
                        }
                    }
                }
            } else {
                $bpdNumber = Common_GetNumbers::getCode('bg_date_detail_body_head', '', $this->params['pt_code'], false);
            }
//            $dataDetail = [
//                'bped_id' => $priEntryDataId,
//                'bpd_ref_no' => $bpdNumber,
//                'add_time' => date("Y-m-d H:i:s")
//            ];
//            $dataDetail = array_merge($dataDetail, $detail);
//            $bpeddId = Service_BgPriEntryDataDetail::add($dataDetail);

            $trade_area_code = $this->params['trade_area_code'];
            if(empty($trade_area_code)){
                if(isset($this->defaultArr['trade_area_code'])){
                    $trade_area_code = $this->defaultArr['trade_area_code'];
                }
            }
            if(empty($trade_area_code)){
                $trade_area_code = "";
            }

            $destination_port = $this->params['destination_port'];

            if(empty($destination_port)){
                $destination_port = "";
            }

            //以下信息要改
            $declare_port = $this->defaultArr['enty_port_code'];
            $ie_port = $this->params['ie_port'];
            //



            $head = [
                'bped_id' => $priEntryDataId,
                'bpd_ref_no' => $detail['bpd_ref_no'],
                'pt_code' => $this->params['pt_code'],
                'ie_flag' => $this->params['ie_flag'],
                'declare_port' => $this->defaultArr['declare_port'],
                'ie_port' => $ie_port,
                'enty_port_code' => $declare_port,
                'ems_no' => $this->companyInfo['bwl_no'],
                'ems_cop_no' => '',
                'cop_gb_code' => '',
                'platenumber' => $this->params['platenumber'],
                'traf_name' => '',
                'traf_mode' => $this->defaultArr['traf_mode'],
                'voyage_no' => '',
                'bill_no' => '',
                'wrap_type' => $wrap_type,
                'net_wt' => $detail['net_weight'],
                'gross_wt' => $detail['gross_weight'],
                'pack_no' => $detail['bpdd_pack_number'],
                'duty_mode' => '',
                'trade_co' => $this->companyInfo['trade_co'],
                'trade_name' => $this->companyInfo['trade_name'],
                'agent_code' => $this->companyInfo['declare_customs_code'],
                'agent_name' => $this->companyInfo['declare_company_name'],
                'owner_code' => $this->companyInfo['trade_co'], //暂时和境内收发货人一致
                'owner_name' => $this->companyInfo['trade_name'],//
                'trade_mode' => $trade_mode,
                'trans_mode' => $trans_mode,
                'trade_country' => isset($this->defaultArr['trade_country'])?$this->defaultArr['trade_country']:'',//运抵国
                'trade_area_code' => $trade_area_code,//贸易国
                'destination_port' => $destination_port,//指运港
                'num'=>$num, //拼数
                'rlt_entry_rvsngd_etps_sccd' => $this->companyInfo['rvsngd_etps_sccd'],//关联报关单收发货单位社会统一信用代码',
                'rlt_entry_rcvgd_etpsno' => $this->companyInfo['rcvgd_etps_no'],//关联报关单海关收发货单位编码',
                'rlt_entry_rcvgd_etps_nm' => $this->companyInfo['rcvgd_etps_nm'],// 关联报关单收发货单位名称',
                'rlt_entry_bizop_etps_sccd' => $this->companyInfo['declare_social_credit_code'],//'关联报关单经营企业社会信用代码',
                'rlt_entry_bizop_etpsno' => $this->companyInfo['declare_customs_code'],//'关联报关单经营企业编码',
                'rlt_entry_bizop_etps_nm' => $this->companyInfo['declare_company_name'],//关联报关单经营企业名称,
                'add_time'=>date("Y-m-d H:i:s"),
            ];
            $headId = Service_BgPriEntryDataDetailBodyHead::add($head);
            $log = [
                'bped_id' => $priEntryDataId,
                'bpedbh_id' => $headId,
                'content' => '生成预录入数据',
                'add_time' => date("Y-m-d H:i:s"),
            ];
            Service_BgPriEntryDataDetailLog::add($log);

            $bodyDetail = $this->priEnterDataDetailBodyDetail[$k];
            $gNo = 1;
            foreach ($bodyDetail as $detailBodyDetail) {
                $productInfo = $this->getProductInfo($detailBodyDetail['product_id']);
                $uomInfo = $this->getProductUomInfo($detailBodyDetail['product_id'], $productInfo['hs_code']);

                $contr_item = $this->billNO($productInfo['product_id'], $this->companyInfo['bwl_no']);
                if($contr_item!=''){
                    //账册有取账册
                    $books = Service_BillBook::getByCondition(['warehous_account_no'=>$this->companyInfo['bwl_no'],'recorde_no'=>$contr_item],"*",1,1);
                    $book = $books[0];
                    $gname = $book['product_title'];
                    $code_ts = $book['hs_code'];
                    $gmodel = $book['specification'];
                    $trade_curr = $book['decalar_currency'];

                }else{
                    //账册无取备案
                    $gname = $productInfo['hs_goods_name'];
                    $code_ts = $productInfo['hs_code'];
                    $gmodel = Service_Product::getGModel($productInfo['product_id']);
                    $currency = \Service_Currency::getByField($productInfo['currency_code'], 'currency_code');
                    $trade_curr = "";
                    if ($currency['currency_hs_code'] != '') {
                        $trade_curr = $currency['currency_hs_code'];
                    }else{
                        $this->error[] = "";
                    }
                }

                $addBodyDetail = [
                    'bpedbh_id' => $headId,
                    'product_id' => $productInfo['product_id'],
                    'goods_id' => $productInfo['goods_id'],
                    'g_no' => $gNo,
                    'class_mark' => '',
                    'code_ts' => $code_ts,//
                    'contr_item' => $contr_item,//备案序号,
                    'decl_price' => $productInfo['product_declared_value'],
                    'duty_mode' => '3',
                    'factor' => '',
                    'gmodel' => $gmodel,
                    'gname' => $gname,
                    'origin_country' => '142',//$productInfo[''],原产国为空
                    'trade_curr' => $trade_curr,
                    'decl_total' => $productInfo['product_declared_value'] * $detailBodyDetail['rd_receiving_qty'],
                    'gqty' => $detailBodyDetail['rd_receiving_qty'],
                    'first_qty' => $uomInfo['uom_map']['hum_quantity_law'],
                    'second_qty' => $uomInfo['uom_map']['hum_quantity_second'],
                    'gunit' => $productInfo['pu_code'],
                    'first_unit' => $uomInfo['hs_uom']['pu_code_law'],
                    'second_unit' => $uomInfo['hs_uom']['pu_code_second'],
                    'destination_country'=>$this->params['destination_country'], //最终目的国没有

//                        'use_to'=>'',
//                        'work_usd'=>'',
//                        'exg_no'=>'',
//                        'exg_version'=>'',
//                        'destination_country'=>'',
//                        'ciq_code'=>'',
//                        'decl_goods_ename'=>'',
//                        'orig_place_code'=>'',
//                        'purpose'=>'',
//                        'prod_valid_dt'=>'',
//                        'prod_qgp'=>'',
//                        'goods_attr'=>'',
//                        'stuff'=>'',
//                        'uncode'=>'',
//                        'dang_name'=>'',
//                        'dang_pack_type'=>'',
//                        'dang_pack_spec'=>'',
//                        'eng_man_ent_cnm'=>'',
//                        'no_dang_flag'=>'',
//                        'dest_code'=>'',
//                        'goods_spec'=>'',
//                        'goods_model'=>'',
//                        'goods_brand'=>'',
//                        'produce_date'=>'',
//                        'prod_batch_no'=>'',
//                        'district_code'=>'',
//                        'ciq_name'=>'',
//                        'mnufctr_reg_no'=>'',
//                        'mnufctr_reg_name'=>'',
                    'add_time' => date("Y-m-d H:i:s"),
//                        'update_time'=>'',
//                        'rcep_orig_place_code'=>'',
                ];
                Service_BgPriEntryDataDetailBodyDetail::add($addBodyDetail);
                $gNo++;
            }

        }

    }

    /**
     * @date 2022/7/3
     * @param $productId
     * @param $warehouseCount
     * @return mixed|string
     * @todo 获取账册号
     * @auther 46935
     */
    protected function billNO($productId, $warehouseCount)
    {
        $billBook = Service_BillBookProduct::getByCondition(array(
            'product_id' => $productId,
        ));
        if (!empty($billBook)) {
            $bilId = array();
            foreach ($billBook as $bill) {
                $bilId[] = $bill['bill_book_id'];
            }
            $bilId = array_unique($bilId);
            $billBook = Service_BillBook::getByCondition([
                'id_array' => $bilId,
                'warehous_account_no' => $warehouseCount,
                'state' => '0', //只取正常状态的库存
            ], '*', '1', '1', array('stock_quantity asc '));
            if(!empty($billBook)){
                return $billBook[0]['recorde_no'];
            }
        }
        return '';
    }

    //拆分商品
    protected function split()
    {
        $receivingList = $this->receivingInfo;
        $detailList = [];
        $splitDetail = [];
        $splitHead = [];
        foreach ($receivingList as $receiving) {
            $detail = $receiving['detail'];
            $customerId = $receiving['customer_id'];
            foreach ($detail as $rd) {
                $this->addDetail($rd, $customerId);
            }
        }
        $foreachIndex = 0;
        $netWeight = 0;
        $grossWeight = 0;
        $packNumber = 0;
        foreach ($this->spliteDetail as $detail) {
            $foreachIndex++;
            $splitDetail[] = $detail;
            $netWeight += $this->getProductWeight($detail['product_id']);
            $grossWeight += $this->getProductGrossWeight($detail['product_id']);
            $packNumber += $detail['receiving_qty'];
            if ($foreachIndex % $this->splitNumber == 0) {
                $this->priEnterDataDetailBodyDetail[] = $splitDetail;
                $this->priEntryDataDetail[] = [
                    'bpdd_pack_number' => $packNumber,
                    'net_weight' => $netWeight,
                    'gross_weight' => $grossWeight,
                ];
                $splitDetail = [];
                $netWeight = 0;
                $grossWeight = 0;
            }
        }
        //还有剩余的
        if ($foreachIndex % $this->splitNumber != 0) {
            $this->priEnterDataDetailBodyDetail[] = $splitDetail;
            $this->priEntryDataDetail[] = [
                'bpdd_pack_number' => $packNumber,
                'net_weight' => $netWeight,
                'gross_weight' => $grossWeight,
            ];
        }
        return $this;
    }

    /**
     * @todo 事先计算合并入库单里面的商品表体，提前计算总毛净重
     */
    protected function receivingSplitPre()
    {
        //$totalweight =
        foreach ($this->receivingInfo as $k => $receiving) {
            $detail = $receiving['detail'];
            $detailMerge = [];//入库单商品可能有重复的 合并重复项目
            $totalproductgrossweight = $totalproductnetweight = 0;

            foreach ($detail as $kd => $vd) {
                if ($vd['product_id'] > 0) {
                    $totalproductgrossweight += $vd['rd_receiving_qty'] * $this->getProductGrossWeight($vd['product_id']);
                    $totalproductnetweight += $vd['rd_receiving_qty'] * $this->getProductWeight($vd['product_id']);

                    if (isset($detailMerge[$vd['product_id']])) {
                        $detailMerge[$vd['product_id']]['rd_receiving_qty'] += $vd['rd_receiving_qty'];
                    } else {
                        $detailMerge[$vd['product_id']] = $vd;
                    }
                } else {
                    //假如商品id没写(一日游的业务有可能没备案防止这个情况，正常没有)
                    $key = 'k' . $kd; //将id加一个前缀，防止生成的数组健值和商品id重复了
                    $detailMerge[$key] = $vd;
                }
                $weightArr = array(
                    'totalproductgrossweight' => $totalproductgrossweight,
                    'totalproductnetweight' => $totalproductnetweight,
                );
            }
            $this->receivingInfo[$k]['detail'] = array_values($detailMerge);
            $this->weightArr[$receiving['receiving_code']] = $weightArr;
            //print_r($this->weightArr);
        }
    }

    /**
     * @todo 前置计算拼数
     */
    protected function receivingSplitPreNumber()
    {
        $receivingList = $this->receivingInfo;
        $cfnumber = 0;
        foreach ($receivingList as $receiving) {
            $detail = $receiving['detail'];
            $chunk = array_chunk($detail, $this->splitNumber);
            $index = 1;
            foreach ($chunk as $chunkDetail) {
                $netWeight = 0;
                $grossWeight = 0;
                $packNumber = 0;
                foreach ($chunkDetail as $rd) {
                    $netWeight += $this->getProductWeight($rd['product_id']);
                    $grossWeight += $this->getProductGrossWeight($rd['product_id']);
                    $packNumber += $rd['receiving_qty'];
                }
                $index++;
                $cfnumber++;
            }
        }
        $this->cfnumber = $cfnumber;
        return $this;
    }


    /**
     * @date 2022/7/3
     * @return $this
     * @todo 按入库单拆分商品
     * @auther 46935
     */
    protected function receivingSplit()
    {
        $receivingList = $this->receivingInfo;
        $cfnumber = 1;
        foreach ($receivingList as $receiving) {
            $detail = $receiving['detail'];
            $chunk = array_chunk($detail, $this->splitNumber);
            $index = 1;
            $zdnum = count($chunk);
            foreach ($chunk as $chunkDetail) {
                $netWeight = 0;
                $grossWeightProduct = 0;
                $packNumber = 0;
                foreach ($chunkDetail as $rd) {
                    $netWeight += $rd['rd_receiving_qty'] * $this->getProductWeight($rd['product_id']);
                    $grossWeightProduct += $rd['rd_receiving_qty'] * $this->getProductGrossWeight($rd['product_id']);
                    $packNumber += $rd['receiving_qty'];
                }

                $this->priEnterDataDetailBodyDetail[] = $chunkDetail; //表体不对按固定项目拆分表体要存相应的拆分表体
                //总重量
                //$gap = $receiving['receiving_code']['roughweight'] -  $this->weightArr[$receiving['receiving_code']]['totalproductgrossweight'];
                $grossWeight = $receiving['roughweight'] * ($grossWeightProduct / $this->weightArr[$receiving['receiving_code']]['totalproductgrossweight']);
                $grossWeight = sprintf('%.4f', $grossWeight);
                //var_dump($receiving);

                if ($receiving['pack_no'] < count($chunk)) {
                    $this->error[] = "入库单件数" . $receiving['pack_no'] . "小于报关拆分数:{$zdnum},无法拆分";
                }


                if ($index == 1) {
                    //$pack_number
                    $pack_number = $receiving['pack_no'] - floor($receiving['pack_no'] / $zdnum) * ($zdnum - 1);
                } else {
                    $pack_number = floor($receiving['pack_no'] / $zdnum);
                }

                $this->priEnterHead[] = [
                    'bpd_ref_no' => $receiving['receiving_code'] . '-' . $index,
                    'bpdd_pack_number' => $pack_number,
                    'net_weight' => $grossWeightProduct,
                    'gross_weight' => $grossWeight,
                    'num' => $this->cfnumber,
                    'pack_no' => $pack_number,
                ];
                $index++;
                $cfnumber++;
            }
        }
        return $this;
    }

    protected function getProductUomInfo($productId, $hsCode)
    {
        $uomInfo = Service_HsUom::getByField($hsCode, 'hs_code');
        $uomMap = Service_HsUomMap::getByCondition([
            'product_id' => $productId,
            'hu_id' => $uomInfo['hu_id']
        ]);
//        error_log(var_export([
//            'product_id' => $productId,
//            'hu_id' => $uomInfo['hu_id']
//        ],true));
//        error_log($uomInfo['hu_id']);
//        error_log(var_export($uomMap,true));
        return [
            'hs_uom' => $uomInfo,
            'uom_map' => $uomMap[0]
        ];
    }


    protected function getProductWeight($productId)
    {
        $p = $this->getProductInfo($productId);
        return $p['product_net_weight'];
    }

    protected function getProductGrossWeight($productId)
    {
        $p = $this->getProductInfo($productId);
        return $p['product_weight'];
    }

    public function getProductInfo($productId)
    {
        if (!$this->productList[$productId]) {
            $productInfo = Service_Product::getByField($productId);
            if (!$productInfo) {
                throw new \Exception("商品Id" . $productId . '不存在');
            }
            $this->productList[$productId] = $productInfo;
        }
        return $this->productList[$productId];
    }

    /**
     * @param $receivingDetail
     * @param $customerId
     * @return $this
     * @todo 合并receiving_detail
     */
    protected function addDetail($receivingDetail, $customerId)
    {
        $uniSku = $customerId . $receivingDetail['product_sku'];
        if (!$this->spliteDetail[$uniSku]) {
            $this->spliteDetail[$uniSku] = $receivingDetail;
            $this->currentNumber++;
        } else {
            $this->spliteDetail[$uniSku]['rd_receiving_qty'] += $receivingDetail['rd_receiving_qty'];
        }
        return $this;
    }

    /**
     * @date 2022/7/3
     * @throws \Exception
     * @todo 校验必填的参数
     * @auther 46935
     */
    protected function validate()
    {
        $error = [];
        if (empty($this->params['ref_no'])) {
            $error[] = 'ref_no 必填';
        } else {
           $data = Service_BgPriEntryData::getByField($this->params['ref_no'],'ref_no');
           if(!empty($data)){
               $error[] = 'ref_no 系统已经存在相同的预录入单号'.$this->params['ref_no'];
           }
        }
        if (empty($this->params['ie_flag'])) {
            $error[] = '进出类型必填';
        }
        if (empty($this->params['ie_port'])) {
            $error[] = '进出口岸必填';
        }
        if (empty($this->params['pt_code'])) {
            $error[] = '业务代码为空';
        }
        if (empty($this->params['platenumber'])) {
            $error[] = '车牌号码为空';
        }
        if (empty($this->params['bg_company'])) {
            $error[] = '传输企业不能为空';
        }
        if (!empty($error)) {
            throw new \Exception(implode(',', $error));
        }
    }
}
