<?php


namespace JinDouYun\Model\Finance;


use JinDouYun\Controller\Common\Logger;
use JinDouYun\Dao\Finance\DMerchantFlow;
use JinDouYun\Model\Enterprise\MEnterprise;
use JinDouYun\Model\MBaseModel;
use JinDouYun\Model\Merchant\MMerchant;
use JinDouYun\Model\Order\MOrder;
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:
 * Class MMerchantFlow
 * @package JinDouYun\Model\Finance
 */
class MMerchantFlow extends MBaseModel
{
    /**
     * @var DMerchantFlow
     */
    private $objDMerchantFlow;

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

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

    /**
     * MMerchantFlow constructor.
     * @param $onlineEnterpriseId
     * @param $onlineUserId
     * @throws \Exception
     */
    public function __construct($onlineEnterpriseId, $onlineUserId)
    {
        $this->onlineEnterpriseId = $onlineEnterpriseId;
        $this->onlineUserId = $onlineUserId;
        parent::__construct($onlineEnterpriseId, $onlineUserId);
        $this->objDMerchantFlow = new DMerchantFlow();
        $this->objDMerchantFlow->setTable('qianniao_merchant_flow_' . $this->onlineEnterpriseId);
    }

    /**
     * Doc: (des="多商户结算,不在此处计算抽成,提现时计算抽成")
     * User: XMing 放在确认收款 和 支付回调
     * Date: 2020/12/7
     * Time: 4:01 下午
     * @param int $orderId
     * @return ResultWrapper
     * @throws \Exception
     */
    public function calculation(int $orderId): ResultWrapper
    {
        Logger::logs(E_USER_ERROR,'订单id',__CLASS__,__LINE__,$orderId);
        $objMOrder = new MOrder($this->onlineUserId,$this->onlineEnterpriseId);
        $orderResult = $objMOrder->getOrderByOrderId($orderId);
        if (!$orderResult->isSuccess()){
            Logger::logs(E_USER_ERROR,'sql错误',__CLASS__,__LINE__,$orderResult->getData());
            return ResultWrapper::fail($orderResult->getData(),$orderResult->getErrorCode());
        }

        $order = $orderResult->getData();
        if ($order['payStatus'] == StatusCode::$delete){
            Logger::logs(E_USER_ERROR,'订单未支付',__CLASS__,__LINE__,$order['payStatus']);
            return ResultWrapper::fail('订单未支付',ErrorCode::$paramError);
        }
        if ($order['isSettel'] == StatusCode::$standard){
            Logger::logs(E_USER_ERROR,'isSettel',__CLASS__,__LINE__,$order);
            return ResultWrapper::fail('订单已经结算',ErrorCode::$paramError);
        }
        $objMEnterprise = new MEnterprise();
        $enterpriseResult = $objMEnterprise->getEnterpriseDataByEnterpriseId($this->onlineEnterpriseId);
        if (!$enterpriseResult->isSuccess()){
            Logger::logs(E_USER_ERROR,'sql错误',__CLASS__,__LINE__,$enterpriseResult->getData());
            return ResultWrapper::fail($enterpriseResult->getData(),$enterpriseResult->getErrorCode());
        }
        $enterprise = $enterpriseResult->getData();
        if (empty($enterprise)){
            Logger::logs(E_USER_ERROR,'未获取到平台信息',__CLASS__,__LINE__,'');
            return ResultWrapper::fail('未获取到平台信息',ErrorCode::$paramError);
        }
        //获取商户的信息
        $objMMerchant = new MMerchant($this->onlineEnterpriseId,$this->onlineUserId);
        $shopResult = $objMMerchant->getMerchByShopId($order['shopId']);
        if (!$shopResult->isSuccess()){
            Logger::logs(E_USER_ERROR,'sql',__CLASS__,__LINE__,$shopResult->getData());
            return ResultWrapper::fail($shopResult->getData(),$shopResult->getErrorCode());
        }
        $shop = $shopResult->getData();

        //计算第三方支付的手续费(不计入平余额)
        if (!isset($order['payAmount']) || empty($order['payAmount'])){
            Logger::logs(E_USER_ERROR,'payAmount参数异常',__CLASS__,__LINE__,'');
            return ResultWrapper::fail('payAmount参数异常',ErrorCode::$paramError);
        }
        $tradeMoney = $order['payAmount'];

        $logInserts = [];
        $buildPlatformResult = self::buildPlatform($tradeMoney,$order,$shop,$enterprise);
        if (!$buildPlatformResult->isSuccess()){
            Logger::logs(E_USER_ERROR,'构建平台流水记录时出错',__CLASS__,__LINE__,$buildPlatformResult->getData());
            return ResultWrapper::fail($buildPlatformResult->getData(),$buildPlatformResult->getErrorCode());
        }
        $buildPlatform = $buildPlatformResult->getData();
        $logInserts = array_merge($logInserts,$buildPlatform);

        $buildMerchResult = self::buildMerch($tradeMoney,$order,$shop,$enterprise);
        if (!$buildMerchResult->isSuccess()){
            Logger::logs(E_USER_ERROR,'构建商户流水记录时出错',__CLASS__,__LINE__,$buildMerchResult->getData());
            return ResultWrapper::fail($buildMerchResult->getData(),$buildMerchResult->getErrorCode());
        }
        $buildMerch = $buildMerchResult->getData();
        $logInserts = array_merge($logInserts,$buildMerch['logs']);

        $updateBalance = $buildMerch['updateBalance'];
        if (empty($logInserts)){
            Logger::logs(E_USER_ERROR,'构建流水记录为空',__CLASS__,__LINE__,$logInserts);
            return ResultWrapper::fail('构建流水记录为空',ErrorCode::$paramError);
        }

        Logger::logs(E_USER_ERROR,'流水数据',__CLASS__,__LINE__,$logInserts);
        Logger::logs(E_USER_ERROR,'商户余额更新数据',__CLASS__,__LINE__,$updateBalance);

        $this->objDMerchantFlow->beginTransaction();
        $insertResult = $this->objDMerchantFlow->insert($logInserts,true);
        if ($insertResult === false){
            $this->objDMerchantFlow->rollBack();
            Logger::logs(E_USER_ERROR,'sql',__CLASS__,__LINE__,$this->objDMerchantFlow->error());
            return ResultWrapper::fail($this->objDMerchantFlow->error,ErrorCode::$dberror);
        }
        $updateBalanceResult = $objMMerchant->update($updateBalance['merchantId'],['orderNum' => $updateBalance['orderNum'],'balance' => $updateBalance['balance'],'updateTime' => time()]);
        if (!$updateBalanceResult->isSuccess()){
            $this->objDMerchantFlow->rollBack();
            Logger::logs(E_USER_ERROR,'sql',__CLASS__,__LINE__,$updateBalanceResult->getData());
            return ResultWrapper::fail($updateBalanceResult->getData(),$updateBalanceResult->getErrorCode());
        }
        $updateSettelResult = $objMOrder->updateSettel($orderId);
        if (!$updateSettelResult->isSuccess()){
            $this->objDMerchantFlow->rollBack();
            Logger::logs(E_USER_ERROR,'sql',__CLASS__,__LINE__,$updateSettelResult->getData());
            return ResultWrapper::fail($updateSettelResult->getData(),$updateSettelResult->getErrorCode());
        }
        $this->objDMerchantFlow->commit();
        return ResultWrapper::success(true);
    }

