<?php

namespace app\admin\controller\member;

use app\admin\controller\BaseController;
use app\common\model\MemberCashinModel;
use app\common\model\MemberOauthModel;
use app\common\model\MemberRechargeModel;
use app\common\model\PayOrderModel;
use app\common\model\WechatModel;
use EasyWeChat\Factory;
use shirne\excel\Excel;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use think\Db;
use think\facade\Log;

/**
 * 充值提现管理
 * Class PaylogController
 * @package app\admin\controller
 */
class PaylogController extends BaseController
{
    public function index($id = 0, $fromdate = '', $todate = '', $ordertype = 'all', $type = 'all', $showall = 0)
    {
        $model = Db::view('payOrder po', '*')
            ->view('Member m', ['username', 'nickname', 'avatar', 'level_id', 'mobile'], 'm.id=po.member_id', 'LEFT');

        $levels = getMemberLevels();

        if ($id > 0) {
            $model->where('po.member_id', $id);
            $this->assign('member', Db::name('member')->find($id));
        }
        if (!$showall) {
            $model->where('po.status', 'gt', 0);
        }

        if (!empty($type) && $type != 'all') {
            $model->where('po.pay_type', $type);
        } else {
            $type = 'all';
        }
        if (!empty($ordertype) && $ordertype != 'all') {
            $model->where('po.order_type', $ordertype);
        } else {
            $field = 'all';
        }

        if (!empty($todate)) {
            $totime = strtotime($todate . ' 23:59:59');
            if ($totime === false) $todate = '';
        }
        if (!empty($fromdate)) {
            $fromtime = strtotime($fromdate);
            if ($fromtime === false) $fromdate = '';
        }
        if (!empty($fromtime)) {
            if (!empty($totime)) {
                $model->whereBetween('po.create_time', array($fromtime, $totime));
            } else {
                $model->where('po.create_time', 'EGT', $fromtime);
            }
        } else {
            if (!empty($totime)) {
                $model->where('po.create_time', 'ELT', $totime);
            }
        }

        $logs = $model->order('ID DESC')->paginate(15);

        $all = ['all' => ['title' => '全部']];
        $orderTypes = array_merge($all, PayOrderModel::$orderTypes);
        $payTypes = array_merge($all, PayOrderModel::$payTypes);

        $orderDetails = [
            'order' => 'order/detail',
            'credit' => 'creditOrder/detail',
            'groupbuy' => 'groupbuy.order/detail'
        ];

        $stacrows = $model->group('po.order_type,po.pay_type')->setOption('field', [])->setOption('order', 'po.order_type')->field('po.order_type,po.pay_type,sum(po.pay_amount) as total_amount')->select();
        $statics = [];
        foreach ($stacrows as $row) {
            $statics[$row['pay_type']][$row['order_type']] = $row['total_amount'];
        }
        foreach ($statics as $k => $list) {
            $statics[$k]['sum'] = array_sum($list);
        }

        $this->assign('id', $id);
        $this->assign('fromdate', $fromdate);
        $this->assign('todate', $todate);
        $this->assign('type', $type);
        $this->assign('ordertype', $ordertype);

        $this->assign('orderTypes', $orderTypes);
        $this->assign('orderDetails', $orderDetails);
        $this->assign('payTypes', $payTypes);
        $this->assign('levels', $levels);
        $this->assign('statics', $statics);
        $this->assign('logs', $logs);
        $this->assign('page', $logs->render());
        return $this->fetch();
    }

    /**
     * 充值管理
     * @param string $key
     * @param int $status
     * @return mixed
     */
    public function recharge($key = '', $status = 0)
    {
        $model = Db::view('__MEMBER_RECHARGE__ mr', '*');
        $where = array();
        if ($status > 0) {
            switch ($status) {
                case 1:
                    $where['mr.status'] = 0;
                    $where['mr.remark'] = '';
                    break;
                case 2:
                    $where['mr.status'] = 0;
                    $where['mr.remark'] = array('NEQ', '');
                    break;
                case 3:
                    $where['mr.status'] = 1;
                    break;
                case 4:
                    $where['mr.status'] = 2;
                    break;
                default:
                    $status = 9;
            }
        }
        if (!empty($key)) {
            $where[] = array('m.username', 'LIKE', "%$key%");
        }

        $lists = $model->view('__MEMBER__ m', ['username', 'realname'], 'mr.member_id=m.id', 'LEFT')
            ->view('__PAYTYPE__ p', ['type', 'cardname', 'bank', 'cardno'], 'mr.paytype_id=p.id', 'LEFT')
            ->order('mr.id DESC')->paginate(15);

        $this->assign('lists', $lists);
        $this->assign('page', $lists->render());
        $paytype = getPaytypes();

        $total = Db::name('MemberRecharge')->where('status', 1)->sum('amount');
        $this->assign('total', $total);
        $this->assign('keyword', $key);
        $this->assign('status', $status);
        $this->assign('paytype', $paytype);
        return $this->fetch();
    }

