<?php


namespace JinDouYun\Model\Price;


use JinDouYun\Controller\Common\Logger;
use JinDouYun\Dao\Price\DSupplierOfferPriceSheet;
use JinDouYun\Dao\Price\DSupplierOfferPriceSheetDetails;
use JinDouYun\Model\Goods\MGoods;
use JinDouYun\Model\GoodsManage\MGoodsBasic;
use JinDouYun\Model\GoodsManage\MSku;
use JinDouYun\Model\Purchase\MSupplier;
use Mall\Framework\Core\ErrorCode;
use Mall\Framework\Core\ResultWrapper;
use Mall\Framework\Core\StatusCode;

/**
 * @copyright   Copyright (c) https://www.qianniaovip.com All rights reserved
 * Description: 供应商报价单Model
 * Class MSupplierOfferPriceSheet
 * @package JinDouYun\Model\Price
 */
class MSupplierOfferPriceSheet
{
    /**
     * @var DSupplierOfferPriceSheet
     */
    private $objDSupplierOfferPriceSheet;

    /**
     * @var DSupplierOfferPriceSheetDetails
     */
    private $objDSupplierOfferPriceSheetDetails;

    /**
     * @var int
     */
    private $onlineUserId;

    /**
     * @var int
     */
    private $onlineEnterpriseId;

    /**
     * MSupplierOfferPriceSheet constructor.
     * @param $onlineUserId
     * @param $onlineEnterpriseId
     * @throws \Exception
     */
    public function __construct($onlineUserId, $onlineEnterpriseId)
    {
        $this->onlineUserId = $onlineUserId;
        $this->onlineEnterpriseId = $onlineEnterpriseId;
        $this->objDSupplierOfferPriceSheet = new DSupplierOfferPriceSheet();
        $this->objDSupplierOfferPriceSheetDetails = new DSupplierOfferPriceSheetDetails();
        $this->objDSupplierOfferPriceSheet->setTable('qianniao_supplierOfferPrice_sheet_' . $this->onlineEnterpriseId);
        $this->objDSupplierOfferPriceSheetDetails->setTable('qianniao_supplierOfferPrice_sheet_details_' . $this->onlineEnterpriseId);
    }