    /**
     * Doc: (des="构建平台的流水记录")
     * User: XMing
     * Date: 2020/12/7
     * Time: 5:46 下午
     * @param float $tradeMoney
     * @param array $order
     * @param array $shop
     * @param array $enterprise
     * @return ResultWrapper
     */
    public function buildPlatform(float $tradeMoney,array $order,array $shop,array $enterprise): ResultWrapper
    {
        if($order['payType'] != StatusCode::$payType['wxPay']){
            return ResultWrapper::success([]);
        }
        $changeMoney = bcmul($tradeMoney,WX_RATE,2);
        $log = [
            'no' => createOrderSn(StatusCode::$orderType['saleOrder'],StatusCode::$orderType['saleOrder'],$this->onlineUserId),
            'merchantId' => $shop['merchantId'],
            'merchantName' => $shop['merchantName'],
            'shopId' => $shop['id'],
            'shopName' => $shop['name'],
            'originId' => $order['id'],
            'originNo' => $order['no'],
            'tradeMoney' => $tradeMoney,
            'payType' => $order['payType'],
            'originMoney' => $enterprise['balance'],
            'changeMoney' => $changeMoney,
            'nowMoney'    => $enterprise['balance'],//不改变余额
            'rate'        => WX_RATE,
            'fee'         => $changeMoney,
            'type'        => StatusCode::$standard,
            'isPayment'   => StatusCode::$standard,
            'isPlatform'  => StatusCode::$standard,
            'source'      => 1,
            'describe'    => '本次交易微信支付金额:'.$tradeMoney.'元,微信交易手续费:'.$changeMoney.'元,不计入平余额',
        ];
        $buildLog = self::buildFlowData($log);
        return ResultWrapper::success([$buildLog]);
    }


