<?php
/**
 * 客户调价单管理
 * Created by PhpStorm.
 * User: phperstar
 * Date: 2019/4/26
 * Time: 9:41 AM
 */

namespace JinDouYun\Model\Price;

use JinDouYun\Cache\PriceCache;
use JinDouYun\Controller\Common\Logger;
use JinDouYun\Dao\Customer\DCustomer;
use JinDouYun\Model\GoodsManage\MSku;
use Mall\Framework\Core\ErrorCode;
use Mall\Framework\Core\ResultWrapper;
use Mall\Framework\Core\StatusCode;

use JinDouYun\Model\MBaseModel;
use JinDouYun\Dao\Price\DCustomerPriceEffective;
use JinDouYun\Dao\Price\DCustomerPriceAdjustment;

class MCustomerPriceAdjustment extends MBaseModel
{
    private $onlineUserId;

    private $onlineEnterpriseId;

    private $objDCustomerPriceAdjustment;

    private $objPriceCache;

    /**
     * MCustomerPriceAdjustment constructor.
     * @param $onlineUserId
     * @param $onlineEnterpriseId
     * @throws \Exception
     */
    public function __construct($onlineUserId, $onlineEnterpriseId)
    {
        $this->onlineUserId = $onlineUserId;
        $this->onlineEnterpriseId = $onlineEnterpriseId;
        parent::__construct($this->onlineEnterpriseId, $this->onlineUserId);
        $this->objPriceCache = new PriceCache($this->onlineEnterpriseId);
        $this->objDCustomerPriceAdjustment = new DCustomerPriceAdjustment();//DCustomerPriceAdjustment
        $this->objDCustomerPriceAdjustment->setTable($this->objDCustomerPriceAdjustment->get_Table() . '_' . $this->onlineEnterpriseId . '_' . date('Y') . '_' . ceil(date('m') / 3));
        $this->objDCustomerPriceAdjustment->setSearchIndex('customerPriceAdjustmentSheet_search')->setType('customerPriceAdjustmentSheet');
    }

