<?php
namespace model\import;
use \model;
use \model\check;
use model\freyIbp;
use model\pack\packs;

/**
 * 
 */
class propackv2  extends model
{
	public $title = '包装'; //固定
	public $import = null;    //固定
	public $rules = null;    //规则
	public $demoData = null;  //样例数据
	public $demoremark = null;  //样例说明
    public $itype = '';
    
	
	public function __construct()
	{   
		parent::__construct(); //执行父类
		$this->import = new \lib\import();
		$this->rules = [
            ['key'=>'pp_p_id','caption'=>lg('商品物料编码'),'must'=>true],
            ['key'=>'pp_name','caption'=>lg('方案名称'),'must'=>true],
            ['key'=>'pp_type','caption'=>lg('类型'),'must'=>true],

            ['key'=>'pp_com_id','caption'=>lg('事业部编码'),'must'=>true],
            ['key'=>'pp_pack_style','caption'=>lg('包装方式')],
            ['key'=>'pp_pack_status','caption'=>lg('包装状态')],
            ['key'=>'pp_out_remark','caption'=>lg('包装备注')],
            ['key'=>'pp_craft','caption'=>lg('工艺'),'formatCell'=>[\model\collocation::class,[],'getOidByName',['@', 1170],null]],
            ['key'=>'pp_per_carton','caption'=>lg('每盒数量')],
            ['key'=>'pp_per_bag','caption'=>lg('每袋数量')],
            ['key'=>'pp_per_box','caption'=>lg('每箱数量')],
            ['key'=>'pp_per_pallet_box','caption'=>lg('每托箱数')],
            ['key'=>'pp_per_pallet_layer','caption'=>lg('每托层数')],
            ['key'=>'pp_per_pallet_volume','caption'=>lg('每托体积')],
            // 单个产品体积
            ['key'=>'pp_per_pro_volume','caption'=>lg('单个产品体积')],
            ['key'=>'pp_per_pro_length','caption'=>lg('单个产品长')],
            ['key'=>'pp_per_pro_width','caption'=>lg('单个产品宽')],
            ['key'=>'pp_per_pro_height','caption'=>lg('单个产品高')],
            ['key'=>'p_weight','caption'=>lg('产品净重')],
            ['key'=>'pp_weight_carton','caption'=>lg('每盒毛重')],
            ['key'=>'pp_weight_bag','caption'=>lg('每袋毛重')],
            ['key'=>'pp_weight_box','caption'=>lg('每箱毛重')]
		];
        $this->itype = \mvc::$req['itype'];
		if(empty($this->itype) && !empty(\mvc::$req['params'])){
			$params =json_decode(\mvc::$req['params'],true);
			$this->itype =$params['itype'];
		}

        if($this->itype=='sonMaterial'){
            $this->rules[] =    ['key'=>'son_materials','caption'=>lg('包材子件')];
        }elseif($this->itype=='sonPro'){
            $this->rules[] =    ['key'=>'son_pro','caption'=>lg('套装子零件')];
        }

		$this->demoData = [
            '865806201',
            '套装方案A',
            '共享',
            '事业部编码',
            'FREY袋子+FREY盒子',
            '外包',
            '外包（我司寄标签）',
            '白色刻字',1,2,4,7,0,0,0,0,0,0,0,0,0,0,
		];
         if($this->itype=='sonMaterial'){
            $this->demoData[] =    '格式：包材物料编码@数量@备注';
        }elseif($this->itype=='sonPro'){
            $this->demoData[] =    '格式：商品物料编码@数量@备注';
        }


		$this->demoremark = '';
	}
	
