<?php

namespace tw\services\controller;

use app\models\user\WechatUser;
use tw\services\payment\MachantPay;
use app\models\user\UserBill;
use app\models\user\UserExtract;
use app\admin\model\user\UserExtract as UserExtractAdmin;
use tw\redis\UserRds;

/**
 * 支付，提现相关业务逻辑，为了减少 Controller 部分的代码。
 * Controller 的代码不容易测试。 
 */
class PaymentService
{
    /**
     * 执行用户申請提现
     *
     * @param Object $user
     * @param array $extractInfo: 
     * 
     * ['alipay_code', ''],
     * ['extract_type', ''],
     * ['money', 0],
     * ['name', ''],
     * ['bankname', ''],
     * ['cardnum', ''],
     * ['weixin', ''],
     * 
     * @return [$ok, $err_msg]
     * 
     */
    public static function user_request_extract($user, $extractInfo)
    {
        if (!preg_match('/^(([1-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/', $extractInfo['money'])) {
            return [false, '提现金额输入有误'];
        }
        // 最小提现额度
        if ($extractInfo['money'] < sys_config('user_extract_min_price')) {
            return [false, '金额小于最低提现金额'];
        }
        // 佣金冻结天数
        $frozen_days = intval(sys_config('extract_time'));
        $valid_time = time() - 86400 * $frozen_days;
        // 冻结期获得佣金
        $brokerage_commission = UserBill::where(['uid' => $user['uid'], 'category' => 'now_money', 'type' => 'brokerage'])
            ->where('add_time', '>', $valid_time)
            ->where('pm', 1)
            ->sum('number');
        // 冻结期花费佣金
        $refund_commission = UserBill::where(['uid' => $user['uid'], 'category' => 'now_money', 'type' => 'brokerage'])
            ->where('add_time', '>', $valid_time)
            ->where('pm', 0)
            ->sum('number');
        // 冻结佣金
        $data['broken_commission'] = bcsub($brokerage_commission, $refund_commission, 2);
        if ($data['broken_commission'] < 0) {
            $data['broken_commission'] = 0;
        }
        // 总佣金
        $data['brokerage_price'] = $user['brokerage_price'];
        //可提现佣金
        $commissionCount = bcsub($data['brokerage_price'], $data['broken_commission'], 2);
        if ($extractInfo['money'] > $commissionCount) {
            return [false, '可提现佣金不足'];
        }
        if (!$extractInfo['cardnum'] == '') {
            if (!preg_match('/^([1-9]{1})(\d{14}|\d{18})$/', $extractInfo['cardnum'])) {
                return [false, '银行卡号输入有误'];
            }
        }
        $row = UserExtract::userExtract($user, $extractInfo);
        if ($row) {
            return [true, $row];
        } else {
            return [false, UserExtract::getErrorInfo('提现失败')];
        }
    }

    /**
     * 執行通過提現申請
     */
    public static function user_extract_passed($extractInfo)
    {
        // if (!UserExtractAdmin::be(['id' => $extractId, 'status' => EXTRACT_AUDITING])) {
        //     return [false, '操作记录不存在或状态错误!'];
        // }
        if ($extractInfo['status'] == EXTRACT_SUC) {
            return [false, '您已提现,请勿重复提现'];
        }
        if ($extractInfo['status'] == EXTRACT_FAILED) {
            return [false, '您的提现申请已被拒绝'];
        }

        $res = UserExtractAdmin::changeSuccess($extractInfo['id']);
        if ($res) {
            event('UserExtractSucc', [$extractInfo]);
            return [true, ''];
        } else {
            return [false, '操作失败'];
        }
    }

    /**
     * 拒絕提現申請
     */
    public static function user_extract_reject($extractId, $reason)
    {
        if (!UserExtractAdmin::be(['id' => $extractId, 'status' => EXTRACT_AUDITING])) {
            return [false, '操作记录不存在或状态错误'];
        }
        $extract = UserExtractAdmin::get($extractId);
        if (!$extract) {
            return [false, '操作记录不存在'];
        }
        if ($extract->status == EXTRACT_SUC) {
            return [false, '已经提现,错误操作'];
        }
        if ($extract->status == EXTRACT_FAILED) {
            return [false, '您的提现申请已被拒绝,请勿重复操作'];
        }
        UserExtractAdmin::beginTrans();
        $res = UserExtractAdmin::changeFail($extractId, $reason);
        if ($res) {
            UserExtractAdmin::commitTrans();
            event('UserExtractRejected', [$extract, $reason]);
            return [true, '操作成功'];
        } else {
            UserExtractAdmin::rollbackTrans();
            return [false, '操作失败'];
        }
    }

    /**
     * 用戶自動提現需要滿足的條件
     * 
     * @param array $user:
     * @return boolean:
     */
    public static function user_extract_auto_conditions($user)
    {
        // 微信支付提現到零錢：每個用戶每天提現 1 次，每次最多 200, 平臺每天限額 200,000.
        return [true, ''];
    }

    /**
     * 用户提现，集成支持的各种提现渠道
     * 
     * @param array $extractInfo: user_extract 行
     */
    public static function extract_by_api($extractInfo)
    {
        if (!$extractInfo) {
            return [false, -10404, '记录不存在'];
        }

        $trade_no = md5($extractInfo['uid'] . $extractInfo['extract_price'] . $extractInfo['add_time']);

        switch ($extractInfo['extract_type']) {
            case 'weixin':
                $openid = WechatUser::where('uid', $extractInfo['uid'])->value('routine_openid');
                //
                (new UserRds)->set($extractInfo['uid'], UserRds::FILED_WXPAYNAME, $extractInfo['real_name']);
                //
                return MachantPay::toWeixin($openid, $trade_no, $extractInfo['extract_price'], '佣金提现', $extractInfo['real_name']);
            case 'bank':
                // 记忆银行信息
                (new UserRds)->sets($extractInfo['uid'], [
                    UserRds::FIELD_BANKCARDNO => $extractInfo['bank_code'],
                    UserRds::FIELD_BANKUSER => $extractInfo['real_name'],
                    UserRds::FIELD_BANKNAME => $extractInfo['bank_address'],
                ]);
                list($ok, $fee) = MachantPay::toBankByWeixinFee($extractInfo['extract_price']);
                if (!$ok) {
                    return [false, -10001, '金额错误'];
                }
                $valid = $extractInfo['extract_price'] - $fee;
                return MachantPay::toBankByWeixin($trade_no, $valid, $extractInfo['bank_code'], $extractInfo['real_name'], $extractInfo['bank_address']);
            default:
                // 其他情况不处理，返回失败
                errlog('unbelievable error: extract_type=' . $extractInfo['extract_type']);
                return [false, -10000, '不支持的类型'];
        } // switch
    }
}