    public function rechargeView($id)
    {
        $id = intval($id);
        $model = Db::name('MemberRecharge')->find($id);
        $member = Db::name('member')->where('id', $model['member_id'])->find();

        $paytype = Db::name('member')->where('id', $model['paytype_id'])->find();

        $this->assign('model', $model);
        $this->assign('member', $member);
        $this->assign('paytype', $paytype);
        return $this->fetch();
    }

    /**
     * 充值成功
     * @param string $id
     */
    public function rechargeupdate($id = '')
    {
        $id = intval($id);
        if ($id == 0) $this->error('参数错误 ');

        /**
         * @var MemberRechargeModel
         */
        $recharge = MemberRechargeModel::find($id);
        if (empty($recharge)) $this->error('充值单不存在');
        if ($recharge['status'] != 0) $this->error('充值单已处理过了');


        $data['status'] = 1;
        $data['audit_time'] = time();

        $recharge->updateStatus($data);
        Db::name('member')->where('id', $recharge['member_id'])->setInc('total_recharge', $recharge['amount']);
        user_log($this->mid, 'rechargeaudit', 1, '审核充值单 ' . $id, 'manager');
        $this->success('处理成功！');
    }

    /**
     * 充值撤销
     * @param string $id
     */
    public function rechargecancel($id = '')
    {
        $id = intval($id);
        if ($id == 0) $this->error('参数错误 ');
        $recharge = Db::name('member_recharge')->find($id);
        if (empty($recharge)) $this->error('充值单不存在');
        if ($recharge['status'] != 1) $this->error('充值单未成功');

        $recharge = Db::name('member_recharge')->lock(true)->find($id);
        if ($recharge['status'] != 1) $this->error('充值单未成功');

        $loged = money_log($recharge['member_id'], -$recharge['amount'], '充值撤销', 'charge');
        if ($loged) {
            $data = array();
            $data['status'] = 0;
            $data['audit_time'] = time();
            Db::name('member_recharge')->where('id', $recharge['id'])->update($data);
            Db::name('member')->where('id', $recharge['member_id'])->setDec('total_recharge', $recharge['amount']);
            user_log($this->mid, 'rechargecancel', 1, '撤销充值单 ' . $id, 'manager');
            $this->success('处理成功！');
        } else {
            $this->error('处理失败！');
        }
    }

    /**
     * 充值作废
     * @param string $id
     */
    public function rechargedelete($id = '')
    {
        $id = intval($id);
        if ($id == 0) $this->error('参数错误 ');
        $recharge = Db::name('member_recharge')->find($id);
        if (empty($recharge)) $this->error('充值单不存在');
        if ($recharge['status'] != 0) $this->error('充值单已处理过了');

        $recharge = Db::name('member_recharge')->lock(true)->find($id);
        if ($recharge['status'] != 0) $this->error('充值单已处理过了');
        $data = array();
        $data['status'] = 2;
        $data['audit_time'] = time();
        Db::name('member_recharge')->where('id', $recharge['id'])->update($data);
        user_log($this->mid, 'rechargedelete', 1, '作废充值单 ' . $id, 'manager');
        $this->success('处理成功！');
    }