    /**
     * Doc: (des="构建商户的流水记录")
     * User: XMing
     * Date: 2020/12/7
     * Time: 5:46 下午
     * @param float $tradeMoney
     * @param array $order
     * @param array $shop
     * @param array $enterprise
     * @return ResultWrapper
     */
    public function buildMerch(float $tradeMoney,array $order,array $shop,array $enterprise): ResultWrapper
    {
        $originMoney = $shop['balance'];
        $nowMoney = bcadd($originMoney,$tradeMoney,2);
        $logs = [];
        $finalBalance = $nowMoney;
        $finalOrderNum = bcadd($shop['orderNum'],1);
        $step_one = [
            'no' => createOrderSn(StatusCode::$orderType['saleOrder'],StatusCode::$orderType['saleOrder'],$this->onlineUserId),
            'merchantId' => $shop['merchantId'],
            'merchantName' => $shop['merchantName'],
            'shopId' => $shop['id'],
            'shopName' => $shop['name'],
            'originId' => $order['id'],
            'originNo' => $order['no'],
            'tradeMoney' => $tradeMoney,
            'payType' => $order['payType'],
            'originMoney' => $originMoney,
            'changeMoney' => $tradeMoney,
            'nowMoney'    => $nowMoney,
            'rate'        => 0,
            'fee'         => 0,
            'type'        => StatusCode::$standard,
            'isPayment'   => StatusCode::$delete,
            'isPlatform'  => StatusCode::$delete,
            'source'      => 1,
            'describe'    => '本次交易支付金额:'.$tradeMoney.'元',
        ];
        $logs[] = $step_one;

        Logger::logs(E_USER_ERROR,'订单数据--',__CLASS__,__LINE__,$order);
        if ($order['payType'] == StatusCode::$payType['wxPay']){
            $fee = bcmul($tradeMoney,WX_RATE,2);
            $step_two = [
                'no' => createOrderSn(StatusCode::$orderType['saleOrder'],StatusCode::$orderType['saleOrder'],$this->onlineUserId),
                'merchantId' => $shop['merchantId'],
                'merchantName' => $shop['merchantName'],
                'shopId' => $shop['id'],
                'shopName' => $shop['name'],
                'originId' => $order['id'],
                'originNo' => $order['no'],
                'tradeMoney' => $tradeMoney,
                'payType' => $order['payType'],
                'originMoney' => $nowMoney,//上次计算后的金额
                'changeMoney' => $fee,
                'nowMoney'    => bcsub($nowMoney,$fee,2),
                'rate'        => WX_RATE,
                'fee'         => $fee,
                'type'        => StatusCode::$delete,
                'isPayment'   => StatusCode::$standard,
                'isPlatform'  => StatusCode::$delete,
                'source'      => 1,
                'describe'    => '本次微信交易支付金额:'.$tradeMoney.'元,微信交易手续费:'.$fee.'元',
            ];
            $finalBalance = bcsub($finalBalance,$fee,2);
            $logs[] = $step_two;
        }

        $return = [
            'logs' => $logs,
            'updateBalance' => [
                'shopId' => $shop['id'],
                'merchantId' => $shop['merchantId'],
                'balance'  => $finalBalance,
                'orderNum' => $finalOrderNum,
            ],
        ];
        return ResultWrapper::success($return);
    }

    /**
     * Doc: (des="添加流水记录")
     * User: XMing
     * Date: 2020/12/7
     * Time: 3:48 下午
     * @param array $params
     * @return ResultWrapper
     */
    public function add(array $params): ResultWrapper
    {
        $insert  = self::buildFlowData($params);
        $result = $this->objDMerchantFlow->insert($insert);
        if ($result === false){
            return ResultWrapper::fail($this->objDMerchantFlow->error,ErrorCode::$dberror);
        }
        return ResultWrapper::success(true);
    }