	 /**处理导入
     * @param array|string $src 数组或者文件名
     * @param isInit 是否是初始化
     * @return 可返回任意值(string|array|bool)，都会到前端
     */
    public function import($src,$isInit=false) //固定
    {
        ini_set('memory_limit', \mvc::$cfg['upload']['memory_limit']);
        set_time_limit(0);
		$state = $this->import->execute($src, $this->rules);

		
        $comsArr = [];
        $coms = $this->db->select('company',['com_id','com_code']);
        if($coms){
            $comsArr =  array_column($coms,'com_id','com_code');
            $comsArrRev =  array_column($coms,'com_code','com_id');
        }
		//统一获取
        $pidsArr = [];
        $pmbIdCache = [];
        $sonProIdCache = [];
        $packStyleCache = [];

		//数据重复验证
		if($state && !empty($this->import->data))
		{   
            $pNumArr = array_column($this->import->data,'pp_p_id');
            $pFormatArr = [];
            foreach ($pNumArr as $pNum) {
                $pFormatArr[] = formatNum($pNum);
            }
            $pids = $this->db->select('pro',['p_id','p_innum'],['p_innum_format'=>$pFormatArr]);
            if($pids){
                $pidsArr =  array_column($pids,'p_id','p_innum');
            }
			foreach($this->import->data as &$dv)
			{   
                $tempNum = $dv['pp_p_id'];
                $dv['pp_p_id'] = $pidsArr[$dv['pp_p_id']] ?? 0;
                if(!$dv['pp_p_id']){
                    $state = false;
                    $dv['excelInfo']['error'] = '商品物料编码不存在：'.$tempNum;
                    $this->import->lineNum = $dv['excelInfo']['line'];
                    $this->import->lastError = $dv['excelInfo']['error'];
                    continue;
                }
                if (!empty($dv['pp_pack_status'])) {    
                    if($dv['pp_pack_status'] == '外包'){
                        $dv['pp_pack_status'] = 'outpack';
                    }elseif ($dv['pp_pack_status'] == '内包') {
                        $dv['pp_pack_status'] = 'inpack';
                    }else{
                        $state = false;
                        $dv['excelInfo']['error'] = '包装状态-不支持：'.$dv['pp_pack_status'];
                        $this->import->lineNum = $dv['excelInfo']['line'];
                        $this->import->lastError = $dv['excelInfo']['error'];
                        continue;
                    }
                } else {
                    
                    $dv['pp_pack_status'] = ''; 
                }
                $dv['pp_com_id'] = $comsArr[$dv['pp_com_id']] ?? 0;
                if(!$dv['pp_com_id']){
                    $state = false;
                    $dv['excelInfo']['error'] = '请填写正确的事业部编码';
                    $this->import->lineNum = $dv['excelInfo']['line'];
                    $this->import->lastError = $dv['excelInfo']['error'];
                    continue;
                }
     
                if($dv['pp_type'] == '共享'){
                    $dv['pp_type'] = 'share';
                }elseif ($dv['pp_type'] == '定制') {
                    $dv['pp_type'] = 'self';
                }else{
                    $state = false;
                    $dv['excelInfo']['error'] = '类型-不支持：'.$dv['pp_type'];
                    $this->import->lineNum = $dv['excelInfo']['line'];
                    $this->import->lastError = $dv['excelInfo']['error'];
                    continue;
                }

                if($dv['son_materials']){
                    $son_materials = strtr($dv['son_materials'],['，'=>',',';'=>',','；'=>',',"\n"=>',',"\r\n"=>',']);
                    $materialArr = array_filter(array_map('trim', explode(',', $son_materials)));
                    $dv['material'] = [];
                    $i = -1;
                    $errorArr = [];
                    $uniArr = [];
                   $pmbIdArr =[];
                    foreach ($materialArr as $key => $item) {
                        $dv['material'][$i] = [
                            'ppm_pmb_id'=>0,
                            'ppm_count'=>0,
                            'ppm_remark'=>''
                        ];
                        $itemArr = array_map('trim', explode('@', $item));
                        if(count($itemArr) > 3){
                            $state = false;
                            $dv['excelInfo']['error'] = '包材子件-格式错误：'.$item.',多个请用换行分隔';
                            $this->import->lineNum = $dv['excelInfo']['line'];
                            $this->import->lastError = $dv['excelInfo']['error'];
                            continue;
                        }
                        if(!$itemArr[0]) continue;
                        //检查表格内同一个包装方案是否存在重复物料
                        if(!$uniArr[$itemArr[0]]){
                            $uniArr[$itemArr[0]] = 1;
                        }else{
                            $state = false;
                            $dv['excelInfo']['error'] = '包材子件-包材物料编码重复：'.$itemArr[0];
                            $this->import->lineNum = $dv['excelInfo']['line'];
                            $this->import->lastError = $dv['excelInfo']['error'];
                            continue;
                        }
                       
                        if($itemArr[0]){
                            if(!array_key_exists($itemArr[0], $pmbIdCache)){
                                $pmbIdCache[$itemArr[0]] = $this->db->get('pack_material_brand','pmb_id',['pmb_incode'=>$itemArr[0]]);
                            }
                            $pmb_id = $pmbIdCache[$itemArr[0]];
                            if(!$pmb_id){
                                $errorArr[] = $itemArr[0];
                                continue;
                            }
                            $dv['material'][$i]['ppm_pmb_id'] = $pmb_id;
                            $pmbIdArr[] = $pmb_id;
                        }
                        if($itemArr[1]){
                            $dv['material'][$i]['ppm_count'] = $itemArr[1];
                        }
                        if($itemArr[2]){
                            $dv['material'][$i]['ppm_remark'] = $itemArr[2];
                        }
                        $i--;
                    }

                    if($errorArr){
                        $state = false;
                        $dv['excelInfo']['error'] = '包材子件-包材物料编码不存在：'.implode(",",$errorArr);
                        $this->import->lineNum = $dv['excelInfo']['line'];
                        $this->import->lastError = $dv['excelInfo']['error'];
                        continue;
                    }

                    if($pmbIdArr){
                        $packStyleIds = array_values(array_unique($pmbIdArr));
                        sort($packStyleIds);
                        $packStyleKey = implode(',', $packStyleIds);
                        if(!array_key_exists($packStyleKey, $packStyleCache)){
                            $res = $this->db->select('pack_material_brand(pmb)',
                            [
                                '[><]pack_material(pam)'=>['pmb.pmb_pam_id'=>'pam_id'],
                                '[><]pack_type(pat)'=>['pam.pam_pat_id'=>'pat_id']
                            ],
                            'pat_cn_name',['pmb_id'=>$packStyleIds,'GROUP'=>'pat_id','ORDER'=>['pat_code'=>'ASC']]);
                            $packStyleCache[$packStyleKey] = implode('+',$res);
                        }
                        $dv['pp_pack_style'] = $packStyleCache[$packStyleKey];
                    }
                }

                if($dv['son_pro']){
                    $son_pro = strtr($dv['son_pro'],['，'=>',',';'=>',','；'=>',',"\n"=>',',"\r\n"=>',']);
                    $proArr = array_filter(array_map('trim', explode(',', $son_pro)));
                    $dv['sonpro'] = [];
                    $i = -1;
                    $errorArr = [];
                    $uniArr = [];
                    foreach ($proArr as $key => $item) {
                        $dv['sonpro'][$i] = [
                            'pps_p_id'=>0,
                            'pps_count'=>0,
                            'pps_remark'=>''
                        ];
                        if(!$item) continue;

                        $itemArr = array_map('trim', explode('@', $item));
                        if(count($itemArr) > 3){
                            $state = false;
                            $dv['excelInfo']['error'] = '套装子零件-格式错误：'.$item.',多个请用换行分隔';
                            $this->import->lineNum = $dv['excelInfo']['line'];
                            $this->import->lastError = $dv['excelInfo']['error'];
                            continue;
                        }
                        if(!$itemArr[0]) continue;
                        //检查表格内同一个包装方案是否存在重复零件
                        if(!$uniArr[$itemArr[0]]){
                            $uniArr[$itemArr[0]] = 1;
                        }else{
                            $state = false;
                            $dv['excelInfo']['error'] = '套装子零件-商品物料编码重复：'.$itemArr[0];
                            $this->import->lineNum = $dv['excelInfo']['line'];
                            $this->import->lastError = $dv['excelInfo']['error'];
                            continue;
                        }
                        if(!array_key_exists($itemArr[0], $sonProIdCache)){
                            $sonProIdCache[$itemArr[0]] = $this->db->get('pro','p_id',['p_innum_format'=>$itemArr[0]]);
                        }
                        $p_id = $sonProIdCache[$itemArr[0]];
                        if(!$p_id){
                            $errorArr[] = $itemArr[0];
                            continue;
                        }
                        $dv['sonpro'][$i]['pps_p_id'] = $p_id;
                        if($itemArr[1]){
                            $dv['sonpro'][$i]['pps_count'] = $itemArr[1];
                        }
                        if($itemArr[2]){
                            $dv['sonpro'][$i]['pps_remark'] = $itemArr[2];
                        }
                        $i--;
                    }

                    if($errorArr){
                        $state = false;
                        $dv['excelInfo']['error'] = '套装子零件-商品物料编码不存在：'.implode(",",$errorArr);
                        $this->import->lineNum = $dv['excelInfo']['line'];
                        $this->import->lastError = $dv['excelInfo']['error'];
                        continue;
                    }
                }
			}
			unset($dv);
		}
		//入库
		if($state && !empty($this->import->data))
		{   
            //构建一个数组，如果同样的innum 都有同样的com_code 的组合
            $pidArr = array_values(array_unique(array_filter(array_column($this->import->data,'pp_p_id'))));
            $proRows = $this->db->select('pro',['p_id','p_innum','p_weight'],['p_id'=>$pidArr]);
            $innumArr = array_column($proRows,'p_innum','p_id');
            $weightArr = array_column($proRows,'p_weight','p_id');
            $packKey = function($row){
                return implode('|', [
                    $row['pp_p_id'] ?? '',
                    $row['pp_name'] ?? '',
                    $row['pp_com_id'] ?? ''
                ]);
            };
            $packRows = $this->db->select('pro_pack',[
                'pp_id','pp_p_id','pp_name','pp_type','pp_com_id','pp_pack_status'
            ],['pp_p_id'=>$pidArr]);
            $packMap = [];
            $packCount = [];
            foreach($packRows as $row){
                $packMap[$packKey($row)] = $row['pp_id'];
                $packCount[$row['pp_p_id']] = ($packCount[$row['pp_p_id']] ?? 0) + 1;
            }

            $pids = [];
            $temp = [];
            $insertMaterialRows = [];
            $insertSonProRows = [];
            $coverMaterialPpIds = [];
            $coverSonProPpIds = [];
            $this->db->Begin();
			foreach($this->import->data as $k=>$mv)
			{
				if($k > 0 && $k%1000 === 0) errorLog(__CLASS__.$this->title.':'.$k, 'import');
                //通过 pp_p_id、pp_name、pp_com_id确定具体包装方案
                $pp_id = $packMap[$packKey($mv)] ?? 0;
                if($pp_id){
                    $mv['pp_id'] = $pp_id;
                }else{
                    $mv['pp_id'] = $mv['pp_id'] ?? 0;
                }
                $data = [
                    'pp_opuser'=>getOpuser(),
                    'pp_update_time'=>getNowTime()
                ];
                $proData = [];
                foreach ($mv as $field => $val) {
                    if(strpos($field, 'pp_')!==false){
                        $data[$field] = $val;
                    }elseif($field=='p_weight'){
                        $proData['p_weight'] = $val;
                    }
                }
                unset($data['pp_id']);
                $counts = $packCount[$data['pp_p_id']] ?? 0;
                if($mv['pp_id']){
                    $counts--;
                }
                if($counts==0){
                    $data['pp_default'] =1;
                }
     
                if($mv['pp_id']){

                    $this->db->update('pro_pack',$data,['pp_id'=>$mv['pp_id']]);
                    $pp_id = $mv['pp_id'];
                }else{
                    $data['pp_create_time'] = getNowTime();
                    $this->db->insert('pro_pack',$data);
                    $pp_id = $this->db->id();
                    $packMap[$packKey($data)] = $pp_id;
                    $packCount[$data['pp_p_id']] = ($packCount[$data['pp_p_id']] ?? 0) + 1;
                }
                //只有修改了商品净重才更新商品信息
                if(isset($proData['p_weight']) && ($weightArr[$data['pp_p_id']] ?? null) != $proData['p_weight']){
                    $pids[] = $data['pp_p_id'];
                    $this->db->update('pro',$proData,['p_id'=>$data['pp_p_id']]);
                    $weightArr[$data['pp_p_id']] = $proData['p_weight'];
                }
                    //商品净重
               
                //包材子件导入
                if($this->itype=='sonMaterial'&& isset($mv['son_materials'])){
                    $coverMaterialPpIds[$pp_id] = $pp_id;
                    $materialArr = $mv['material'] ?? [];
                    foreach ($materialArr as $val) {
                        
                        $val['ppm_pp_id'] = $pp_id;
                        $val['ppm_update_time'] = getNowTime();
                        $val['ppm_opuser'] = getOpuser();
                        $materialKey = $pp_id.'_'.$val['ppm_pmb_id'];
                        $val['ppm_create_time'] = getNowTime();
                        $insertMaterialRows[$materialKey] = $val;
                    }
                }
                //子零件导入
                if($this->itype=='sonPro' && isset($mv['son_pro'])){
                    
                    $coverSonProPpIds[$pp_id] = $pp_id;
                    $sonProArr = $mv['sonpro'] ?? [];
                   
                    foreach ($sonProArr as $val) {
                        $updata = [
                            'pps_update_time'=>getNowTime(),
                            'pps_opuser'=>getOpuser(),
                            'pps_p_id'=>$val['pps_p_id'],
                            'pps_count'=>$val['pps_count'],
                            'pps_pp_id'=>$pp_id,
                            'pps_remark'=>$val['pps_remark'],
                        ];
                        $sonProKey = $pp_id.'_'.$val['pps_p_id'];
                        $updata['pps_create_time'] = getNowTime();
                        $insertSonProRows[$sonProKey] = $updata;
                    }
                }
                //物料编码=>事业部
                $temp[$innumArr[$mv['pp_p_id']]][] = $comsArrRev[$mv['pp_com_id']]??'';
			}
            //更新内容推送到IBP接口
            if($coverMaterialPpIds ){
                $this->db->delete('pro_pack_material',['ppm_pp_id'=>array_values($coverMaterialPpIds)]);
            }
            if($coverSonProPpIds){
                $this->db->delete('pro_pack_sonpro',['pps_pp_id'=>array_values($coverSonProPpIds)]);
            }
            if($insertMaterialRows){
                foreach(array_chunk(array_values($insertMaterialRows), 500) as $rows){
                    $this->db->insert('pro_pack_material',$rows);
                }
            }
            if($insertSonProRows){
                foreach(array_chunk(array_values($insertSonProRows), 500) as $rows){
                    $this->db->insert('pro_pack_sonpro',$rows);
                }
            }
			$this->db->End();
            $freyIbp = new freyIbp();
            if($pids){
                $pids = array_unique($pids);
                $freyIbp->receivePdmProBase($pids,'base');
            }
            if($temp){
                $groupedData = [];
           
                foreach ($temp as $innum => $coms) {
                    $uniqueComs = array_filter(array_unique($coms));
                    if(!$coms) continue;
                    sort($uniqueComs);
                    $groupKey = serialize($uniqueComs);
                    
                    if (!isset($groupedData[$groupKey])) {
                        $groupedData[$groupKey] = [
                            'innums' => [],
                            'coms'   => $uniqueComs
                        ];
                    }
                    $groupedData[$groupKey]['innums'][] = $innum;

                }
                foreach ($groupedData as $group) {
                    $uniqueInnums = array_unique($group['innums']);
                    $freyIbp->receivePdmProPack($uniqueInnums, $group['coms'], 'pack');
                }
            }
		}
        return $this->import->output(); //生成处理-结果
	}
}
