<?php

namespace app\common\model;

use think\Model;
use think\Db;

/**
 * 货币模型
 */
class Wallet extends BaseModel
{
    // 日志变动类型
    const log_type = [
        1  => '系统调节',//money + -
        10  => '用户充值',//money + -
        20 => '老年大学活动报名',//money + -
    ];
    // 操作钱包余额类型
    const money_type = [
        'money' => '余额',
    ];

    protected $message = '';
    protected $data    = [];

    /**
     * 获取交易类型配置
     * @return mixed
     */
    public function getLogType($type = '')
    {
        $conf = self::log_type;
        if ($type) {
            return $conf[$type] ?: $type;
        }
        return $conf;
    }

    //获取钱包名称
    public function getWalletName($name = '')
    {
        $conf = self::money_type;
        if ($name) {
            return $conf[$name] ?: $name;
        }
        return $conf;
    }

    /**
     * 获取钱包余额
     * @param int $user_id 用户编号
     * @param string $wallet_name 指定钱包名
     * @return array|float
     */
    public function getWalletBak($user_id = 0, $wallet_name = '')
    {
        //所有钱包余额
        if (!$wallet = Db::name('user_wallet')->where(['user_id' => $user_id])->find()) {
            abort(500, '钱包余额获取失败');
        }

        if ($wallet_name) { //返回指定钱包
            return isset($wallet[$wallet_name]) ? $wallet[$wallet_name] : 0;
        } else { //返回所有钱包
            return $wallet;
        }
    }

    public function getWallet($user_id = 0, $wallet_name = 'money')
    {
        return Db::name('user')->where('id',$user_id)->value($wallet_name);
    }


    /**
     *
     * @param floatval $number 金额(正数进账,负数出账)
     * @param $accountType 货币类型,money,score
     * @param $logtype 日志的类型
     * @param $remark  备注
     * @param $user_id  用户id
     * @param $table  来源表
     * @param $data_id  表id
     * @param $isAdmin 是否是管理员处理
     * @return array
     * @return array[status]
     * @return array[msg]
     * @return array[log_table]
     * @return array[log_id]
     */
    public function lockChangeAccountRemain($user_id, $accountType = 'money', $number, $logtype = '', $remark = '', $table = '', $table_id = 0, $isAdmin = false)
    {
        //初始化
        $result = array(
            'status'    => false,
            'msg'       => '',
            'log_table' => '',
            'log_id'    => '',
        );

        //获取小数点
        $point = $accountType == 'money' ? 2 : 0;
        bcscale($point);

        //钱包名称
        $wallet_name = $this->getWalletName($accountType);

        //检测
        $number = floatval($number);
        if ($number == 0) {
            $result['msg'] = '交易金额:0';
            return $result;
        }
        if (0 === bccomp($number, 0)) {
            $result['msg'] = '交易金额:0';
            return $result;
        }


        //检测
        $wallet = Db::name('user_wallet')->lock(true)->where(['user_id' => $user_id])->find();
        if (!$wallet) {
            $result['msg'] = '不存在的用户';
            return $result;
        }

        if (bccomp(bcadd($wallet[$accountType], $number), 0) === -1) {
            $result['msg'] = $wallet_name . '余额不足!';
            return $result;
        } else {
            if (0 !== bccomp($number, 0)) {

                //钱币记录
                $data             = array();
                $data['user_id']  = $user_id;
                $data['log_type'] = $logtype;
//                $data['money_type'] = $accountType;
                $data['before']       = $wallet[$accountType];
                $data['change_value'] = $number;
                $data['remain']       = bcadd($wallet[$accountType], $number);
                $data['table']        = $table;
                $data['table_id']     = $table_id;
                $data['remark']       = $remark;
                $data['createtime']   = time();
                $data['updatetime']   = time();

                //新的方式
                $rs1 = Db::name('user_wallet')->where(['user_id' => $user_id])->update([$accountType => $data['remain']]);


                /////////////
                $log_table = 'user_' . $accountType . '_log';

                $rs2_id = Db::name($log_table)->insertGetId($data);

                if ($rs1 === false || $rs2_id === false) {
                    $result['msg'] = '更新财务记录失败!';
                    return $result;
                }

                if ($rs1 !== false && $rs2_id !== false) {
                    $result['status']    = true;
                    $result['msg']       = '账户余额已更新!';
                    $result['log_table'] = $log_table;
                    $result['log_id']    = $rs2_id;

                    return $result;
                } else {
                    $result['msg'] = '更新财务记录失败!';
                    return $result;
                }
            } else {
                $result['msg'] = '金额不足0.01';
                return $result;
            }
        }
    }

    /**
     * 余额变更
     * @param int $user_id 用户id
     * @param float $number 金额(正数进账,负数出账)
     * @param string $accountType 货币类型 self::money_type
     * @param int $log_type 日志的类型 self::log_type
     * @param string $remark 备注
     * @param string $table 来源表
     * @param int $table_id 表id
     * @return bool
     */
    public function change(int $user_id, float $number, string $accountType = 'money', int $log_type = 0, string $remark = '', string $table = '', int $table_id = 0)
    {
        //获取小数点
        $point = $accountType == 'money' ? 2 : 0;
        bcscale($point);

        //钱包名称
        $wallet_name = $this->getWalletName($accountType);

        //检测
        if ($number == 0 || 0 === bccomp($number, 0)) {
            return $this->error('交易金额:0');
        }

        //检测
        if (!$wallet = Db::name('user_wallet')->lock(true)->where(['user_id' => $user_id])->find()) {
            return $this->error('不存在的用户');
        }

        if (bccomp(bcadd($wallet[$accountType], $number), 0) === -1) {
            return $this->error("{$wallet_name}余额不足!");
        }

        //钱币记录
        $data = [
            'user_id'      => $user_id,
            'log_type'     => $log_type,
            'before'       => $wallet[$accountType],
            'change_value' => $number,
            'remain'       => bcadd($wallet[$accountType], $number),
            'table'        => $table,
            'table_id'     => $table_id,
            'remark'       => $remark,
            'createtime'   => time(),
            'updatetime'   => time(),
        ];
        //新的方式
        $upWallet = Db::name('user_wallet')->where(['user_id' => $user_id])->update([$accountType => $data['remain']]);
        if ($upWallet === false) {
            return $this->error("更新账户余额失败!");
        }
        if (!Db::name("user_{$accountType}_log")->insertGetId($data)) {
            return $this->error("更新财务记录失败!");
        }

        return $this->success("账户余额已更新!");
    }

    protected function success($message = '', $data = [])
    {
        $this->message = $message;
        $this->data    = $data;
        return true;
    }

    protected function error($message = '', $data = [])
    {
        $this->message = $message;
        $this->data    = $data;
        return false;
    }

    public function getMessage()
    {
        return $this->message;
    }

    public function getData($name = null)
    {
        $data = $this->data;
        !empty($name) && $data = $this->data[$name];
        return $data;
    }
}