    /**
     * Doc: (des="构建流水记录数据")
     * User: XMing
     * Date: 2020/12/7
     * Time: 3:50 下午
     * @param array $params
     * @return array
     */
    private static function buildFlowData(array $params): array
    {
        return [
            "no"           => getArrayItem($params, 'no', createOrderSn(StatusCode::$orderType['saleOrder'],StatusCode::$orderType['saleOrder'],1)),
            //varchar(30) DEFAULT NULL COMMENT '流水号',
            "merchantId"   => getArrayItem($params, 'merchantId', 0),
            //int(10) DEFAULT NULL COMMENT '商户Id',
            "merchantName" => getArrayItem($params, 'merchantName', ''),
            //varchar(30) DEFAULT NULL COMMENT '商户名称',
            "shopId"       => getArrayItem($params, 'shopId', 0),
            //int(10) DEFAULT NULL COMMENT '店铺Id',
            "shopName"     => getArrayItem($params, 'shopName', ''),
            //varchar(30) DEFAULT NULL COMMENT '店铺名称',
            "originId"     => getArrayItem($params, 'originId', 0),
            //int(10) DEFAULT NULL COMMENT '原单据id',
            "originNo"     => getArrayItem($params, 'originNo', ''),
            //varchar(30) DEFAULT NULL COMMENT '原始单号',
            "tradeMoney"   => getArrayItem($params, 'tradeMoney', '0.00'),
            //decimal(10,2) NOT NULL COMMENT '流水金额 eg: 支付100元 提现100元',
            "payType"      => getArrayItem($params, 'payType', 0),
            //tinyint(3) NOT NULL DEFAULT '0' COMMENT '支付方式',
            "originMoney"  => getArrayItem($params, 'originMoney', '0.00'),
            //decimal(10,2) NOT NULL COMMENT '原金额',
            "changeMoney"  => getArrayItem($params, 'changeMoney', '0.00'),
            //decimal(10,2) NOT NULL COMMENT '变动金额',
            "nowMoney"     => getArrayItem($params, 'nowMoney', '0.00'),
            //decimal(10,2) NOT NULL COMMENT '变动后金额',
            "rate"         => getArrayItem($params, 'rate', '0.00'),
            //decimal(10,4) DEFAULT NULL COMMENT '抽成比率 eg: 0.006% (0.006)',
            "fee"          => getArrayItem($params, 'fee', '0.00'),
            //decimal(10,2) DEFAULT NULL COMMENT '抽成金额',
            "type"         => getArrayItem($params, 'type', 0),
            //tinyint(3) DEFAULT '5' COMMENT '5加 4减',
            "isPayment"    => getArrayItem($params, 'isPayment', 0),
            //tinyint(3) DEFAULT '4' COMMENT '是否是第三方支付手续费 5是 4否',
            "isPlatform"   => getArrayItem($params,'isPlatform',0),
            //tinyint(3) DEFAULT '4' COMMENT '记录类型 4 商户 5 平台',
            "source"       => getArrayItem($params, 'source', 0),
            //tinyint(3) DEFAULT '1' COMMENT '1支付结算 2提现',
            "describe"     => getArrayItem($params, 'describe', ''),
            //varchar(50) DEFAULT 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/9
     * Time: 4:30 下午
     * @param $selectParams
     * @return ResultWrapper
     */
    public function getAll($selectParams): ResultWrapper
    {
        $fields = ' * ';
        $countFields = ' COUNT(id) AS total ';
        $whereSql = '';
        if (isset($selectParams['isPlatform']) && !empty($selectParams['isPlatform'])){
            $whereSql .= ' AND isPlatform  = '.$selectParams['isPlatform'];
        }
        if (isset($selectParams['shopId']) && !empty($selectParams['shopId'])){
            $whereSql .= ' AND shopId  = '.$selectParams['shopId'];
        }
        if (isset($selectParams['originNo']) && !empty($selectParams['originNo'])){
            $whereSql .= ' AND originNo = '.$selectParams['originNo'];
        }
        if (isset($selectParams['source']) && !empty($selectParams['source'])){
            $whereSql .= ' AND source = '.$selectParams['source'];
        }
        if (isset($selectParams['startTime']) && !empty($selectParams['startTime'])){
            $whereSql .= ' AND startTime BETWEEN '.$selectParams['startTime'].' AND '.$selectParams['endTime'];
        }
        $countSql = 'SELECT '.$countFields.' FROM qianniao_merchant_flow_'.$this->onlineEnterpriseId.' WHERE id IS NOT NULL '.$whereSql;
        $count = $this->objDMerchantFlow->query($countSql);

        $whereSql .= ' ORDER BY createTime DESC ';
        if (isset($selectParams['limit']) && !empty($selectParams['limit'])){
            $whereSql .= ' LIMIT '.$selectParams['offset'].','.$selectParams['limit'];
        }
        $sql = 'SELECT '.$fields.' FROM qianniao_merchant_flow_'.$this->onlineEnterpriseId.' WHERE id IS NOT NULL '.$whereSql;
        $lists = $this->objDMerchantFlow->query($sql);
        if ($lists === false){
            return ResultWrapper::fail($this->objDMerchantFlow->error,ErrorCode::$dberror);
        }
        $ret = [
            'data' => $lists,
            'total' => isset($count[0]['total']) ? $count[0]['total'] : 0
        ];
        return ResultWrapper::success($ret);
    }

}