<?php


namespace app\models\mining;


use app\models\user\User;
use app\models\user\UserLevel;
use app\models\user\UserMoney;
use crmeb\basic\BaseModel;
use crmeb\traits\ModelTrait;
use think\db\Query;
use think\Exception;

class MiningMachine extends BaseModel
{
    /**
     * 数据表主键
     * @var string
     */
    protected $pk = 'id';
    /**
     * 模型名称
     * @var string
     */
    protected $name = 'mining_machine';
    use ModelTrait;

    /**
     * @return MiningMachine
     */
    public static function valid()
    {
        return self::where('is_del', 0);
    }

    /**
     * @param int $page
     * @param int $limit
     * @param array $where
     * @return array
     */
    public static function getList(int $page = 1, int $limit = 10, array $where = []): array
    {
        $money_type = init_money_type();
        $model = self::valid();
        if (isset($where['get_money_type']) && $where['get_money_type'] != '') $model = $model->where('get_money_type', $where['get_money_type']);
        if (isset($where['type']) && $where['type'] != '') $model = $model->where('type', $where['type']);
        $count = $model->count();
        $data = $model->order('id', 'desc')->page($page, $limit)->select()->each(function ($item) use ($money_type, $where) {
            $item['_day_get'] = $item['day_get'] . $money_type[$item['get_money_type']] . '/T';
            $item['_cost_money'] = $item['cost_money'] . $money_type[$item['cost_money_type']];
            $item['_stand_money'] = $item['stand_money'] . $money_type[$item['get_money_type']];
            $item['tags'] = explode(',', $item['tags']);
            $item['award_ratio'] = 0;
            //$item['service'] = explode(',', $item['tags']);
            if (isset($where['uid']) && $where['uid']) {
                $uids = User::where('spread_uid', $where['uid'])->column('uid');
                $item['award_ratio'] = UserMiningRatio::where('uid', $where['uid'])->where('mid', $item['id'])->value('ratio') ?: 0;
                $item['lower_award_ratio'] = UserMiningRatio::where('mid', $item['id'])->where('uid', 'in', $uids)->max('ratio') ?: 0;
                $item['user_service_ratio'] = UserMiningService::where('uid', $where['uid'])->where('mid', $item['id'])->value('ratio') ?: $item['service_ratio'];
                $item['lower_service_ratio'] = UserMiningService::where('mid', $item['id'])->where('uid', 'in', $uids)->min('ratio') ?: $item['service_ratio'];
            }
        })->toArray();
        return compact('count', 'data');
    }

    public static function buyMachine($id, $uid, $num)
    {
        $info = self::valid()->where('id', $id)->find();
//        if (bcmod($num, $info['step'], 2) > 0) return self::setErrorInfo('算力值错误');
        if ($num < $info['step']) return self::setErrorInfo('垓矿机单次购买算力不小于' . $info['step']);
        if (!$info) {
            return self::setErrorInfo('矿机已下架或不存在');
        }
        if ($info['stock'] < $num) {
            return self::setErrorInfo('矿机不足');
        }
        $money_type = init_money_type();
        $user_money = UserMoney::initialUserMoney($uid, $info['cost_money_type']);
        $user_money_stand = UserMoney::initialUserMoney($uid, $info['get_money_type']);
        if ($info['cost_money_type'] == $info['get_money_type']) {
            $cost_money = bcadd($info['cost_money'], $info['stand_money'], 8);
            $stand_money = 0;
        } else {
            $cost_money = $info['cost_money'];
            $stand_money = $info['stand_money'];
        }
        $cost_money = bcmul($cost_money, $num);
        $stand_money = bcmul($stand_money, $num);
        $info['cost_money'] = bcmul($info['cost_money'], $num);
        $info['stand_money'] = bcmul($info['stand_money'], $num);
        if ($user_money['money'] < $cost_money) {
            return self::setErrorInfo('购买矿机所需的' . $money_type[$info['cost_money_type']] . '不足');
        }
        if ($user_money_stand['money'] < $stand_money) {
            return self::setErrorInfo('部署矿机需质押的' . $money_type[$info['stand_money_type']] . '(包含GAS)不足');
        }
        BaseModel::beginTrans();
        try {
            $res1 = UserMoney::expendMoney($uid, $info['cost_money_type'], $cost_money, 'buy_machine', '购买矿机', '购买矿机' . $info['name'] . '*' . $num);
            $res2 = true;
            if ($stand_money > 0)
                $res2 = UserMoney::expendMoney($uid, $info['stand_money_type'], $stand_money, 'buy_machine_stand', '部署矿机质押', '部署矿机' . $info['name'] . '*' . $num . ',' . '质押(包含GAS费)');
            if ($res1 && $res2) {
                $res = UserMiningMachine::create([
                    'uid' => $uid,
                    'mid' => $id,
                    'day_get' => $info['day_get'],
                    'get_money_type' => $info['get_money_type'],
                    'cost_money' => $info['cost_money'],
                    'cost_money_type' => $info['cost_money_type'],
                    'stand_money' => $info['stand_money'],
                    'add_time' => time(),
                    'pay_time' => time(),
                    'paid' => 1,
                    'num' => $num,
                    'mining_end_time' => bcadd(bcadd(time(), bcmul($info['first_step_time'] + $info['third_step_time'] + $info['second_step_time'], 3600 * 24)), bcmul($info['stand_time'], 3600 * 24)),
                    'mining_start_time' => bcadd(time(), bcmul($info['stand_time'], 3600 * 24)),
                    'second_step_start_time' => bcadd(bcadd(time(), bcmul($info['first_step_time'], 3600 * 24)), bcmul($info['stand_time'], 3600 * 24)),
                    'third_step_start_time' => bcadd(bcadd(time(), bcmul($info['first_step_time'] + $info['second_step_time'], 3600 * 24)), bcmul($info['stand_time'], 3600 * 24)),
                ]);
                if ($res) $res = $res && self::sendRecommendAward($res) && self::bcDec($id, 'stock', $num);
                if (!$res) {
                    return BaseModel::setErrorInfo('购买失败', true);
                }
            } else {
                return BaseModel::setErrorInfo('支付失败', true);
            }
            $uper = User::getUserInfo($uid);
            while ($uper) {
                UserLevel::setLevelComplete($uper['uid']);
                $uper = User::getUserInfo($uper['spread_uid']);
            }
            BaseModel::commitTrans();
            return true;
        } catch (Exception $e) {
            return BaseModel::setErrorInfo($e->getMessage(), true);
        }
    }

    public static function sendRecommendAward($order)
    {
        $user = User::getUserInfo($order['uid']);
        $spread = User::getUserInfo($user['spread_uid']);
        if (!$spread) return true;
        $num = $order['cost_money'];
        $money_type = $order['cost_money_type'];
        $send = 0;
        $res = true;
        while ($spread) {
            $ratio = UserLevel::getUserLevelInfo(UserLevel::getUserLevel($spread['uid']), 'recommend_award_ratio');
            $brokerage = bcmul($num, bcdiv($ratio, 100, 4), 8);
            if ($brokerage > $send) {
                $res = $res && UserMoney::incomeMoney($spread['uid'], $money_type, bcsub($brokerage, $send, 8), 'buy_machine_spread_brokerage', '推荐佣金', '下级用户' . $user['nickname'] . '(' . $user['uid'] . ')' . '购买矿机' . $order['num'] . 'T,支付' . $order['cost_money'] . $order['cost_money_type'] . '获得推荐奖');
                $send = $brokerage;
            }
            $spread = User::getUserInfo($spread['spread_uid']);
        }
        return $res;
    }
}