    /**
     * Doc: (des="添加供应商报价单")
     * User: XMing
     * Date: 2020/12/16
     * Time: 6:10 下午
     * @param array $params
     * @param int $supplierId
     * @return ResultWrapper
     * @throws \Exception
     */
    public function add(array $params, int $supplierId): ResultWrapper
    {
        $details = getArrayItem($params, 'details', []);
        if (empty($details)) {
            return ResultWrapper::fail('报价单商品数据为空', ErrorCode::$paramError);
        }
        $objMSupplier = new MSupplier($this->onlineUserId, $this->onlineEnterpriseId);
        $supplierResult = $objMSupplier->getSupplierById($supplierId);
        if (!$supplierResult->isSuccess()) {
            return ResultWrapper::fail($supplierResult->getData(), $supplierResult->getErrorCode());
        }
        $supplier = $supplierResult->getData();
        $params['supplierName'] = getArrayItem($supplier, 'title', '');
        $params['userId'] = $this->onlineUserId;

        $sheetInsert = self::buildSupplierOfferPriceSheetData($params);

        $this->objDSupplierOfferPriceSheet->beginTransaction();
        $sheetId = $this->objDSupplierOfferPriceSheet->insert($sheetInsert);
        if ($sheetId === false) {
            Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheet->error());
            $this->objDSupplierOfferPriceSheet->rollBack();
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheet->error(), ErrorCode::$dberror);
        }
        $sheetDetailsInserts = [];
        foreach ($details as $detail) {
            $detail['linkId'] = $sheetId;
            $sheetDetailsInserts[] = self::buildSupplierOfferPriceSheetDetailsData($detail, $supplierId);
        }
        $dbResult = $this->objDSupplierOfferPriceSheetDetails->insert($sheetDetailsInserts, true);
        if ($dbResult === false) {
            Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheetDetails->error());
            $this->objDSupplierOfferPriceSheet->rollBack();
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheetDetails->error(), ErrorCode::$dberror);
        }
        $this->objDSupplierOfferPriceSheet->commit();
        return ResultWrapper::success($sheetId);
    }

    /**
     * Doc: (des="编辑报价单")
     * User: XMing
     * Date: 2020/12/17
     * Time: 11:53 上午
     * @param array $params
     * @param int $id
     * @param int $supplierId
     * @return ResultWrapper
     */
    public function edit(array $params, int $id, int $supplierId): ResultWrapper
    {
        $details = getArrayItem($params, 'details', []);
        if (empty($details)) {
            return ResultWrapper::fail('报价单商品数据为空', ErrorCode::$paramError);
        }
        $commonResult = self::commonMerge($details, $id, $supplierId);
        if (!$commonResult->isSuccess()) {
            Logger::logs(E_USER_ERROR, 'error', __CLASS__, __LINE__, $commonResult->getData());
            return ResultWrapper::fail($commonResult->getData(), $commonResult->getErrorCode());
        }
        $commonMerge = $commonResult->getData();

        $this->objDSupplierOfferPriceSheet->beginTransaction();
        $updateResult = $this->objDSupplierOfferPriceSheet->update(['updateTime' => time()], $id);
        if ($updateResult === false) {
            Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheet->error());
            $this->objDSupplierOfferPriceSheet->rollBack();
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheet->error(), ErrorCode::$dberror);
        }

        $insert = getArrayItem($commonMerge, 'insert', []);
        $update = getArrayItem($commonMerge, 'update', []);
        $delete = getArrayItem($commonMerge, 'delete', []);

        if (!empty($insert)) {
            $result = $this->objDSupplierOfferPriceSheetDetails->insert($insert, true);
            if ($result === false) {
                Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheetDetails->error());
                $this->objDSupplierOfferPriceSheet->rollBack();
                return ResultWrapper::fail($this->objDSupplierOfferPriceSheetDetails->error(), ErrorCode::$dberror);
            }
        }

        if (!empty($delete)) {
            $result = $this->objDSupplierOfferPriceSheetDetails
                ->update(['deleteStatus' => StatusCode::$delete, 'updateTime' => time()], ['id' => $delete]);
            if ($result === false) {
                Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheetDetails->error());
                $this->objDSupplierOfferPriceSheet->rollBack();
                return ResultWrapper::fail($this->objDSupplierOfferPriceSheetDetails->error(), ErrorCode::$dberror);
            }
        }

        if (!empty($update)) {
            foreach ($update as $value) {
                $result = $this->objDSupplierOfferPriceSheetDetails
                    ->update(['updateTime' => time(), 'offerPrice' => $value['offerPrice']], $value['id']);
                if ($result === false) {
                    Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheetDetails->error());
                    $this->objDSupplierOfferPriceSheet->rollBack();
                    return ResultWrapper::fail($this->objDSupplierOfferPriceSheetDetails->error(), ErrorCode::$dberror);
                }
            }
        }
        $this->objDSupplierOfferPriceSheet->commit();
        return ResultWrapper::success(true);
    }

    /**
     * Doc: (des="列表")
     * User: XMing
     * Date: 2020/12/17
     * Time: 10:26 上午
     * @param array $selectParams
     * @return ResultWrapper
     */
    public function getAll(array $selectParams): ResultWrapper
    {
        $buildSql = self::buildSqlBySelectParams($selectParams);
        $lists = $this->objDSupplierOfferPriceSheet->query($buildSql['sql']);
        if ($lists === false) {
            Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheet->error());
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheet->error(), ErrorCode::$dberror);
        }
        $count = $this->objDSupplierOfferPriceSheet->query($buildSql['countSql']);
        self::formatSheetLists($lists);
        $ret = [
            'data'  => $lists,
            'total' => isset($count[0]['total']) ? $count[0]['total'] : 0,
        ];
        return ResultWrapper::success($ret);
    }

    /**
     * Doc: (des="详情")
     * User: XMing
     * Date: 2020/12/17
     * Time: 10:53 上午
     * @param int $id
     * @return ResultWrapper
     * @throws \Exception
     */
    public function get(int $id): ResultWrapper
    {
        $result = $this->objDSupplierOfferPriceSheet->get($id);
        if ($result === false) {
            Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheet->error());
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheet->error(), ErrorCode::$dberror);
        }
        if (empty($result)) {
            return ResultWrapper::fail('未获取到指定单据信息', ErrorCode::$paramError);
        }
        $detailsResult = self::getSheetDetailsByLinkId($result['id']);
        if (!$detailsResult->isSuccess()) {
            Logger::logs(E_USER_ERROR, 'error', __CLASS__, __LINE__, $detailsResult->getData());
            return ResultWrapper::fail($detailsResult->getData(), $detailsResult->getErrorCode());
        }
        $result['no'] = StatusCode::$noPrefix[StatusCode::$orderType['supplierOfferPrice']] . $result['no'];
        $result['details'] = $detailsResult->getData();
        return ResultWrapper::success($result);
    }

    /**
     * Doc: (des="")
     * User: XMing
     * Date: 2020/12/17
     * Time: 11:57 上午
     * @param array $params
     * @param int $linkId
     * @param int $supplierId
     * @return ResultWrapper
     */
    private function commonMerge(array $params, int $linkId, int $supplierId): ResultWrapper
    {
        $lists = $this->objDSupplierOfferPriceSheetDetails->select(['linkId' => $linkId, 'deleteStatus' => StatusCode::$standard]);
        if ($lists === false) {
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheetDetails->error(), ErrorCode::$dberror);
        }
        $oldMaterielIdIds = [];
        $oldMaterielIdMap = [];
        foreach ($lists as $list) {
            $oldMaterielIdIds[] = $list['materielId'];
            $oldMaterielIdMap[$list['materielId']] = $list;
        }

        $update = [];
        $insert = [];
        $delete = [];
        foreach ($params as $param) {
            if (in_array($param['materielId'], $oldMaterielIdIds)) {
                $id = $oldMaterielIdMap[$param['materielId']]['id'];
                if (empty($id)) {
                    return ResultWrapper::fail('id参数异常', ErrorCode::$paramError);
                }
                $update[] = [
                    'offerPrice' => json_encode($param['offerPrice']),
                    'id'         => $id,
                ];
                unset($oldMaterielIdMap[$param['materielId']]);
                continue;
            }
            $param['linkId'] = $linkId;
            $insert[] = self::buildSupplierOfferPriceSheetDetailsData($param, $supplierId);
        }

        foreach ($oldMaterielIdMap as $value) {
            $delete[] = $value['id'];
        }

        $ret = [
            'insert' => $insert,
            'update' => $update,
            'delete' => $delete
        ];
        return ResultWrapper::success($ret);
    }

    /**
     * Doc: (des="删除")
     * User: XMing
     * Date: 2020/12/17
     * Time: 11:45 上午
     * @param int $id
     * @return ResultWrapper
     */
    public function del(int $id): ResultWrapper
    {
        $dbResult = $this->objDSupplierOfferPriceSheet->update(['deleteStatus' => StatusCode::$delete, 'updateTime' => time()], $id);
        if ($dbResult === false) {
            Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheet->error());
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheet->error(), ErrorCode::$dberror);
        }
        return ResultWrapper::success(true);
    }

    /**
     * Doc: (des="根据linkId获取详情睡")
     * User: XMing
     * Date: 2020/12/17
     * Time: 11:00 上午
     * @param int $linkId
     * @return ResultWrapper
     * @throws \Exception
     */
    protected function getSheetDetailsByLinkId(int $linkId): ResultWrapper
    {
        $lists = $this->objDSupplierOfferPriceSheetDetails->select(['linkId' => $linkId, 'deleteStatus' => StatusCode::$standard]);
        if ($lists === false) {
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheetDetails->error(), ErrorCode::$dberror);
        }
        $formatResult = self::formatSheetDetails($lists);
        if (!$formatResult->isSuccess()) {
            return ResultWrapper::fail($formatResult->getData(), $formatResult->getErrorCode());
        }
        $format = $formatResult->getData();
        return ResultWrapper::success($format);
    }

    /**
     * Doc: (des="格式化报价单详情数据")
     * User: XMing
     * Date: 2020/12/17
     * Time: 11:03 上午
     * @param array $lists
     * @return ResultWrapper
     * @throws \Exception
     */
    protected function formatSheetDetails(array $lists): ResultWrapper
    {
        if (empty($lists)) {
            return ResultWrapper::success([]);
        }
        $materielIds = [];
        foreach ($lists as $list) {
            $materielIds[] = $list['materielId'];
        }
        $objMGoodsBasic = new MGoodsBasic( $this->onlineUserId,$this->onlineEnterpriseId);
        $materielMapResult = $objMGoodsBasic->getMapsByIds($materielIds);
        if (!$materielMapResult->isSuccess()) {
            return ResultWrapper::fail($materielMapResult->getData(), $materielMapResult->getErrorCode());
        }
        $materielMap = $materielMapResult->getData();
        if (empty($materielMap)) {
            return ResultWrapper::fail('未获取到物料数据', ErrorCode::$paramError);
        }

        $skuIds = [];
        foreach ($lists as &$list) {
            $row = getArrayItem($materielMap, $list['materielId'], []);
            $list['materielName'] = '';
            $list['materielImages'] = [];
            $list['materielCode'] = '';
            if (!empty($row)) {
                $list['materielName'] = getArrayItem($row, 'title', '');
                $list['materielImages'] = getArrayItem($row, 'images', []);
                $list['materielCode'] = getArrayItem($row, 'code', []);
            }
            $list['offerPrice'] = json_decode($list['offerPrice'], true);
            foreach ($list['offerPrice'] as $skuId => $value){
                !empty($skuId) && $skuIds[] = $skuId;
            }
        }
        unset($list);

        $objMSku = new MSku($this->onlineUserId,$this->onlineEnterpriseId);
        $skuMapResult = $objMSku->getSkuMapByIds($skuIds);
        if (!$skuMapResult->isSuccess()){
            return ResultWrapper::fail($skuMapResult->getData(), $skuMapResult->getErrorCode());
        }
        $skuMap = $skuMapResult->getData();
        foreach ($lists as &$list){
            $offerPrice = getArrayItem($list,'offerPrice',[]);
            foreach ($offerPrice as $skuId => &$value){
                $skuRow = getArrayItem($skuMap,$skuId,[]);
                if (!empty($skuRow)){
                    $value['unitName'] = getArrayItem($skuRow,'unitName','');
                    $value['specGroup'] = getArrayItem($skuRow,'specGroup',[]);
                }
            }
            $list['offerPrice'] = $offerPrice;
        }

        return ResultWrapper::success($lists);
    }

    /**
     * Doc: (des="格式化报价单列表")
     * User: XMing
     * Date: 2020/12/17
     * Time: 10:52 上午
     * @param $lists
     */
    protected static function formatSheetLists(&$lists)
    {
        foreach ($lists as &$list) {
            $list['no'] = StatusCode::$noPrefix[StatusCode::$orderType['supplierOfferPrice']] . $list['no'];
        }
    }


    /**
     * Doc: (des="构建sql")
     * User: XMing
     * Date: 2020/12/17
     * Time: 10:27 上午
     * @param array $selectParams
     * @return array
     */
    private function buildSqlBySelectParams(array $selectParams): array
    {
        $tableName = $this->objDSupplierOfferPriceSheet->get_Table();
        $fields = ' * ';
        $countFields = ' COUNT(`id`) AS total ';
        $whereSql = '';
        if (isset($selectParams['supplierId']) && !empty($selectParams['supplierId'])) {
            $whereSql .= ' AND `supplierId` = ' . $selectParams['supplierId'];
        }

        if (isset($selectParams['auditStatus']) && !empty($selectParams['auditStatus'])){
            $whereSql .= ' AND `auditStatus` = ' . $selectParams['auditStatus'];
        }

        if (isset($selectParams['keyword']) && !empty($selectParams['keyword'])) {
            $keyword = '"%' . $selectParams['keyword'] . '%"';
            $whereSql .= ' AND ( `no` LIKE ' . $keyword . ' OR `supplierName` LIKE ' . $keyword . ') ';
        }

        if (isset($selectParams['startTime']) && !empty($selectParams['startTime'])) {
            $whereSql .= ' AND `createTime` BETWEEN ' . $selectParams['startTime'] . ' AND ' . $selectParams['endTime'];
        }

        $countSql = 'SELECT ' . $countFields . ' FROM ' . $tableName . ' WHERE `deleteStatus` = ' . StatusCode::$standard . $whereSql;

        $whereSql .= ' ORDER BY createTime DESC ';
        if (isset($selectParams['limit']) && !empty($selectParams['limit'])) {
            $whereSql .= ' LIMIT ' . $selectParams['offset'] . ',' . $selectParams['limit'];
        }

        $sql = 'SELECT ' . $fields . ' FROM ' . $tableName . ' WHERE `deleteStatus` = ' . StatusCode::$standard . $whereSql;

        return [
            'sql'      => $sql,
            'countSql' => $countSql
        ];
    }


    /**
     * Doc: (des="构建供应商报价单数据")
     * User: XMing
     * Date: 2020/12/16
     * Time: 5:54 下午
     * @param array $params
     * @return array
     */
    public static function buildSupplierOfferPriceSheetData(array $params): array
    {

        $no = createOrderSn(StatusCode::$source['manage'], StatusCode::$orderType['supplierOfferPrice'], $params['userId']);
        return [
            'no'           => getArrayItem($params, 'no', $no),
            // char(25) NOT NULL COMMENT '订单编号',
            'supplierId'   => getArrayItem($params, 'supplierId', 0),
            // int(10) DEFAULT '0' COMMENT '供应商id',
            'supplierName' => getArrayItem($params, 'supplierName', ''),
            // varchar(50) DEFAULT '1,2' COMMENT '供应商名称',
            'materielNum'  => getArrayItem($params, 'materielNum', 0),
            // int(10) NOT NULL DEFAULT '0' COMMENT '物料数量',
            'auditStatus'  => getArrayItem($params, 'auditStatus', StatusCode::$auditStatus['auditing']),
            // tinyint(3) DEFAULT '2' COMMENT '审核状态 默认1 待审 2审核通过 3 审核未通过 4 审核中',
            'deleteStatus' => StatusCode::$standard,
            // tinyint(3) NOT NULL DEFAULT '5' COMMENT '是否删除 4 删除 5正常',
            'createTime'   => getArrayItem($params, 'createTime', time()),
            // int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
            'updateTime'   => getArrayItem($params, 'updateTime', time()),
            // int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
            'extends'      => getArrayItem($params, 'extends', null),
            // json DEFAULT NULL COMMENT '拓展字段',
        ];
    }

    /**
     * Doc: (des="构建供应商报价单数据")
     * User: XMing
     * Date: 2020/12/16
     * Time: 6:01 下午
     * @param array $params
     * @param int $supplierId
     * @return array
     */
    public static function buildSupplierOfferPriceSheetDetailsData(array $params, int $supplierId): array
    {
        return [
            'supplierId' => getArrayItem($params, 'supplierId', $supplierId),
            // int(10) DEFAULT '0' COMMENT '供应商id',
            'linkId'     => getArrayItem($params, 'linkId', 0),
            // int(10) DEFAULT '0' COMMENT '单据id',
            'materielId' => getArrayItem($params,'materielId',0),
            // int(10) NOT NULL COMMENT '物料id',
            'offerPrice' => json_encode(getArrayItem($params, 'offerPrice', null)),
            // json NOT NULL COMMENT '价格数据',
            'createTime' => getArrayItem($params, 'createTime', time()),
            // int(10) NOT NULL DEFAULT '0' COMMENT '创建时间',
            'updateTime' => getArrayItem($params, 'updateTime', time()),
            // int(10) NOT NULL DEFAULT '0' COMMENT '更新时间',
        ];
    }


    /**
     * Doc: (des="报价单审核")
     * User: XMing
     * Date: 2020/12/21
     * Time: 4:23 下午
     * @param int $id
     * @return ResultWrapper
     */
    public function audit(int $id): ResultWrapper
    {
        $dbResult = $this->objDSupplierOfferPriceSheet->update(['auditStatus' => StatusCode::$auditStatus['auditPass'],'updateTime'=>time()],$id);
        if ($dbResult === false){
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheet->error(),ErrorCode::$dberror);
        }
        return ResultWrapper::success(true);
    }

    /**
     * Doc: (des="根据物料ids获取物料的成本价格，供应商")
     * User: XMing
     * Date: 2020/12/21
     * Time: 4:42 下午
     * @param array $selectParams
     * @return ResultWrapper
     */
    public function getCostPriceByMaterielIds(array $selectParams): ResultWrapper
    {
        $buildSql = self::buildDetailsSqlBySelectParams($selectParams);
        $lists = $this->objDSupplierOfferPriceSheetDetails->query($buildSql['sql']);
        if ($lists === false) {
            Logger::logs(E_USER_ERROR, 'sql error', __CLASS__, __LINE__, $this->objDSupplierOfferPriceSheetDetails->error());
            return ResultWrapper::fail($this->objDSupplierOfferPriceSheetDetails->error(), ErrorCode::$dberror);
        }
        return ResultWrapper::success($lists);
    }

    /**
     * Doc: (des="sql-供应商报价单详情")
     * User: XMing
     * Date: 2020/12/21
     * Time: 4:44 下午
     * @param array $selectParams
     * @return array
     */
    public function buildDetailsSqlBySelectParams(array $selectParams): array
    {
        $tableName = $this->objDSupplierOfferPriceSheetDetails->get_Table();
        $fields = ' * ';
        $whereSql = '';
        if (isset($selectParams['supplierId']) && !empty($selectParams['supplierId'])) {
            $whereSql .= ' AND `supplierId` = ' . $selectParams['supplierId'];
        }
        if (isset($selectParams['materielId']) && !empty($selectParams['materielId'])){
            $whereSql .= ' AND `materielId` = '.$selectParams['materielId'];
        }

        if (isset($selectParams['materielIds']) && !empty($selectParams['materielId'])){
            $materielIdsStr = implode(',',$selectParams['materielIds']);
            $whereSql .= ' AND `materielId` IN ('.$materielIdsStr.') ';
        }

        if (isset($selectParams['startTime']) && !empty($selectParams['startTime'])) {
            $whereSql .= ' AND `createTime` BETWEEN ' . $selectParams['startTime'] . ' AND ' . $selectParams['endTime'];
        }

        $sql = 'SELECT ' . $fields . ' FROM ' . $tableName . ' WHERE `deleteStatus` = ' . StatusCode::$standard . $whereSql;

        return [
            'sql'      => $sql,
            'countSql' => '',
        ];
    }
}