<?php

namespace model;

use \model;
use \model\ypApi;
use \model\pro\factory;

class napro extends \model
{
    /**
     * @method 获取北美品牌列表信息
     * @author hongzhang
     * @copyright 2026-03-10
     */
    function getNaProBrandList($params = [])
    {
        $table = 'napro_factory';
        $join = [
            '[>]napro_product(np)' => ['fac_id' => 'pro_fac_id'],
            '[>]napro_product_vehicle(ppv)' => ['np.pro_id' => 'ppv_pro_id'],
            '[>]na_vehicle_base(vb)' => ['ppv.ppv_base_id' => 'base_id'],
        ];
        $where['GROUP'] = ['fac_id'];
        if(isset($params['base_cate'])){
            $cateNames = explode(',', (string)$params['base_cate']);
            $cateNames = array_values(array_filter(array_map('trim', $cateNames), function ($name) {
                return $name !== '';
            }));
            if (!empty($cateNames)) {
                $where['np.pro_name'] = $cateNames;
            }
        }
        if (isset($params['year'])) {
            $yearIds = explode(',', (string)$params['year']);
            $yearIds = array_values(array_filter(array_map('trim', $yearIds), function ($id) {
                return $id !== '';
            }));
            if (!empty($yearIds)) {
                $where['vb.base_year_id'] = $yearIds;
            }
        }
        if (isset($params['base_make_id'])) {
            $makeIds = explode(',', (string)$params['base_make_id']);
            $makeIds = array_values(array_filter(array_map('trim', $makeIds), function ($id) {
                return $id !== '';
            }));
            if (!empty($makeIds)) {
                $where['vb.base_make_id'] = $makeIds;
            }
        }
        if (isset($params['base_model_id'])) {
            $modelIds = explode(',', (string)$params['base_model_id']);
            $modelIds = array_values(array_filter(array_map('trim', $modelIds), function ($id) {
                return $id !== '';
            }));
            if (!empty($modelIds)) {
                $where['vb.base_model_id'] = $modelIds;
            }
        }
        $fields = [
            'fac_id',
            'fac_name',
            'pro_count' => raw('COUNT(DISTINCT np.pro_id)'),
        ];
        return $this->db->select($table, $join, $fields, $where);
    }

