<?php
/**
 * 和订单支付相关
 * Created by PhpStorm.
 * User: phperstar
 * Date: 2021/4/12
 * Time: 11:35 PM
 */

namespace JinDouYun\Model\Order;


use Mall\Framework\Core\ResultWrapper;
use Mall\Framework\Core\ErrorCode;
use Mall\Framework\Core\StatusCode;

use JinDouYun\Cache\SystemCache;
use JinDouYun\Cache\EnterpriseCache;

use JinDouYun\Model\System\MPaymentSetting;
use JinDouYun\Model\Customer\MMemberBalanceDetail;
use JinDouYun\Model\Finance\MReceived;
use JinDouYun\Model\Finance\MAccount;
use JinDouYun\Model\Finance\MAccountDetail;

use JinDouYun\Dao\Finance\DRefundAccount;

use Util\WeiXin\Pay;

class MPay
{
    private $enterpriseId;
    private $userCenterId;
    private $objMAccount;

    private $objDRefundAccount;

    public function __construct($enterpriseId, $userCenterId)
    {
        $this->enterpriseId = $enterpriseId;
        $this->userCenterId = $userCenterId;
        $this->objMAccount = new MAccount($enterpriseId, $userCenterId);
        $this->objMAccountDetail = new MAccountDetail($enterpriseId, $userCenterId);

        $this->objDRefundAccount = new DRefundAccount('finance');
    }

    /**
     * 退款
     * @param $orderData array 订单数据
     * @param $deleteReceived boolean 是否删除收款单
     * @param $refundData  array  退款数据
     * @param $refundWay   int    退款方式 默认原路返回
     * @return ResultWrapper
     */
    public function refund($orderData, $deleteReceived = false, $refundData = [], $refundWay = 5)
    {
        if(!isset($orderData['payType']) || empty($orderData['payType'])){
            return ResultWrapper::fail('支付方式为空', ErrorCode::$paramError);
        }

        // 如果是退款单取退款单数据 / 取消订单退款取订单数据
        $refund = [
            'id'      => (!empty($refundData)) ? $refundData['id']  :$orderData['id'],
            'no'      => (!empty($refundData)) ? $refundData['no']  :$orderData['no'],
            'orderNo' => (!empty($refundData)) ? $refundData['sourceNo']  :$orderData['no'],
            'orderId' => (!empty($refundData)) ? $refundData['originId']  : $orderData['id'],
            'money'   => (!empty($refundData)) ? $refundData['money'] : $orderData['payAmount'],
            'financeType' => (!empty($refundData)) ? '退款单退款' : '取消订单退款',
            'shopId'  => (!empty($refundData)) ? $refundData['shopId'] : $orderData['shopId'],
            'shopName'  => (!empty($refundData)) ? $refundData['shopName'] : $orderData['shopName'],
            'contactUnit' => (!empty($refundData)) ? $refundData['unitName'] : $orderData['customerName'], // 往来单位名称
            'unitId' => (!empty($refundData)) ? $refundData['unitId'] : $orderData['customerId'], // 往来单位名称
        ];

        $payType = explode(',', $orderData['payType']);

        // 后台代客下单 ，订单支付成功后操作
        if( in_array(StatusCode::$payType['cashPay'], $payType) && $orderData['payStatus'] == StatusCode::$standard ){
            //查询当前收款单的account数据
            $this->objDRefundAccount->setTable('qianniao_refund_account_' . $this->enterpriseId . '_' . date('Y', $refundData['createTime']) . '_' . ceil(date('m', $refundData['createTime']) / 3));
            $refundResult =  $this->objDRefundAccount->select(['refundId'=>$refundData['id']]);
            foreach ($refundResult as $value){
                $refund['accountId'] = $value['accountId'];
                $result = self::updateAccountMoneyAndDetail(StatusCode::$payType['cashPay'], $refund, StatusCode::$delete);
                if(!$result->isSuccess()){
                    return ResultWrapper::fail($result->getData(), $result->getErrorCode());
                }
                unset($refund['accountId']);
            }
        }

        // 组合支付/会员余额/银行打款 支付退回余额
        if( in_array(StatusCode::$payType['balance'], $payType) || in_array(StatusCode::$payType['bankLoans'], $payType) || $refundWay == StatusCode::$delete){
            //减少余额 新增会员流水记录
            $memberBalanceDetailData = [
                'customerId' => $orderData['customerId'],
                'type'       => StatusCode::$standard,
                'userCenterId' => $orderData['userCenterId'],
                'purpose'    => (!empty($refundData)) ? '退货退款' : '取消订单退款',
                'orderIds'   => $refund['orderId'],
                'remark'     => '订单no'.$refund['orderNo'],
                'money'      => $refund['money'],
                'financeType' => '会员余额退款'
            ];

            $objMMemberBalanceDetail = new MMemberBalanceDetail($this->enterpriseId,$this->userCenterId);
            $memberBalanceDbResult = $objMMemberBalanceDetail->addMemberBalanceDetail($memberBalanceDetailData);
            if (!$memberBalanceDbResult->isSuccess()) {
                return ResultWrapper::fail($memberBalanceDbResult->getData(), $memberBalanceDbResult->getErrorCode());
            }

            // 银行打款支付退款同步减银行打款账户
            if( in_array(StatusCode::$payType['bankLoans'], $payType) ){
                $extends = json_decode($orderData['extends'], true);
                if( isset($extends['bankData']['id']) && !empty($extends['bankData']['id'])){
                    $refund['accountId'] = $extends['bankData']['id'];
                    $result = self::updateAccountMoneyAndDetail(StatusCode::$payType['bankLoans'], $refund, StatusCode::$delete);
                    if(!$result->isSuccess()){
                        return ResultWrapper::fail($result->getData(), $result->getErrorCode());
                    }
                    unset($refund['accountId']);
                }
            }
            
            return ResultWrapper::success('退款成功');
        }

        // 微信支付退回微信
        if( $orderData['payType'] == strval(StatusCode::$payType['wxPay']) && $refundWay == StatusCode::$standard){
            // 获取当前登录企业的小程序配置
            $objSystemCache = new SystemCache();
            $miniprogramSetting = $objSystemCache->getAppIdByEnterpriseId($this->enterpriseId);
            if (empty($miniprogramSetting)) {
                return ResultWrapper::fail('后台小程序配置项为空', ErrorCode::$configEroor);
            }
            $miniprogramSetting = json_decode($miniprogramSetting, true);//获取小程序appid
            $appid = $miniprogramSetting['appid'];

            // 获取微信支付配置项
            $objMPaymentSetting = new MPaymentSetting($this->userCenterId, $this->enterpriseId);
            $result = $objMPaymentSetting->getPayData(StatusCode::$payType['wxPay']);
            if (!$result->isSuccess() || empty($result->getData())) {
                return ResultWrapper::fail('获取微信配置错误', ErrorCode::$configEroor);
            }
            $payment = $result->getData();
            $weixinConfigData = [
                'mch_id'        => $payment['mchId'],
                'apiPartnerKey' => $payment['apiPartnerKey'],
                'appid'         => $appid
            ];
            $sslData = [
                'cert' => UPLOAD_FILE_PATH .'/'.$payment['apiclient_cert'],
                'key' => UPLOAD_FILE_PATH .'/'. $payment['apiclient_key'],
            ];

            // 微信退款操作
            $objPay  =new Pay($appid, $weixinConfigData['mch_id'],$weixinConfigData['apiPartnerKey']);
            $result = $objPay->transfers($orderData['outerTradeNo'], $refund['no'],$refund['money'],$orderData['payAmount'],$sslData);
            if(!$result->isSuccess()){
                return ResultWrapper::fail($result->getData(), $result->getErrorCode());
            }

            // 微信退款完成操作微信账户
            $result = self::updateAccountMoneyAndDetail(StatusCode::$payType['wxPay'], $refund, StatusCode::$delete);
            if(!$result->isSuccess()){
                return ResultWrapper::fail($result->getData(), $result->getErrorCode());
            }
            return ResultWrapper::success($result->getData());
        }

        // 对收款单做退款流程平账
        if($deleteReceived){

        }

        return ResultWrapper::success('退款操作成功');
    }