    /**
     * 提现管理
     * @param string $key
     * @param string $status
     * @return mixed|\think\response\Redirect
     */
    public function cashin($key = '', $status = '')
    {
        if ($this->request->isPost()) {
            return redirect(url('', ['status' => $status, 'key' => base64url_encode($key)]));
        }
        $key = empty($key) ? '' : base64url_decode($key);
        $model = Db::view('__MEMBER_CASHIN__ mc', '*')->view('__MEMBER__ m', ['username', 'nickname', 'avatar', 'realname'], 'mc.member_id=m.id', 'LEFT');

        if (!empty($key)) {
            $model->where('m.username|m.nickname|m.realname|mc.card_name', 'LIKE', "%$key%");
        }
        if ($status !== '') {
            $model->where('m.status', $status);
        }

        $lists = $model->order('mc.id DESC')->paginate(15);


        $this->assign('lists', $lists);
        $this->assign('page', $lists->render());
        $total = Db::name('MemberCashin')->where('status', 'gt', 0)->sum('amount');
        $this->assign('ids', implode('', array_column($lists->items(), 'id')));
        $this->assign('total', $total);
        $this->assign('status', $status);
        $this->assign('keyword', $key);
        return $this->fetch();
    }

    /**
     * 导出提现记录
     * @param string $ids
     * @param string $status
     * @param string $key
     */
    public function export($ids = '', $status = '', $key = '')
    {
        $model = Db::view('__MEMBER_CASHIN__ mc', '*')->view('__MEMBER__ m', ['username', 'realname'], 'mc.member_id=m.id', 'LEFT');
        if (empty($ids)) {
            if (!empty($key)) {
                $key = base64_decode($key);
                $model->where('m.username|mc.card_name', 'LIKE', "%$key%");
            }
            if ($status !== '') {
                $model->where('m.status', $status);
            }
        } elseif ($ids == 'status') {
            $model->where('mc.status', 0);
        } else {
            $model->whereIn('mc.id', idArr($ids));
        }

        $rows = $model->order('mc.id DESC')->select();
        if (empty($rows)) {
            $this->error('没有选择要导出的项目');
        }

        $excel = new Excel();
        $excel->setHeader(array(
            '编号',
            '会员ID',
            '会员账号',
            '提现来源',
            '提现金额',
            '应转款',
            '申请时间',
            '提现方式',
            '银行',
            '分行',
            '开户名',
            '卡号',
            '状态'
        ));
        $excel->setColumnType('A', DataType::TYPE_STRING);
        $excel->setColumnType('B', DataType::TYPE_STRING);
        $excel->setColumnType('E', DataType::TYPE_STRING);
        $excel->setColumnType('F', DataType::TYPE_STRING);
        $excel->setColumnType('L', DataType::TYPE_STRING);

        foreach ($rows as $row) {
            $excel->addRow(array(
                $row['id'],
                $row['member_id'],
                $row['username'],
                money_type($row['from_field'], false),
                showmoney($row['amount']),
                showmoney($row['real_amount']),
                date('Y-m-d H:i:s', $row['create_time']),
                showcashtype($row['cashtype']),
                $row['bank_name'],
                $row['bank'],
                $row['card_name'],
                $row['cardno'],
                audit_status($row['status'], false)
            ));
        }

        $excel->output(date('Y-m-d-H-i') . '-提现单导出[' . count($rows) . '条]');
    }