    /**
     * 客户调价单添加
     */
    public function add($sheetData)
    {
        // 保存调单价数据
        $no = createOrderSn(StatusCode::$source['manage'], StatusCode::$orderType['customerPriceAdjustment'], $this->onlineUserId);
        foreach ($sheetData as $key => $value) {
            unset($sheetData[$key]['effective']);
            $sheetData[$key]['no'] = $no;
        }
        $dbResult = $this->objDCustomerPriceAdjustment->insert($sheetData, true);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDCustomerPriceAdjustment->error(), ErrorCode::$dberror);
        }

        if (is_array($dbResult)) {
            foreach ($dbResult as $key => $id) {
                if (isset($sheetData[$key])) {
                    $sheetData[$key]['id'] = $id;
                }
            }
        }
        self::updateEsData($sheetData);
        return ResultWrapper::success($dbResult);

    }

    /**
     * 更新ES
     * @param $data
     * @return mixed
     */
    public function updateEsData($data)
    {
        if (empty($data)) return $data;
        foreach ($data as $key => $val) {
            $esData = [
                'enterpriseId'      => $this->onlineEnterpriseId,
                'id'                => $val['id'],//自增id,
                'no'                => $val['no'],//调价单号,
                'goodsCode'         => isset($val['goodsCode']) ? $val['goodsCode'] : createCode(StatusCode::$code['goodsBasic']['prefix'], $val['goodsId'], StatusCode::$code['goodsBasic']['length']),//商品编号
                'goodsName'         => $val['goodsName'],//商品名称
                'goodsId'           => $val['goodsId'],//商品id
                'shopId'            => $val['shopId'],//店铺id
                'shopName'          => $val['shopName'],//店铺名称
                'createUserId'      => $val['createUserId'],//创建人id
                'createUserName'    => $val['createUserName'],//创建人姓名
                'effectiveUserName' => isset($val['effectiveUserName']) ? $val['effectiveUserName'] : '',//生效人姓名
                'effectiveUserId'   => isset($val['effectiveUserId']) ? $val['effectiveUserId'] : '',//生效人id
                'deleteStatus'      => StatusCode::$standard,//删除状态 4删除 5正常
                'effectiveStatus'   => isset($val['effectiveStatus']) ? $val['effectiveStatus'] : StatusCode::$auditStatus['auditPass'],//生效状态 1.待审 2审核通过 3未通过 4审核中
                'createTime'        => isset($val['createTime']) ? $val['createTime'] : time(),//创建时间
                'updateTime'        => isset($val['updateTime']) ? $val['updateTime'] : time(),//修改时间
                'salePrice'         => json_decode($val['salePrice'], true),//销售价格
                'customerId'        => $val['customerId'],
                'customerName'      => $val['customerName'],
                'customerCode'      => '',
            ];
            $_id = self::createEsDocumentId($val['id']);
            $result = $this->objDCustomerPriceAdjustment->addUpSearchIndexDocument($esData, $_id);
            if (isset($result['_shards']) && isset($result['_shards']['successful']) && $result['_shards']['successful'] == 1) {
                //echo "es操作成功";
                //return;
            }
            //echo "es操作失败";
        }
    }

    /**
     * 生成文档id
     * @param $id
     * @return string
     */
    private function createEsDocumentId($id)
    {
        return 'EnterpriseId_' . $this->onlineEnterpriseId . '_id_' . $id;
    }

    /**
     * 生成单据编号
     */
    public function createNo($createUserId)
    {
        return date('YmdHis') . substr(strval($createUserId + 100), -2) . substr(microtime(), 2, 4);
    }

    /**
     * 获取指定用户区域可售商品
     */
    public function goodsLists($params)
    {
        // 判断用户所在区域是否在店铺经营范围内
        $objDCloudShopRegion = new DCloudShopRegion();
        $condition = 'shop_id = ' . $params['shopId'] . ' and FIND_IN_SET(' . $params['provinceId'] . ', province_id) and FIND_IN_SET(' . $params['cityId'] . ', city_id) and FIND_IN_SET(' . $params['districtId'] . ', district)';
        $shop_region = $objDCloudShopRegion->get($condition, 'id');
        if ($shop_region == false) {
            return ResultWrapper::fail($objDCloudShopRegion->error(), ErrorCode::$dberror);
        } else if (empty($shop_region)) {
            return ResultWrapper::success([]);
        }

        // 查询店铺中在该区域内的商品
        $pageData = pageToOffset($params['page'], $params['pageSize']);

        $condition = 'shop_id = ' . $params['shopId'] . ' and is_delete = 0  and ( is_area_sale = 1 or is_area_sale = 2 and FIND_IN_SET(' . $params['provinceId'] . ', province_id) and FIND_IN_SET(' . $params['cityId'] . ', city_id) and FIND_IN_SET(' . $params['districtId'] . ', district_id))  ';

        if (isset($params['keyword'])) {
            $condition = $condition . 'and goods_name like "%' . $params['keyword'] . '%"';
        }

        $total = $this->objDNsGoods->count($condition);

        $dbResult = $this->objDNsGoods->select($condition, 'materialCode,marketCode,goods_name,state', 'goods_id desc', $pageData['limit'], $pageData['offset']);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDNsGoods->error(), ErrorCode::$dberror);
        } else {
            $return = [
                'data'  => $dbResult,
                'total' => $total,
            ];
            return ResultWrapper::success($return);
        }
    }

    /**
     * 获取所有调价单
     */
    public function getAll($params,$export = 0)
    {
        $pageData = pageToOffset($params['page'], $params['pageSize']);
        if($export){
            $pageData['limit'] = null;
            $pageData['offset'] = null;
        }
        $condition = null;

        if ($params['keyword']) {
            $condition = "(goodsName like '%" . $params['keyword'] . "%' or goodsCode like '%" . $params['keyword'] . "%' or no like '%".$params['keyword']."%')";
        }

        if ($params['startTime'] && $params['endTime']) {
            if ($condition !== null) {
                $condition .= ' and ';
            }
            $condition .= " createTime >= " . $params['startTime'] . " and createTime <=" . $params['endTime'];
        }

        if ($params['effectiveStatus']) {
            if ($condition !== null) {
                $condition .= ' and ';
            }
            $condition .= " effectiveStatus = " . $params['effectiveStatus'];
        }
        
        if (isset($params['goodsId']) && !empty($params['goodsId'])) {
            if ($condition !== null) {
                $condition .= ' and ';
            }
            $condition .= " goodsId = " . $params['goodsId'];
        }

        if (isset($params['shopId']) && !empty($params['shopId'])){
            if ($condition !== null) {
                $condition .= ' and ';
            }
            $condition .= " shopId = " . $params['shopId'];
        }

        $condition = parent::getShopIdQueryParams($condition);
        $total = $this->objDCustomerPriceAdjustment->count($condition);

        $dbResult = $this->objDCustomerPriceAdjustment->select($condition, '*', 'id desc', $pageData['limit'], $pageData['offset']);
        if ($dbResult === false) {
            return ResultWrapper::fail($this->objDCustomerPriceAdjustment->error(), ErrorCode::$dberror);
        }
        $return = [
            'data'  => self::format($dbResult),
            'total' => $total,
        ];
        //客户调价单导出
        if($export){
            self::exportCustomerPriceSheet($return['data']);
            exit;
        }
        return ResultWrapper::success($return);
    }

    /**
     * 格式化返回数据
     * @param $data
     * @return mixed
     * @throws \Exception
     */
    public function format($data)
    {
        $skuIds = [];
        foreach ($data as $key => &$val) {
            if (!is_array($val['salePrice'])){
                $val['salePrice'] = json_decode($val['salePrice'], true);
            }
            foreach ($val['salePrice'] as $row){
                $skuIds[] = $row['skuId'];
            }
        }

        $objMSku = new MSku($this->onlineUserId,$this->onlineEnterpriseId);
        $skuResult = $objMSku->getSpecNameBySkuId($skuIds);
        $allSkuData = [];
        if ($skuResult->isSuccess()){
            $allSkuData = $skuResult->getData();
        }

        foreach ($data as &$value){
            foreach ($value['salePrice'] as &$row){
                $row['unitName'] = isset($allSkuData[$row['skuId']]) ? $allSkuData[$row['skuId']]['unitName'] : '';
                $row['specGroup'] = isset($allSkuData[$row['skuId']]) ? $allSkuData[$row['skuId']]['specGroup'] : [];
                if (empty($row['specGroup'])){
                    $value['specType'] = StatusCode::$specType['single'];
                }else{
                    $value['specType'] = StatusCode::$specType['multiple'];
                }
            }
        }

        return $data;
    }

    /**
     * 生效操作
     * @param $id
     * @param $params
     * @return ResultWrapper
     * @throws \Exception
     */
    public function effective($id, $params)
    {
        // 计算客户调价单分表
        $tableName = 'qianniao_customerPriceAdjustmentSheet_' . $this->onlineEnterpriseId . '_' . date('Y', $params['createTime']) . '_' . ceil(date('m', $params['createTime']) / 3);
        $this->objDCustomerPriceAdjustment->setTable($tableName);

        $priceAdjustment = $this->objDCustomerPriceAdjustment->get($id);
        if ($priceAdjustment === false) {
            return ResultWrapper::fail($this->objDCustomerPriceAdjustment->error(), ErrorCode::$dberror);
        }

        if (empty($priceAdjustment)) {
            return ResultWrapper::fail('要生效的调价单不存在', ErrorCode::$contentNotExists);
        }

        $this->objDCustomerPriceAdjustment->beginTransaction();

        // 将调价单变更为生效状态
        $dbResult = $this->objDCustomerPriceAdjustment->update(
            [
                'effectiveStatus'   => StatusCode::$auditStatus['auditPass'],
                'effectiveUserName' => $params['effectiveUserName'],
                'effectiveUserId'   => $params['effectiveUserId'],
            ]
            , $id);
        if ($dbResult === false) {
            $this->objDCustomerPriceAdjustment->rollBack();
            return ResultWrapper::fail($this->objDCustomerPriceAdjustment->error(), ErrorCode::$dberror);
        }

        // 记录最后生效数据
        unset($dbResult);
        $objDCustomerPriceEffective = new DCustomerPriceEffective();
        $objDCustomerPriceEffective->setTable('qianniao_customerPriceEffective_' . $this->onlineEnterpriseId);
        $data = [
            'no'         => $priceAdjustment['no'],
            'goodsId'    => $priceAdjustment['goodsId'],
            'shopId'     => $priceAdjustment['shopId'],
            'salePrice'  => $priceAdjustment['salePrice'],
            'startTime'  => $priceAdjustment['startTime'],
            'endTime'    => $priceAdjustment['endTime'],
            'customerId' => $priceAdjustment['customerId'],
        ];

        $dbResult = $objDCustomerPriceEffective->replace($data);
        if ($dbResult === false) {
            $this->objDCustomerPriceAdjustment->rollBack();
            return ResultWrapper::fail($objDCustomerPriceEffective->error(), ErrorCode::$dberror);
        }

        $_id = self::createEsDocumentId($id);
        $this->objDCustomerPriceAdjustment->esupdateTypeFieldVaule([
            'effectiveStatus'   => StatusCode::$auditStatus['auditPass'],
            'effectiveUserName' => isset($params['effectiveUserName']) ? $params['effectiveUserName'] : '',
            'effectiveUserId'   => isset($params['effectiveUserId']) ? $params['effectiveUserId'] : '',
        ], $_id);

        //删除缓存
        $this->objPriceCache->delCustomerAdj($priceAdjustment['goodsId'],$priceAdjustment['customerId']);
        $this->objDCustomerPriceAdjustment->commit();
        return ResultWrapper::success($dbResult);
    }


    /**
     * 获取指定用户的可用的调价单
     * @param int $shopId  店铺id
     * @param int $customerId  客户id
     * @param array $goodsIds 店铺下商品集合
     * @return  ResultWrapper
     */
    public function getCustomerPriceByIds($shopId, $customerId, $goodsIds)
    {
        $objDCustomerPriceEffective = new DCustomerPriceEffective();
        $objDCustomerPriceEffective->setTable('qianniao_customerPriceEffective_' . $this->onlineEnterpriseId);

        $where = 'shopId = ' . $shopId . ' and customerId = ' . $customerId. ' and goodsId in ('.implode(',', $goodsIds).')';

        $dbResult = $objDCustomerPriceEffective->select($where, 'goodsId,salePrice', 'endTime desc');
        if ($dbResult === false) {
            return ResultWrapper::fail($objDCustomerPriceEffective->error(), ErrorCode::$dberror);
        }
        return ResultWrapper::success($dbResult);
    }


    /**
     * 客户调价单搜索
     * @param $selectParams
     * @return ResultWrapper
     */
    public function search($selectParams)
    {
        $defaultDSL = [
            'from' => $selectParams['offset'],
            'size' => $selectParams['limit'],
            'sort' => [
                'createTime' => [
                    'order' => 'desc'
                ],
            ],
        ];

        $dsl = [];
        $dsl['query']['bool']['must'][] = [
            'term' => ['enterpriseId' => $this->onlineEnterpriseId],
        ];

        //店铺id
        parent::getAccessShopIds();
        if (parent::$shopIds) {
            $dsl['query']['bool']['filter'][] = [
                'terms' => ['shopId' => parent::$shopIds]
            ];
        }

        //订单编号,收货人,商品名称
        if (!empty($selectParams['keyword'])) {
            $dsl['query']['bool']['must'][] = [
                'multi_match' => [
                    'fields'    => ['goodsCode', 'goodsName'],
                    'query'     => $selectParams['keyword'],
                    'fuzziness' => 'AUTO',
                ],
            ];
        }

        //生效状态
        if (!empty($selectParams['effectiveStatus'])) {
            $dsl['query']['bool']['filter'][] =
                ['term' => ['effectiveStatus' => $selectParams['effectiveStatus']]];
        }

        //时间
        if (!empty($selectParams['startTime']) && !empty($selectParams['endTime'])) {
            $dsl['query']['bool']['must'][] = [
                'range' => [
                    'createTime' => [
                        'gte' => $selectParams['startTime'],
                        'lte' => $selectParams['endTime'],
                    ]
                ]
            ];
        } else {
            if (!empty($selectParams['startTime'])) {
                $dsl['query']['bool']['must'][] = [
                    'range' => [
                        'createTime' => [
                            'gte' => $selectParams['startTime'],
                        ]
                    ]
                ];
            }

            if (!empty($selectParams['endTime'])) {
                $dsl['query']['bool']['must'][] = [
                    'range' => [
                        'createTime' => [
                            'lte' => $selectParams['endTime'],
                        ]
                    ]
                ];
            }
        }

        $dsl = array_merge($defaultDSL, $dsl);
        $result = $this->objDCustomerPriceAdjustment->getSearchQueryDsl($dsl);
        if (isset($result['status']) && $result['status'] == 400) {
            return ResultWrapper::fail('获取数据失败' . $result['error']['reason'], ErrorCode::$apiNotResult);
        }
        $total = $result['hits']['total'];
        $dbResult = $result['hits']['hits'];
        $list = [];
        foreach ($dbResult as $key => &$value) {
            $data = [];
            $data = $value['_source'];
            $list[] = $data;
        }
        $return = [
            'data'  => self::format($list),
            'total' => ($total) ? intval($total) : 0,
        ];
        return ResultWrapper::success($return);
    }
    
    /**
     * 客户调价单导出方法
     * @param $priceSheetData
     */
    private static function exportCustomerPriceSheet($priceSheetData)
    {
        //导出到本地
        header("Content-type:application/vnd.ms-excel");
        header("Content-Disposition:filename=客户调价单明细表记录.csv");
        header('Cache-Control: max-age=0');
        $fp = fopen('php://output', 'a');
        
        $head = ['调价单编码','客户名称','商品名称','调价时间','调整后价格规格','调整市场价格','调整人','相关店铺', '状态'];       //定义标题
        
        foreach ($head as $i => $v) {
            $head[$i] = mb_convert_encoding($v, 'GBK', 'utf-8');     //将中文标题转换编码,否则乱码
        }
        fputcsv($fp, $head);
        $limit = 10000;
        $num = 0;//计数器
        foreach ($priceSheetData as $v) {
    
            $price = ''; //市场价格
            $unitName = ''; //规格
            $specValueName = '';
            if(!empty($v['salePrice'])){
                foreach ($v['salePrice'] as $key => $value){
                    $price = $value['price'];
                    foreach ($value['specGroup'] as $K => $V){
                      $specValueName   = $V['specValueName'];
                    }
                    $unitName = $value['unitName'].';'.$specValueName;
                }
            }
            //循环数据
            $num++;
            if ($num == $limit) {
                ob_flush();//释放内存
                flush();
            }
            $rows['no'] = isset($v['no']) ? $v['no'] : '';//调价单编码
            $rows['customerName'] = isset($v['customerName']) ? $v['customerName'] : '';//客户名称
            $rows['goodsName'] = isset($v['goodsName']) ? $v['goodsName'] : '';//商品名称
            $rows['createTime'] = isset($v['createTime']) ? date('Y-m-d H:i:s',$v['createTime']) : '';//调价时间
            $rows['unitName'] = $unitName;//调整规格
            $rows['price'] = '-¥'.$price;//调整市场价格
            $rows['createUserName'] = isset($v['createUserName']) ? $v['createUserName'] : '';//调整人
            $rows['shopName'] = isset($v['shopName']) ? $v['shopName'] : '';//相关店铺
            $rows['effectiveStatus'] =  $v['effectiveStatus'] === 2 ? '生效' : '未生效';//状态
            foreach ($rows as $kk => $vv) {
                $rs[$kk] = mb_convert_encoding($vv, 'GBK', 'utf-8');  //转译编码
            }
            fputcsv($fp, $rs);
            $rows = [];
        }
        exit;
    }
    
    /**
     * 获取指定商品的最后生效的客户调价单数据
     * @param $params
     * @return ResultWrapper
     */
    public function getCustomerPriceByGoodsIds($params)
    {
        $pageData = pageToOffset($params['page'], $params['pageSize']);
        $objDCustomerPriceEffective = new DCustomerPriceEffective();
        $objDCustomerPriceEffective->setTable('qianniao_customerPriceEffective_' . $this->onlineEnterpriseId);
        $conditon = [
            'goodsId' => $params['goodsId'],
        ];
        $dbResult = $objDCustomerPriceEffective->select($conditon, 'id,customerId,salePrice', 'id desc',$pageData['limit'],$pageData['offset']);
        if ($dbResult === false) {
            return ResultWrapper::fail($objDCustomerPriceEffective->error(), ErrorCode::$dberror);
        }
        $count = $objDCustomerPriceEffective->count($conditon);
        if ($count === false) {
            return ResultWrapper::fail($objDCustomerPriceEffective->error(), ErrorCode::$dberror);
        }
        $data = self::formatCustomerName($dbResult);
        if(!$data->isSuccess()){
            return ResultWrapper::fail($objDCustomerPriceEffective->error(), ErrorCode::$dberror);
        }
        $dbResult = $data->getData();
        foreach ($dbResult as $key =>$value){
            $dbResult[$key]['salePrice'] = json_decode($value['salePrice']);
        }
        $return = [
            'data'  => $dbResult,
            'total' => $count,
        ];
        return ResultWrapper::success($return);
    }
    
    /**
     * 删除指定商品的最后生效的客户调价单数据
     * @param array $params
     * @return ResultWrapper
     */
    public function delCustomerPrice($params)
    {
        $objDCustomerPriceEffective = new DCustomerPriceEffective();
        $objDCustomerPriceEffective->setTable('qianniao_customerPriceEffective_' . $this->onlineEnterpriseId);
        $dbResult = $objDCustomerPriceEffective->select($params['id']);
        if ($dbResult === false) {
            return ResultWrapper::fail($objDCustomerPriceEffective->error(), ErrorCode::$dberror);
        }
        if(empty($dbResult)){
            return ResultWrapper::fail('要作废的调价单不存在', ErrorCode::$contentNotExists);
        }
        foreach ($dbResult as $key => $value){

            $value['salePrice'] = json_decode($value['salePrice'], true);
            foreach ($value['salePrice'] as $k => $v){
                if($v['skuId'] == $params['skuId']){
                    unset($value['salePrice'][$k]);
                    continue;
                }
            }
            $value['salePrice'] = json_encode( $value['salePrice']);
            $updateDbResult = $objDCustomerPriceEffective->update(['salePrice'=>$value['salePrice']], $value['id']);
            if ($updateDbResult === false) {
                return ResultWrapper::fail($objDCustomerPriceEffective->error(), ErrorCode::$dberror);
            }
        }

        return ResultWrapper::success($updateDbResult);
    }
    
    /**
     * 格式化客户名称
     * @return array
     */
    public function formatCustomerName($data)
    {   //customerId
        //根据客户id进行渲染客户名称
        $customerIdBindCustomerName = [];
        $customerIds = [];
        foreach ($data as $k => $v){
            if(!empty($v['customerId'])){
                $customerIds[] = $v['customerId'];
            }
        }
        if(!empty($customerIds)){
            $objDCustomer = new DCustomer();
            $objDCustomer->setTable('qianniao_customer_' . $this->onlineEnterpriseId);
            $customerData = $objDCustomer->select($customerIds, 'id,name');
            if($customerData == false){
                return ResultWrapper::fail($objDCustomer->error(), ErrorCode::$dberror);
            }
            if(!empty($customerData)){
                foreach ($customerData as $k => $v){
                    $customerIdBindCustomerName[$v['id']] = $v['name'];
                }
            }
            // 循环主数据,进行对应的字段映射操作
            foreach ($data as $key => $value){
                $data[$key]['customerName'] = isset($customerIdBindCustomerName[$value['customerId']]) ? $customerIdBindCustomerName[$value['customerId']] :'';
            }
        }
        return  ResultWrapper::success($data);
    }
}