    /**
     * 退款操作银行账户余额和流水
     * @param int $payTpye 支付方式
     * @param aray $refund 退款数据
     * @param int $type    收入支出标识 5收入 4支出
     *
     * @return ResultWrapper
     */
    public function updateAccountMoneyAndDetail($payTpye, $refund, $type)
    {
        if(isset($refund['accountId'])){
            //获取银行打款账户信息
            $accountResult = $this->objMAccount->getAccountInfo($refund['accountId']);
        }else{
            //获取微信账户信息
            $accountResult = $this->objMAccount->getDefaultAccount($payTpye);
        }
        if (!$accountResult->isSuccess()) {
            return ResultWrapper::fail($accountResult->getData(), $accountResult->getErrorCode());
        }
        $accountInfo = $accountResult->getData();
        //账户明细
        $accountDetail = [
            'accountId'          => $accountInfo['id'],
            'accountCode'        => $accountInfo['accountCode'],
            'accountName'        => $accountInfo['name'],
            'accountNumber'      => $accountInfo['accountNumber'],
            'sourceId'           => $refund['id'],
            'sourceNo'           => $refund['no'],
            'financeType'        => $refund['financeType'],
            'beginBalance'       => $accountInfo['money'],
            'shopId'             => $refund['shopId'],
            'shopName'           => $refund['shopName'],
            'contactUnit'        => '客户名称:' . $refund['contactUnit'],  // 往来单位名称
            'supplierId'         => 0,
            'customerId'         => $refund['unitId'],
            'operatorId'         => $this->userCenterId,
            'receiveOrPayPerson' => '平台',
            'remark'             => $refund['financeType'].$refund['money'].'元',
            'createTime'         => time(),
            'updateTime'         => time(),
        ];

        // 根据收入支出类型组装对应的数据
        if($type == StatusCode::$standard){
            $accountDetail['income'] = $refund['money'];
            $accountDetail['expend'] = 0;
            $accountDetail['endBalance'] =  bcadd($accountInfo['money'], $refund['money'], 2);

            $accountChangeMoney =  $refund['money'];
        }else{
            $accountDetail['income'] = 0;
            $accountDetail['expend'] = $refund['money'];
            $accountDetail['endBalance'] =  bcsub($accountInfo['money'], $refund['money'], 2);

            $accountChangeMoney =  -1 * $refund['money'];
        }

        $result = $this->objMAccountDetail->addAccountDetail($accountDetail);
        if (!$result->isSuccess()) {
            return ResultWrapper::fail($result->getData(), $result->getErrorCode());
        }

        $result = $this->objMAccount->updateMoney($accountInfo['id'], $accountChangeMoney);
        if (!$result->isSuccess()) {
            return ResultWrapper::fail($result->getData(), $result->getErrorCode());
        }

        return ResultWrapper::success($result->getData());
    }
}