    /**
     * @method 获取北美品牌下的产品列表信息
     * @author hongzhang
     * @copyright 2026-03-11
     */
    function getNaProListByBrand($params)
    {
        $filters = $params['filters'];
        $page = $params['page'];
        $pagesize = $params['rows'];
        $sidx = empty($params['sidx']) ? '' : $params['sidx'];
        $sord = empty($params['sord']) ? 'asc' : $params['sord'];
        $orderby = $params['orderby'];
        $refiled = [];
        $this->set('refiled', $refiled);
        $sidx = strtr($sidx, $refiled);
        $table = 'napro_product(np)';
        $join = null;
        // 匹配规则：
        // 1) 取 napro_product_number 中 ppn_pro_id = pro_id 的所有号码
        // 2) 与 oe_numidx + pro_factory 比对：
        //    on_formart = ppn_format 且 pf_name = ppn_factory
        $matchExistsSql = "EXISTS (
            SELECT 1
            FROM napro_product_number npn
            JOIN pro_factory pf ON pf.pf_name = npn.ppn_factory
            JOIN oe_numidx oen ON oen.on_pf_id = pf.pf_id
                AND oen.on_formart = npn.ppn_format
            WHERE npn.ppn_pro_id = np.pro_id
        )";
        // 统一定义“第一个匹配零件”，用于图片等扩展筛选
        $firstMatchOeIdSql = "(
            SELECT MIN(oen.on_oe_id)
            FROM napro_product_number npn
            LEFT JOIN pro_factory pf ON pf.pf_name = npn.ppn_factory
            LEFT JOIN oe_numidx oen ON oen.on_pf_id = pf.pf_id
                AND oen.on_formart = npn.ppn_format
            WHERE npn.ppn_pro_id = np.pro_id
        )";
        $where = $this->filter2medoo($filters, function (&$field, &$op, &$data) use ($matchExistsSql, $firstMatchOeIdSql) {
            $field = strtr($field, $this->get('refiled'));
            switch ($field) {
                case 'oe_oe':
                    if ($data === '' || $data === null) {
                        $op = null;
                        break;
                    }
                    $op = 'RAW_' . $field;
                    if ($data == 1 || $data === '1') {
                        $data = raw($matchExistsSql);
                    } else {
                        $data = raw("NOT {$matchExistsSql}");
                    }
                    break;
                case 'pro_picture':
                    if ($data === '' || $data === null) {
                        $op = null;
                        break;
                    }
                    $op = 'RAW_' . $field;
                    if ($data == 1 || $data === '1') {
                        $data = raw("(pro_picture IS NOT NULL AND TRIM(pro_picture) NOT IN ('', '0', '[]'))");
                    } else {
                        $data = raw("(pro_picture IS NULL OR TRIM(pro_picture) IN ('', '0', '[]'))");
                    }
                    break;
                case 'oe_pic':
                    if ($data === '' || $data === null) {
                        $op = null;
                        break;
                    }
                    $op = 'RAW_' . $field;
                    if ($data == 1) {
                        $data = raw("EXISTS (
                            SELECT 1
                            FROM oe_pic op
                            JOIN files f ON op.pic_fileid = f.fileid
                            WHERE op.pic_type = 'img'
                              AND op.pic_oe_id = {$firstMatchOeIdSql}
                        )");
                    } else {
                        $data = raw("NOT EXISTS (
                            SELECT 1
                            FROM oe_pic op
                            JOIN files f ON op.pic_fileid = f.fileid
                            WHERE op.pic_type = 'img'
                              AND op.pic_oe_id = {$firstMatchOeIdSql}
                        )");
                    }
                    break;
                case 'cate_name':
                    if ($data === '' || $data === null) {
                        $op = null;
                        break;
                    }
                    $inputOp = $op;
                    $op = 'RAW_' . $field;
                    $cateField = 'pc.' . cateName();
                    $rawData = (string)$data;
                    $quotedEq = $this->db->quote($rawData);
                    $likeVal = '%' . addcslashes($rawData, "\\%_") . '%';
                    $quotedLike = $this->db->quote($likeVal);
                    if ($inputOp === 'eq') {
                        $cateCond = "{$cateField} = {$quotedEq}";
                    } elseif ($inputOp === 'ne') {
                        $cateCond = "{$cateField} <> {$quotedEq}";
                    } elseif ($inputOp === 'nc') {
                        $cateCond = "{$cateField} NOT LIKE {$quotedLike} ESCAPE '\\\\'";
                    } else {
                        $cateCond = "{$cateField} LIKE {$quotedLike} ESCAPE '\\\\'";
                    }
                    // 按“第一个匹配零件”的小类进行筛选
                    $data = raw("EXISTS (
                        SELECT 1
                        FROM oe_item oi
                        JOIN pro_cate pc ON oi.oe_cate_id = pc.id
                        WHERE oi.oe_id = {$firstMatchOeIdSql}
                          AND {$cateCond}
                    )");
                    break;
                case 'has_na_model':
                    if ($data === '' || $data === null) {
                        $op = null;
                        break;
                    }
                    $op = 'RAW_' . $field;
                    if ($data == 1 || $data === '1') {
                        $data = raw("EXISTS (
                            SELECT 1
                            FROM oe_model_na omna
                            WHERE omna.oml_oe_id = {$firstMatchOeIdSql}
                        )");
                    } else {
                        $data = raw("NOT EXISTS (
                            SELECT 1
                            FROM oe_model_na omna
                            WHERE omna.oml_oe_id = {$firstMatchOeIdSql}
                        )");
                    }
                    break;
            }
        });
        $facIds = !empty($params['fac_id']) ? explode(',', $params['fac_id']) : [];
        $facIds = array_values(array_filter(array_map('trim', $facIds), function ($id) {
            return $id !== '';
        }));
        if (empty($facIds)) {
            return [
                'page' => (int)$page,
                'total' => 0,
                'records' => 0,
                'rows' => [],
            ];
        }
        if (!is_array($where)) {
            $where = [];
        }
        $where['pro_fac_id'] = $facIds;
        $cateNames = [];
        if (isset($params['base_cate'])) {
            $cateNames = explode(',', (string)$params['base_cate']);
            $cateNames = array_values(array_filter(array_map('trim', $cateNames), function ($name) {
                return $name !== '';
            }));
        }
        $yearIds = [];
        if (isset($params['year'])) {
            $yearIds = explode(',', (string)$params['year']);
            $yearIds = array_values(array_filter(array_map('intval', $yearIds), function ($id) {
                return $id > 0;
            }));
        }
        $makeIds = [];
        if (isset($params['base_make_id'])) {
            $makeIds = explode(',', (string)$params['base_make_id']);
            $makeIds = array_values(array_filter(array_map('intval', $makeIds), function ($id) {
                return $id > 0;
            }));
        }
        $modelIds = [];
        if (isset($params['base_model_id'])) {
            $modelIds = explode(',', (string)$params['base_model_id']);
            $modelIds = array_values(array_filter(array_map('intval', $modelIds), function ($id) {
                return $id > 0;
            }));
        }
        if (!empty($cateNames) || !empty($yearIds) || !empty($makeIds) || !empty($modelIds)) {
            $vehicleConds = [];
            if (!empty($cateNames)) {
                // 先转义
                $quotedCateNames = array_map(function ($name) {
                    return $this->db->quote((string)$name);
                }, $cateNames);
                $vehicleConds[] = 'np.pro_name IN (' . implode(',', $quotedCateNames) . ')';
            }
            if (!empty($yearIds)) {
                $vehicleConds[] = 'vb.base_year_id IN (' . implode(',', $yearIds) . ')';
            }
            if (!empty($makeIds)) {
                $vehicleConds[] = 'vb.base_make_id IN (' . implode(',', $makeIds) . ')';
            }
            if (!empty($modelIds)) {
                $vehicleConds[] = 'vb.base_model_id IN (' . implode(',', $modelIds) . ')';
            }
            $where['RAW_vehicle_filter'] = raw("EXISTS (
                SELECT 1
                FROM napro_product_vehicle ppv
                JOIN na_vehicle_base vb ON ppv.ppv_base_id = vb.base_id
                WHERE ppv.ppv_pro_id = np.pro_id
                  AND " . implode(' AND ', $vehicleConds) . "
            )");
        }
        $where = $this->listWhere($where, $page, $pagesize, $sidx, $sord, $orderby);
        if ($page > 0 && $pagesize > 0) {
            $fields = '*';
            $pages = $this->paging($table, $join, $fields, $where, $page, $pagesize);
            $where["LIMIT"] = [$pages['limit'], $pagesize];
        }
        $fields = [
            'pro_id',
            'pro_realoem',
            'pro_name',
            'pro_picture',
        ];
        $arr = $this->db->select($table, $join, $fields, $where);
        if (!empty($arr)) {
            $proIds = array_column($arr, 'pro_id');
            // 获取所有可能存在于零件库中的零件信息
            $existPoeList = $this->getExistPoeList($proIds);
            // dump($existPoeList);
            $oeIds = array_values(array_unique(array_column($existPoeList, 'oe_id')));
            $existPoeArr = [];
            foreach ($existPoeList as $v) {
                $existPoeArr[$v['pro_id']][] = $v;
            }
            if(empty($oeIds)){
               $picRes = [];
               $hasNaModelRes = [];
            }else{
                 // oe主图
                $picRes = $this->db->select('oe_pic', ['[><]files' => ['pic_fileid' => 'fileid']], '*', ['pic_oe_id' => $oeIds, 'pic_type' => 'img', 'pic_ismain' => 1]);
                // 是否有北美模型
                $hasNaModelRes = $this->db->select('oe_model_na', ['oml_oe_id'], ['oml_oe_id' => $oeIds, 'GROUP' => ['oml_oe_id']]);
            }
            $picArr = [];
            foreach ($picRes as $pic) {
                if ($pic['pic_type'] == 'img' && $pic['filetype'] == 'image') {
                    $picArr[$pic['pic_oe_id']]['bigImg'] = $pic['filepath'] . '/' . $pic['filebasename'] . 'big.' . $pic['fileextname'];
                    $picArr[$pic['pic_oe_id']]['smallImg'] = $pic['filepath'] . '/' . $pic['filebasename'] . 'small.' . $pic['fileextname'];
                    if ($params['isExport']) {
                        $picArr[$pic['pic_oe_id']]['type'] = 'image';
                        $picArr[$pic['pic_oe_id']]['filename'] = \mvc::$cfg['dir']['files'] . '/' . $picArr[$pic['pic_oe_id']]['smallImg'];

                        list($width, $height, $type, $attr) = getimagesize($picArr[$pic['pic_oe_id']]['filename']);
                        $picArr[$pic['pic_oe_id']]['widthScale'] = 1;
                        $picArr[$pic['pic_oe_id']]['heightScale'] = 1;
                        $picArr[$pic['pic_oe_id']]['rowHeight'] = $height;
                    }
                }
            }
            $hasNaModelArr = array_flip(array_column($hasNaModelRes, 'oml_oe_id'));
            foreach ($arr as &$v) {
                // 产品图片
                if (!empty($v['pro_picture'])) {
                    $paths = json_decode($v['pro_picture'], true);
                    if (is_array($paths) && count($paths) > 0) {
                        $v['pro_picture'] = $paths;
                    } else {
                        $v['pro_picture'] = '';
                    }
                }
                // 存在的零件库信息,默认选中第一个存在的零件库信息展示
                $html = '<div class="napro-poe-cell">';
                $poeList = $existPoeArr[$v['pro_id']] ?? [];
                $displayOeId = !empty($poeList) ? (int)$poeList[0]['oe_id'] : 0;
                $selectedTargetOeId = 0;
                if (!empty($poeList)) {
                    // 仅有一个匹配零件时，默认可直接作为目标零件
                    if (count($poeList) == 1) {
                        $selectedTargetOeId = (int)$poeList[0]['oe_id'];
                    }
                }
                $selectedCateName = '';
                foreach ($poeList as $poe) {
                    if ((int)$poe['oe_id'] === $displayOeId) {
                        $selectedCateName = $poe['cat_name'] ?? '';
                        break;
                    }
                }
                if ($selectedCateName === '' && !empty($poeList)) {
                    $selectedCateName = $poeList[0]['cat_name'] ?? '';
                }
                $v['cate_name'] = $selectedCateName;
                // 选中
                $isMultiPoe = count($poeList) > 1;
                foreach ($poeList as $poe) {
                    $poeId = (int)$poe['oe_id'];
                    $checked = $selectedTargetOeId > 0 && $selectedTargetOeId === $poeId ? ' checked' : '';
                    $name = 'oe_id[' . (int)$v['pro_id'] . ']';
                    $jsTitle = addslashes((string)$poe['pf_name'] . ':' . (string)$poe['oe_number']);
                    $text = htmlspecialchars((string)$poe['pf_name'], ENT_QUOTES) . ':' . htmlspecialchars((string)$poe['oe_number'], ENT_QUOTES);
                    $html .= '<span style="display:inline-flex;align-items:center;">';
                    if ($isMultiPoe) {
                        $html .= '<input type="radio" name="' . $name . '" value="' . $poeId . '"' . $checked . ' style="margin-right:6px;">';
                    }
                    $html .= '<a href="javascript:openOeSet(' . $poeId . ',\'' . $jsTitle . '\');" title="详情">' . $text . '</a>';
                    $html .= '</span><br>';
                }
                // 添加绑定零件按钮
                $html .= '<span class="napro-poe-actions" style="display:inline-flex;align-items:center;">';
                $html .= '<button type="button" class="btn btn-outline-primary btn-sm napro-refer-btn js-open-refer-dialog" data-pro-id="' . (int)$v['pro_id'] . '">绑定零件</button>';
                $html .= '</span>';
                $v['caption']['oe_oe'] = $html . '</div>';
                // 零件主图
                $v['oe_pic'] = $picArr[$displayOeId] ?? '';
                // 是否有北美模型
                $v['has_na_model'] = isset($hasNaModelArr[$displayOeId]) ? 'Y' : 'N';
            }
        }
        $data = [
            'page' => $page,
            'total' => $pages['total'],
            'records' => $pages['records'],
            'rows' => $arr
        ];
        return $data;
    }

    /**
     * @method 获取北美品牌下的产品详情信息
     * @author hongzhang
     * @copyright 2026-03-11
     */
    function getNaProDetail($naProId)
    {
        // 获取参数信息
        $proCommonInfo = $this->db->get(
            'napro_product',
            [
                '[>]napro_factory' => ['pro_fac_id' => 'fac_id'],
            ],
            ['pro_id', 'pro_name', 'pro_picture', 'pro_param', 'fac_name', 'pro_format'],
            ['pro_id' => $naProId]
        );
        if (!empty($proCommonInfo['pro_picture'])) {
            $paths = json_decode($proCommonInfo['pro_picture'], true);
            if (is_array($paths) && count($paths) > 0) {
                $proCommonInfo['pro_picture'] = $paths;
            } else {
                $proCommonInfo['pro_picture'] = [];
            }
        }
        if (!empty($proCommonInfo['pro_param'])) {
            $params = json_decode($proCommonInfo['pro_param'], true);
            if (is_array($params) && count($params) > 0) {
                $proCommonInfo['pro_param'] = $params;
            } else {
                $proCommonInfo['pro_param'] = '';
            }
        }
        $existPoeList = [];
        $existPoeList = $this->getExistPoeList($naProId);
        // 获取对照号信息
        $proNumJoin = [
            '[>]pro_factory(pf)' => ['ppn_factory' => 'pf_name'],
            '[>]napro_product(np)' => ['ppn_pro_id' => 'pro_id'],
            '[>]oe_numidx(on)' => ['pf.pf_id' => 'on_pf_id','ppn_format' => 'on_formart'],
            '[>]oe_item(oi2)' =>['on.on_oe_id' => 'oe_id'],
            '[>]pro_factory(pf2)' => ['oi2.oe_pf_id' => 'pf_id'],
        ];
        
        $proNumField =  ['ppn_id','ppn_main', 'ppn_number', 'ppn_format', 'ppn_factory', 'ppn_make','oi2.oe_id(link_oe_id)','pf2.pf_name(link_oe_pf_name)','oi2.oe_oe(link_oe_oe)'];
        $proNumInfoRaw = $this->db->select('napro_product_number',$proNumJoin,$proNumField,['ppn_pro_id' => $naProId]);
        $proNumInfo = [];
        $existPoeCount = [];
        foreach ($proNumInfoRaw as $row) {
            $ppnId = $row['ppn_id'];
            $rowHasLink = !empty($row['link_oe_id']);
            if ($rowHasLink) {
                if(!isset($proNumInfo[$ppnId])){
                     $proNumInfo[$ppnId] = [
                        'ppn_id' => $row['ppn_id'],
                        'ppn_main' => $row['ppn_main'],
                        'ppn_number' => $row['ppn_number'],
                        'ppn_format' => $row['ppn_format'],
                        'ppn_factory' => $row['ppn_factory'],
                        'ppn_make' => $row['ppn_make'],
                    ];
                }
                $proNumInfo[$ppnId]['link_oe'][] = [
                    'link_oe_id' => $row['link_oe_id'],
                    'link_oe_pf_name' => $row['link_oe_pf_name'],
                    'link_oe_oe' => $row['link_oe_oe'],
                ];
                $existPoeCount[$row['link_oe_id']] = isset($existPoeCount[$row['link_oe_id']]) ? $existPoeCount[$row['link_oe_id']] + 1 : 1;
                continue;
            }
            
            if (!isset($proNumInfo[$ppnId])) {
                $proNumInfo[$ppnId] = $row;
                continue;
            }
        }
        $proNumInfo = array_values($proNumInfo);
        // 获取车型信息
        $proModelInfo = $this->db->select(
            'napro_product_vehicle',
            ['[><]na_vehicle_base' => ['ppv_base_id' => 'base_id']],
            ['ppv_id','base_id', 'base_year_id', 'base_make_id', 'base_make_name', 'base_model_id', 'base_model_name', 'ppv_pos_id', 'ppv_attrs', 'ppv_remark'],
            ['ppv_pro_id' => $naProId, 'ORDER' => ['base_year_id' => 'DESC']]
        );

        // 对于检索出零件库中匹配的数据，绑定匹配的第一个零件的小类
        if(count($existPoeList)){
            $proCommonInfo['cat_id'] = $existPoeList[0]['cat_id'];
            $proCommonInfo['cat_name'] = $existPoeList[0]['cat_name'];
        }
        return [
            'baseInfo' => $proCommonInfo,
            'nummber' => $proNumInfo,
            'model' => $proModelInfo,
            'existPoe' => $existPoeList,
            'existPoeCount' => $existPoeCount,
        ];
    }

    /**
     * @method 保存产品的零件信息
     * @author hongzhang
     * @copyright 2026-03-12
     */
    function saveOePro($params)
    {
        $syncParam = ($params['sync_param'] ?? 0) == 1 ? 1 : 0;
        $naProId = $params['pro_id'];
        $proCateid = $params['pro_cat_id'];

        if(!$proCateid)exitJson('请先完善号码小类');
        //小类信息
        $cateFeilds = ['id'];
        $cateFeilds = langSqlFields($cateFeilds,'cat_', 'cat.');
        $cateItem = $this->db->get('pro_cate(cat)',$cateFeilds,['id' => $proCateid]);
        $opuser = getOpuser();
		$datetime = getNowTime();
        $oeNumidx = new \model\oeNumidx();
        $oe = new oe();
        $isNew = false;
        $res = $this->getOeFormat($params);
        $uniNums = $res['addNums'];
        $incorrectNums = $res['incorrectNums'];
        $uniNamodels = $res['addNamodels'];
        $uniNamodelLinks = $res['addNamodelLinks'];
        if($params['oe_id'] == -1){
            $isNew = true;
        }else{
            $hasPoe = [];
            if($uniNums){
                foreach($uniNums as $row){
                    $sql = sprintf("SELECT oe_id, oe_oe FROM oe_numidx
						JOIN oe_item ON on_oe_id=oe_id 
						WHERE on_formart='%s' and on_pf_id=%d and oe_cate_id=%d group by oe_id", $row['on_formart'], $row['on_pf_id'], $proCateid);
                    $row['poes'] = $this->db->query($sql)->fetchAll();
                    if($row['poes']){
                        $hasPoe = array_merge($hasPoe, $row['poes']);
                    }
                }
            }
            
            $hasPoe = array_values(array_column($hasPoe, null, 'oe_id'));
            if(empty($hasPoe)) $isNew = true;
            if($params['oe_id']){
                if(!in_array($params['oe_id'], array_column($hasPoe, 'oe_id'))){
                    exitJson('零件ID：'.$params['oe_id'].'不存在于检测零件中，请核查');
                }else{
                    $oe_id = (int) $params['oe_id'];
                }
            }
            if(!$oe_id && count($hasPoe) > 1) exitJson('存在多个零件，请到已确认北美数据的详情审核');
        }

        $addBase = [
            'oe_cate_id'=>$proCateid,
            'oe_opuser'=>$opuser,
			'oe_update_time'=>$datetime,
        ];
       
        $this->db->Begin();
        $oldOeInfo = [];
        if($isNew){
            $addBase['oe_create_time'] = $datetime;
            //名称引用分类
			$addBase = langGetVals($addBase, $cateItem, ['oe_'=>'cat_']);
            $this->db->insert('oe_item', $addBase);
			$oe_id = $this->db->id();
        }else{
            $oe_id = $oe_id? $oe_id: $hasPoe[0]['oe_id'];
            $oldOeInfo = $this->db->get('oe_item', '*', ['oe_id'=>$oe_id]);
            //取用量
            if($oldOeInfo['oe_etk_info']){
                $oe_etk_info = json_decode($oldOeInfo['oe_etk_info'], true);
                if($oe_etk_info['para']){
                    foreach ($oe_etk_info['para'] as $pvlas) {
                        if($pvlas['name']=='用量'){
                            $addbase['oe_amount'] = $pvlas['val'];
                            break;
                        }
                    }
                }
            }
            $this->db->update('oe_item', $addBase, ['oe_id'=>$oe_id]);
        }
        //处理参考号
        if($uniNums){
            foreach($uniNums as $add){
                $chk = $this->db->get('oe_numidx(oen)', ["[>]oe_item(poe)" => ["oen.on_oe_id" =>"oe_id"]], ['on_id', 'on_mk_id', 'oe_id'], ['on_isborrow'=>0, 'oe_cate_id'=>$proCateid, 'on_pf_id'=>$add['on_pf_id'], 'on_formart'=>$add['on_formart']]);
                if($chk['oe_id'] && $chk['oe_id'] != $oe_id) exitJson('号码重复，零件ID：'.$chk['oe_id'].'已经存在号码'.$add['on_number']);
                if(empty($chk)){
                    $add['on_oe_id'] = $oe_id;
                    $add['on_opuser'] = $opuser;
                    $add['on_create_time'] = $datetime;
                    $add['on_update_time'] = $datetime;
                    $this->db->insert('oe_numidx', $add);
					$on_id = $this->db->id();
                }else{
                    $on_id = $chk['on_id']; 
                    if(isset($add['on_mk_id']) && $add['on_mk_id'] != $chk['on_mk_id']){
                        $add['on_mk_id'] = implode(',', array_unique(array_merge(explode(',', $add['on_mk_id']), explode(',', $chk['on_mk_id']))));
                        $this->db->update('oe_numidx', ['on_mk_id'=>$add['on_mk_id'], 'on_opuser'=>$opuser, 'on_update_time'=>$datetime], ['on_id'=>$on_id]);
                    }
                }
                if($add['on_pf_id'] == 1){
                    $tbIds = [];
                    $add['on_mk_id'] = trim($add['on_mk_id'], ',');
                    if(!empty($add['on_mk_id'])){
                        $ids = $this->db->select('tag_brand_make', 'tbm_tb_id', ['tbm_mk_id'=>explode(',', $add['on_mk_id'])]);
                        if($ids) $tbIds = $ids;
                    }else{
                        $ypApi = new ypApi();
                        $res = $ypApi->Get('etk/getNumberBrand', ['number'=>$add['on_formart']]);
                        if($res['data']){
                            $names = $res['data'];
                            $namesstr = implode("','", $names);
                            $sql = "SELECT DISTINCT tb_id FROM `tag_brand` WHERE tb_cn_name IN ('{$namesstr}') OR tb_en_name IN ('{$namesstr}') 
                            OR tb_id IN (SELECT DISTINCT tbm_tb_id FROM tag_brand_cnbrand JOIN m_cn_model ON brand_id = tbm_brand_id WHERE brand_name IN ('{$namesstr}'))
                            OR tb_id IN (SELECT DISTINCT tbm_tb_id FROM tag_brand_make JOIN m_make ON mk_id = tbm_mk_id WHERE mk_cn_name IN ('{$namesstr}') OR mk_en_name IN ('{$namesstr}'))";
                            $vals = $this->db->query($sql)->fetchAll();
                            if($vals) $tbIds = array_column($vals, 'tb_id');
                        }
                    }
                    $oeNumidx->saveOeNumTb($oe_id, $on_id,$tbIds);
                }
            }
        }

        //处理北美车型
        if($uniNamodels){
            foreach($uniNamodels as $add){
                // 验证唯一性
                $exsitWhere = ['oml_oe_id'=>$oe_id,'oml_base_id'=>$add['oml_base_id'],'oml_veh_id'=>$add['oml_veh_id'],'oml_pos'=>$add['oml_pos'],'oml_attrs'=>$add['oml_attrs'],'oml_remark'=>$add['oml_remark']];
                $exist = $this->db->get('oe_model_na','oml_id',$exsitWhere);
                if($exist) continue;
                $addArr = [
                    'oml_oe_id' => $oe_id,
                    'oml_base_id' => $add['oml_base_id'],
                    'oml_veh_id' => $add['oml_veh_id'],
                    'oml_pos' => $add['oml_pos'],
                    'oml_attrs' => $add['oml_attrs'],
                    'oml_remark' => $add['oml_remark'],
                    'oml_opuser' => $opuser,
                    'oml_from_id' => 100
                ];
                $this->db->insert('oe_model_na',$addArr);
                $oml_id = $this->db->id();
                if($oml_id){
                    $addLinkArr = $uniNamodelLinks[$add['link_ppv_id']];
                    if(!$addLinkArr) continue;
                    foreach($addLinkArr as &$link){
                        $link['ops_oml_id'] = $oml_id;
                        $link['ops_oe_id'] = $oe_id;
                    }
                    //验证关联表唯一性
                    $linkWhere = ['ops_oml_id'=>$oml_id,'ops_oe_id'=>$oe_id];
                    $linkExist = $this->db->get('oe_model_na_link','ops_id',$linkWhere);
                    if($linkExist) continue;
                    $this->db->insert('oe_model_na_link',$addLinkArr);
                }
            }
        }

        // 新增的话需要设置零件主号码
        if($isNew){
            $numTable = 'napro_product_number';
            $numJoin = [
                '[><]pro_factory(pf)' => ['ppn_factory' =>'pf_name'],
            ];
            $numFileds = ['pf_id','ppn_format'];
            $numWhere = ['ppn_pro_id' => $naProId, 'ppn_main'=>1];
            $mainNum = $this->db->get($numTable,$numJoin,$numFileds,$numWhere);
            //新增零件，主号码非OE，尝试号码库找OE
            if(isset($mainNum['pf_id']) && $mainNum['pf_id'] != 1){
                $main_on_id = $this->db->get('oe_numidx', 'on_id', ['on_pf_id'=>1, 'on_oe_id'=>$oe_id, 'ORDER'=>['on_id']]);
                if(!$main_on_id){
                    // 没找到oe号，则直接取用对应北美产品主号码为参考号
                    $main_on_id = $this->db->get('oe_numidx', 'on_id', ['on_pf_id'=>$mainNum, 'on_oe_id'=>$oe_id, 'on_formart'=>$mainNum['ppn_format']]);
                }
            }else{
                 $main_on_id = $this->db->get('oe_numidx', 'on_id', ['on_pf_id'=>$mainNum, 'on_oe_id'=>$oe_id, 'on_formart'=>$mainNum['ppn_format']]);
            }
            $oe->setOeMain($main_on_id);
        }

        $this->db->End();
        // if (!$syncParam) {
        //     return [];
        // }

        // $paramRow = $this->db->get('napro_product', ['pro_param'], ['pro_id' => $naProId]);
        // $paramToSync = !empty($paramRow['pro_param']) ? json_decode($paramRow['pro_param'], true) : [];
        // if (!is_array($paramToSync)) {
        //     $paramToSync = [];
        // }

        // $oeRow = $this->db->get('oe_item', ['oe_para'], ['oe_id' => $oeId]);
        // $oePara = !empty($oeRow['oe_para']) ? json_decode($oeRow['oe_para'], true) : [];
        // if (!is_array($oePara)) {
        //     $oePara = [];
        // }

        // $nameIndex = [];
        // foreach ($oePara as $idx => $item) {
        //     if (is_array($item) && isset($item['name'])) {
        //         $nameIndex[(string)$item['name']] = $idx;
        //     }
        // }

        // $updated = 0;
        // $added = 0;

        // foreach ($paramToSync as $name => $val) {
        //     $name = trim((string)$name);
        //     if ($name === '') {
        //         continue;
        //     }

        //     if (is_scalar($val) || $val === null) {
        //         $val = (string)$val;
        //     } else {
        //         $val = json_encode($val, JSON_UNESCAPED_UNICODE);
        //     }

        //     if (isset($nameIndex[$name])) {
        //         $i = $nameIndex[$name];
        //         if (!is_array($oePara[$i])) {
        //             $oePara[$i] = [];
        //         }
        //         $oePara[$i]['name'] = $name;
        //         $oePara[$i]['val'] = $val;
        //         if (!array_key_exists('unit', $oePara[$i])) $oePara[$i]['unit'] = '';
        //         if (!array_key_exists('cn_name', $oePara[$i])) $oePara[$i]['cn_name'] = '';
        //         $updated++;
        //     } else {
        //         $oePara[] = [
        //             'val' => $val,
        //             'name' => $name,
        //             'unit' => '',
        //             'cn_name' => ''
        //         ];
        //         $added++;
        //     }
        // }

        // $this->db->update('oe_item', ['oe_para' => json_encode(array_values($oePara), JSON_UNESCAPED_UNICODE)], ['oe_id' => $oeId]);
        return [
            'effect_oe' => $oe_id,
            'incorrectNums'=> $incorrectNums
        ];
    }

    /**
     * @method 获取北美车型列表
     * @author hongzhang
     * @copyright 2026-03-12
     */
    function getModelnaList($req)
    {
        $pId = $req['pId'] ?? 0;
        $join = [
            '[>]na_vehicle_base' => ['pml_base_id' => 'base_id']
        ];
        $fields = ['base_id', 'base_make_name', 'base_model_name', 'base_year_id', 'pml_pos', 'pml_attrs', 'pml_remark', 'pml_from_id', 'pml_opuser', 'pml_update_time'];
        $naModelnaList = $this->db->select('pro_model_na', $join, $fields, ['pml_p_id' => $pId]);
        return $naModelnaList;
    }

    /**
     * @method 根据北美产品id获取可能存在的零件库信息
     * @author hongzhang
     * @copyright 2026-03-18
     */
    function getExistPoeList($naProIds,$proCateId = 0)
    {
        if (!is_array($naProIds)) {
            $naProIds = [$naProIds];
        }
        $existPoeList = [];
        $existPoeJoin = [
            '[><]napro_product_number(npn)'=> ['np.pro_id'=>'ppn_pro_id'],
            '[>]pro_factory(pf)' => ['npn.ppn_factory' => 'pf_name'],
            '[><]oe_numidx(on)' => ['npn.ppn_format' => 'on_formart', 'pf.pf_id' => 'on_pf_id'],
            '[>]oe_numidx(on2)' => ['on.on_oe_id' => 'on_oe_id', '1' => "@on2.on_ismain = 'Y'"],
            '[>]pro_factory(pf2)' => ['on2.on_pf_id' => 'pf_id'],
            '[>]oe_item(oi)' => ['on2.on_oe_id' => 'oe_id'],
            '[>]pro_cate(cat)' => ['oi.oe_cate_id' => 'id'],
        ];
        $existPoeFields = ['np.pro_id', 'on2.on_oe_id(oe_id)', 'on2.on_number(oe_number)', 'on2.on_formart(oe_formart)', 'pf2.pf_name(pf_name)', 'cat.id(cat_id)', 'cat.' . LG_NAME . '(cat_name)'];
        $existPoeWhere = ['pro_id' => $naProIds];
        // 列表页会一次传入多个pro_id，需按 pro_id+oe_id 分组，避免同oe被不同产品“抢占”后丢行
        $existPoeWhere['GROUP'] = ['np.pro_id', 'on2.on_oe_id'];
        if($proCateId != 0){
            $existPoeWhere['cat.id'] = $proCateId;
        }
        $existPoeList = $this->db->select('napro_product(np)', $existPoeJoin, $existPoeFields, $existPoeWhere);
        return $existPoeList;
    }

    /**
     * @method 设置产品的零件参照
     * @author hongzhang
     * @copyright 2026-03-19
     */
    function setReferPoe($naProId,$fac,$formatNum)
    {
        $row = $this->db->get('napro_product(np)', ['[>]napro_factory'=>['np.pro_fac_id'=>'fac_id']],['fac_name', 'pro_format'], ['pro_id' => $naProId]);
        if(empty($row)){
           return ['success'=>false,'message'=>'产品不存在'];
        }
        $facId = $this->db->get('pro_factory', ['pf_id'], ['pf_name'=>$fac]);
        if(empty($facId)){
            return ['success'=>false,'message'=>'工厂不存在'];
        }
        $existOeNum = $this->db->get('oe_numidx', ['on_oe_id'], ['on_formart' => $formatNum,'on_pf_id'=>$facId['pf_id']]);
        if(empty($existOeNum)){
            return ['success'=>false,'message'=>'找不到输入号码对应的零件'];
        }
        $existProFac = $this->db->get('pro_factory', ['pf_id'], ['pf_name'=>$row['fac_name']]);
        if(empty($existProFac)){
            return ['success'=>false,'message'=>'北美产品厂商不存在'];
        }
        // 再确认一遍是否已经添加过这条北美零件的参考号
        $addedNaPoe = $this->db->get('oe_numidx', ['on_oe_id'], ['on_oe_id'=>$existOeNum['on_oe_id'],'on_pf_id'=>$existProFac['pf_id'],'on_formart'=>$row['pro_format']]);
        if(!empty($addedNaPoe)){
            return ['success'=>false,'message'=>'北美零件已存在，无需重复设置'];
        }
        $addNum = [
            'on_oe_id' => $existOeNum['on_oe_id'],
            'on_pf_id' => $existProFac['pf_id'],
            'on_number' => $row['pro_format'],
            'on_formart' => $row['pro_format'],
            'on_opuser' => getOpUser(),
            'on_create_time' =>getNowTime(),
            'on_update_time' =>getNowTime(),
        ];
        $this->db->insert('oe_numidx', $addNum);
        return ['success'=>true,'message'=>'设置成功'];
    }

    /**
     * @method 批量保存前校验北美产品的目标零件
     * @author hongzhang
     * @copyright 2026-04-18
     */
    function validateBatchSavePlan($params)
    {
        $proIds = $params['pro_ids'] ?? [];
        if (!is_array($proIds)) {
            $proIds = explode(',', (string)$proIds);
        }
        $proIds = array_values(array_filter(array_map('intval', $proIds), function ($id) {
            return $id > 0;
        }));
        if (empty($proIds)) {
            return [
                'items' => [],
                'unmatchedIds' => [],
                'multiUnselectedIds' => [],
            ];
        }

        $selectedOeMap = $params['selected_oe_map'] ?? [];
        if (is_string($selectedOeMap)) {
            $decoded = json_decode($selectedOeMap, true);
            if (is_array($decoded)) {
                $selectedOeMap = $decoded;
            } else {
                $selectedOeMap = [];
            }
        }
        if (!is_array($selectedOeMap)) {
            $selectedOeMap = [];
        }
        $selectedOeMap = array_map('intval', $selectedOeMap);

        $existPoeList = $this->getExistPoeList($proIds);
        $poeMap = [];
        foreach ($existPoeList as $row) {
            $pid = (int)$row['pro_id'];
            if (!isset($poeMap[$pid])) {
                $poeMap[$pid] = [];
            }
            $poeMap[$pid][] = $row;
        }

        $items = [];
        $unmatchedIds = [];
        $multiUnselectedIds = [];
        foreach ($proIds as $proId) {
            $poeList = $poeMap[$proId] ?? [];
            if (empty($poeList)) {
                $unmatchedIds[] = $proId;
                continue;
            }
            if (count($poeList) == 1) {
                $only = $poeList[0];
                $items[] = [
                    'pro_id' => $proId,
                    'oe_id' => (int)$only['oe_id'],
                    'pro_cat_id' => (int)$only['cat_id'],
                    'cat_name' => (string)($only['cat_name'] ?? ''),
                    'oe_title' => (string)($only['pf_name'] . ':' . $only['oe_number']),
                ];
                continue;
            }

            $selectedOeId = (int)($selectedOeMap[$proId] ?? ($selectedOeMap[(string)$proId] ?? 0));
            if ($selectedOeId <= 0) {
                $multiUnselectedIds[] = $proId;
                continue;
            }

            $selectedRow = null;
            foreach ($poeList as $poe) {
                if ((int)$poe['oe_id'] === $selectedOeId) {
                    $selectedRow = $poe;
                    break;
                }
            }
            if (!$selectedRow) {
                $multiUnselectedIds[] = $proId;
                continue;
            }

            $items[] = [
                'pro_id' => $proId,
                'oe_id' => $selectedOeId,
                'pro_cat_id' => (int)$selectedRow['cat_id'],
                'cat_name' => (string)($selectedRow['cat_name'] ?? ''),
                'oe_title' => (string)($selectedRow['pf_name'] . ':' . $selectedRow['oe_number']),
            ];
        }

        return [
            'items' => $items,
            'unmatchedIds' => $unmatchedIds,
            'multiUnselectedIds' => $multiUnselectedIds,
        ];
    }

    /**
     * @method 获取北美产品需要同步到零件库的相关信息
     * @author hongzhang
     * @copyright 2026-03-20
     */
    function getOeFormat($params){
        $factory = new factory();
        // 获取号码相关信息
        $naproId = $params['pro_id'];
        $numChkIds = $params['num_ok_chk'] ?? [];
        $namodelChkIds = $params['na_model_chk'] ?? [];
        $syncNumAll = ($params['sync_num_all'] ?? 0) == 1;
        $syncModelAll = ($params['sync_model_all'] ?? 0) == 1;
        if (!is_array($numChkIds)) {
            $numChkIds = [];
        }
        if (!is_array($namodelChkIds)) {
            $namodelChkIds = [];
        }

        // 如果没有带上号码，则自动带上产品本身的主号
        $mainNum = $this->db->get('napro_product_number','ppn_id',['ppn_main' => 1,'ppn_pro_id'=>$naproId]);
        if ($mainNum) {
            $numChkIds[] = $mainNum;
        }
        // 外加上已经匹配到的号码
        $matchNums = $this->db->select('napro_product_number(npn)',
            [
                '[>]pro_factory(pf)' => ['npn.ppn_factory' => 'pf_name'],
                '[><]oe_numidx(on)' => ['npn.ppn_format' => 'on_formart', 'pf.pf_id' => 'on_pf_id']
            ],
            'ppn_id',
            ['ppn_pro_id'=>$naproId]
        );

        $numChkIds = array_merge($numChkIds, $matchNums);

        $numChkIds = array_values(array_unique(array_filter(array_map('intval', $numChkIds), function ($id) {
            return $id > 0;
        })));
        $numTable = 'napro_product_number';
        $numJoin = [
            '[>]m_make(mm)' => ['ppn_make' => 'mk_en_name']
        ];
        $numFileds = ['ppn_id','ppn_factory','ppn_number','ppn_main','mk_id'];
        $numWhere = ['ppn_pro_id' => $naproId];
        if (!$syncNumAll) {
            $numWhere['ppn_id'] = $numChkIds;
        }
        $numList = $this->db->select($numTable,$numJoin,$numFileds,$numWhere);
        $addNums = [];
        foreach($numList as $item){
            $pfid = $item['ppn_factory'] == 'OE'? 1: $factory->getFacId($item['ppn_factory'], 'add');
            $addNums[] = [
                'on_pf_id' => $pfid,
                'on_number' => $item['ppn_number'],
                'on_formart' => formatNum( $item['ppn_number']),
                'on_mk_id' => $item['mk_id']??[],
                'on_from'=>100,
            ];
        }

        // 获取选中的北美车型相关信息
        $namodelTable = 'napro_product_vehicle';
        $namodelFeild = ['ppv_id','ppv_base_id','ppv_veh_id','ppv_pos_id','ppv_attrs','ppv_remark'];
        $namodelWhere = ['ppv_pro_id' => $naproId];
        $namodelList = [];
        $addNamodels = [];
        if (!$syncModelAll && count($namodelChkIds) > 0) {
            // 详情界面保存，且选中了北美车型
            $namodelChkIds = array_values(array_unique(array_filter(array_map('intval', $namodelChkIds), function ($id) {
                return $id > 0;
            })));
            $namodelWhere['ppv_id'] = $namodelChkIds;
            $namodelList = $this->db->select($namodelTable,[],$namodelFeild,$namodelWhere);
        }else if($syncModelAll){
            // 列表页面批量保存，且选中了车型选项
            $namodelList = $this->db->select($namodelTable,[],$namodelFeild,$namodelWhere);
        }
        foreach($namodelList as $item){
            $addNamodels[] = [
                'oml_base_id' => $item['ppv_base_id'],
                'oml_veh_id' => $item['ppv_veh_id'],
                'oml_pos' => $item['ppv_pos_id'],
                'oml_attrs' => $item['ppv_attrs'],
                'oml_remark' => $item['ppv_remark'],
                'link_ppv_id' => $item['ppv_id'], //这个字段用于同步后续的link表
            ];
        }

        // 获取选中北美车型详情链接相关信息
        $namodelLinkTable = 'napro_product_links';
        $namodelLinkFeild = ['pps_ppv_id','pps_type','pps_cat','pps_dataid'];
        $namodelLinkWhere = ['pps_pro_id' => $naproId];
        $namodelLinkList = [];
        $addNamodelLinks = [];
        if (!$syncModelAll && count($namodelChkIds) > 0) {
            // 详情界面保存，且选中了北美车型
            $namodelLinkWhere['pps_ppv_id'] = $namodelChkIds;
            $namodelLinkList = $this->db->select($namodelLinkTable,[],$namodelLinkFeild,$namodelLinkWhere);
        }else if($syncModelAll){
            // 列表页面批量保存，且选中了车型选项
            $namodelLinkList = $this->db->select($namodelLinkTable,[],$namodelLinkFeild,$namodelLinkWhere);
        }
        foreach($namodelLinkList as $item){
            $addNamodelLinks[$item['pps_ppv_id']][] = [
                'ops_type' => $item['pps_type'],
                'ops_cat' => $item['pps_cat'],
                'ops_dataid' => $item['pps_dataid'],
            ];
        }

        return [
            'addNums' => $addNums,
            'incorrectNums' => [],
            'addNamodels' => $addNamodels,
            'addNamodelLinks' => $addNamodelLinks,
        ];
    }

    /**
     * @method 删除零件绑定的北美车型
     * @author hongzhang
     * @copyright 2026-04-17
     */
    function delNaModelData($req){
        $ids = $req['ids'] ?? [];
        if (!is_array($ids)) {
            $ids = explode(',', (string)$ids);
        }
        $ids = array_values(array_filter(array_map('intval', $ids), function ($id) {
            return $id > 0;
        }));
        if (empty($ids)) {
            return false;
        }
        $this->db->delete('oe_model_na', ['oml_id' => $ids]);
        $this->db->delete('oe_model_na_link', ['ops_oml_id' => $ids]);
        return true;
    }

    /**
     * @method 获取所有北美车型相关筛选项（年份，品牌，产品品类）
     * @author hongzhang
     * @copyright 2026-04-24
     */
    function getSelectOptionList(){
        $table = 'na_vehicle_base';
        $selectOptionList = [];
        $join = ['[><]napro_product_vehicle' => ['base_id' => 'ppv_base_id']];
        $selectOptionList['year'] = $this->db->select($table, $join, ['base_year_id'], ['GROUP' => 'base_year_id', 'ORDER' => ['base_year_id' => 'DESC']]);
        $selectOptionList['make'] = $this->db->select($table, $join, ['base_make_id','base_make_name'], ['GROUP'=>'base_make_id','ORDER'=>['base_make_name'=>'ASC']]);
        
        // 获取北美产品品类
        $selectOptionList['cate'] = $this->db->select('napro_product', ['pro_name', 'count' => raw('COUNT(*)')], ['GROUP' => 'pro_name', 'ORDER' => ['count' => 'DESC'], 'LIMIT'=>50]);
        
        $selectOptionList['yearCount'] = count($selectOptionList['year']);
        $selectOptionList['makeCount'] = count($selectOptionList['make']);
        $selectOptionList['cateCount'] = count($selectOptionList['cate']);
        return $selectOptionList;
    }

    /**
     * @method 获取北美汽车品牌下的所有车型
     * @author hongzhang
     * @copyright 2026-04-24
     */
    function getModelListByMake($make_id){
        $table = 'na_vehicle_base';
        $selectOptionList['model'] = $this->db->select($table, ['base_model_id','base_model_name'], ['base_make_id'=>$make_id, 'GROUP'=>'base_model_id','ORDER'=>['base_model_name'=>'ASC']]);
        $selectOptionList['modelCount'] = count($selectOptionList['model']);
        return $selectOptionList;
    }
}