    /**
     * 提现成功
     * @param string $id
     */
    public function cashupdate($id = '', $paytype = '')
    {
        $id = intval($id);
        if ($id == 0) $this->error('参数错误 ');
        $cash = MemberCashinModel::get($id);
        if (empty($cash)) $this->error('提现单不存在');
        if ($cash['status'] != 0) $this->error('提现单已处理过了');

        $successed = true;
        if ($paytype == 'wechat') {
            $successed = false;
            if ($cash['cashtype'] == 'wechat') {
                $wechats = MemberOauthModel::getAccountsByMemberAndType($cash['member_id']);
            } else {
                $wechats = WechatModel::where('account_type', 'service')->select();
            }
            if (empty($wechats)) {
                $this->error('未查询到微信服务号资料,请先设置资料');
            }

            foreach ($wechats as $wechat) {
                if (empty($wechat['cert_path']) || empty($wechat['key_path'])) continue;
                $payment = Factory::payment(WechatModel::to_pay_config($wechat, '', true));
                $paydata = [
                    'partner_trade_no' => 'CASH' . $cash['id'], // 商户订单号，需保持唯一性(只能是字母或者数字，不能包含有符号)
                    'openid' =>  $wechat['openid'],
                    'check_name' => 'NO_CHECK', // NO_CHECK：不校验真实姓名, FORCE_CHECK：强校验真实姓名
                    //'re_user_name' => $cash['card_name'], // 如果 check_name 设置为FORCE_CHECK，则必填用户真实姓名
                    'amount' => $cash['real_amount'], // 企业付款金额，单位为分
                    'desc' => '提现', // 企业付款操作说明信息。必填
                ];
                if ($cash['cashtype'] == 'wechat') {
                    $paydata['openid'] = $wechat['openid'];
                    $paydata['check_name'] = 'FORCE_CHECK';
                    $paydata['re_user_name'] = $cash['card_name'];
                } else {
                    $paydata['enc_bank_no'] = $cash['cardno'];
                    $paydata['enc_true_name'] = $cash['card_name'];
                    $paydata['bank_code'] = $this->getBankCode($cash['bank']);
                }

                $result = $payment->transfer->toBalance($paydata);
                break;
            }
            if (empty($result)) {
                $this->error('微信服务号配置不完整,请先设置资料');
            }
        } elseif ($paytype == 'wechatpack') {
            $successed = false;
            $wechats = MemberOauthModel::getAccountsByMemberAndType($cash['member_id']);
            foreach ($wechats as $wechat) {
                if (empty($wechat['cert_path']) || empty(empty($wechat['key_path']))) continue;
                $payment = Factory::payment(WechatModel::to_pay_config($wechat, '', true));
                $redpackData = [
                    'mch_billno'   => 'CASH' . $cash['id'],
                    'send_name'    => getSetting('site-name'),
                    're_openid'    => $wechat['openid'],
                    'total_num'    => 1,  //固定为1，可不传
                    'total_amount' => $cash['real_amount'],  //单位为分，不小于100
                    'wishing'      => '恭喜发财',
                    //'client_ip'    => '192.168.0.1',  //可不传，不传则由 SDK 取当前客户端 IP
                    'act_name'     => '提现',
                    'remark'       => '',
                    // ...
                ];
                $result = $payment->redpack->sendNormal($redpackData);
                break;
            }
            if (empty($result)) {
                $this->error('小程序配置不完整,请先设置资料');
            }
        } elseif ($paytype == 'wechatminipack') {
            $successed = false;
            $wechats = MemberOauthModel::getAccountsByMemberAndType($cash['member_id'], 'miniprogram');
            foreach ($wechats as $wechat) {

                if (!empty($cash['appid']) && $wechat['appid'] == $cash['appid']) {
                    if (empty($wechat['cert_path']) || empty(empty($wechat['key_path']))) {
                        $this->error('小程序支付信息配置错误');
                    }
                    //$payment=Factory::payment(WechatModel::to_pay_config($wechat));

                    $this->error('暂不支持小程序红包');
                    break;
                }
            }
        } else {
            $paytype = 'handle';
        }
        Log::info('提现:' . var_export($result, true));
        if (!empty($result)) {
            if ($result['return_code'] != 'SUCCESS') {
                $this->error($result['return_msg']);
            }
            if ($result['result_code'] == 'SUCCESS') {
                $successed = true;
            } else {
                $this->error($result['err_code'] . ':' . $result['err_code_des']);
            }
        }
        if (!$successed) {
            $this->error('支付信息配置错误');
        }


        $data = array();
        $data['paytype'] = $paytype;
        $data['status'] = 1;
        $data['audit_time'] = time();
        $cash->updateStatus($data);

        user_log($this->mid, 'cashaudit', 1, '处理提现单 ' . $id, 'manager');
        $this->success('处理成功！');
    }

    private function getBankCode($bankname)
    {
        $banklist = banklist(true);
        return isset($banklist[$bankname]) ? $banklist[$bankname] : '';
    }

    /**
     * 提现驳回
     * @param string $id
     */
    public function cashdelete($id = '')
    {
        $id = intval($id);
        if ($id == 0) $this->error('参数错误 ');
        $cash = MemberCashinModel::get($id);
        if (empty($cash)) $this->error('提现单不存在');

        if ($cash['status'] != 0) $this->error('提现单已处理过了');

        $data['status'] = -1;
        $cash->updateStatus($data);

        user_log($this->mid, 'cashdelete', 1, '驳回提现单 ' . $id, 'manager');
        $this->success('处理成功！');
    }
}
