<?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\Exception;

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


    /**
     * @param int $status
     * @return UserMiningMachine
     */
    public static function valid($status = 1)
    {
        return self::where('status', $status)->where('mining_start_time', '<=', time())
            ->where('mining_end_time', '>', time())->where('paid', 1);
    }

    /**
     * @return UserMiningMachine
     */
    public static function dayMiningStatusStart()
    {
        return self::valid(0)->update(['status' => 1]);
    }

    /**
     * @return UserMiningMachine
     */
    public static function dayMiningStatusEnd()
    {
        return self::where('status', 'in', [0, 1])->where('mining_end_time', '<=', time())
            ->where('paid', 1)->update(['status' => 2]);
    }

    public static function dayMining()
    {
        $p = file_get_contents('mass_ratio');
        $p = explode('*-&-*', $p);
        if ($p[0] != date('Y-m-d')) {
            $p[1] = $p[1] + 1;
        }
        $p = $p[1] > 35 ? 35 : $p[1];
        file_put_contents('mass_ratio', date('Y-m-d') . '*-&-*' . $p);
//        var_dump($p);
        //今日已发放矿机
        BaseModel::beginTrans();
        self::dayMiningStatusEnd();
        self::dayMiningStatusStart();
        try {
            $res = true;
            $send_ids = UserMining::where('add_date', date('Y-m-d'))->column('umid');
//            var_dump(UserMining::getLastSql());
//            var_dump($send_ids);
            //今日需发放且未发放的矿机
            $list = self::where('status', 1)->where('mining_start_time', '<=', time() - (3600 * 24))
                ->where('mining_end_time', '>', time())->where('paid', 1)->whereNotIn('id', $send_ids)->select();
//            var_dump($list);
//            var_dump($list);
            if (count($list)) {
//                var_dump($list);
                $money_types = MiningMachine::group('get_money_type')->field('COUNT(id),get_money_type')->select();
                $day_gets = [];
                foreach ($money_types as $v) {

                    if ($v['get_money_type'] == 'XCH') {
                        $day_gets[$v['get_money_type']] = get_hpool_price($v['get_money_type']);
                    } else if ($v['get_money_type'] == 'FIL') {
                        $day_gets[$v['get_money_type']] = get_fil_price();
                    } else {
                        $day_gets[$v['get_money_type']] = get_hpool_price($v['get_money_type']);
                    }
                }
                foreach ($list as $v) {
                    $machine = MiningMachine::get($v['mid']);
//                    var_dump(date('Y-m-d H:i:s',$v['third_step_start_time']));
//                    exit;
                    if (time() > $v['third_step_start_time']) {
                        //第三阶段 释放质押和未发放完的部分
                        $day_get = bcmul($machine['day_get'] > 0 ? $machine['day_get'] : $day_gets[$machine['get_money_type']], $v['num'], 8);
                        if ($v['get_money_type'] == 'XCH')
                            $day_get = bcmul($day_get, 0.84, 8);
                        if ($v['get_money_type'] == 'MASS')
                            $day_get = bcmul($day_get, 1.35 - $p * 0.01, 8);
                        $send_stand = bcdiv($v['stand_money'], $machine['third_step_time'], 8);
                        $day_unlock = 0;
                        $locks = UserMining::where('umid', $v['id'])->where('add_date', '<>', strtotime('Y-m-d'))->where('lock_money', '>', 0)->select();
                        foreach ($locks as $vv) {
                            if ($vv['lock_money'] >= $vv['day_unlock_money']) {
                                $day_unlock = bcadd($day_unlock, $vv['day_unlock_money'], 8);
                                UserMining::where('id', $vv['id'])->dec('lock_money', $vv['day_unlock_money'])->update();
                            } else {
                                $day_unlock = bcadd($day_unlock, $vv['lock_money'], 8);
                                UserMining::where('id', $vv['id'])->dec('lock_money', $vv['lock_money'])->update();
                            }
                        }
                        if (bcadd($send_stand, $day_unlock, 8)) {
                            $res = $res && UserMining::create([
                                    'umid' => $v['id'],
                                    'get_money' => bcadd($send_stand, $day_unlock, 8),
                                    'get_money_type' => $v['get_money_type'],
                                    'add_time' => time(),
                                    'unstand' => $send_stand,
                                    'unlock' => $day_unlock,
                                    'step' => 3,
                                    'add_date' => date('Y-m-d'),
                                ]);
                        }
                        if ($day_unlock > 0) {
                            $res = $res && UserMoney::incomeMoney($v['uid'], $v['get_money_type'], $day_unlock, 'mining', '挖矿', '第二阶段锁定金释放' . $day_unlock . init_money_type()[$v['get_money_type']])
                                && self::sendGroupAward($v['uid'], $v['mid'], $v['get_money_type'], $day_unlock)
                                && self::sendSystemAward($v['uid'], $v['get_money_type'], $day_unlock);
                        }
                        if ($send_stand > 0) {
                            $res = $res && UserMoney::incomeMoney($v['uid'], $v['get_money_type'], $send_stand, 'mining', '挖矿', '第一阶段质押金释放' . $send_stand . init_money_type()[$v['get_money_type']]);
                        }
                    } elseif (time() > $v['second_step_start_time']) {
                        $day_unlock = 0;
                        $locks = UserMining::where('umid', $v['id'])->where('add_date', '<>', strtotime('Y-m-d'))->where('lock_money', '>', 0)->select();
                        foreach ($locks as $vv) {
                            if ($vv['lock_money'] >= $vv['day_unlock_money']) {
                                $day_unlock = bcadd($day_unlock, $vv['day_unlock_money'], 8);
                                UserMining::where('id', $vv['id'])->dec('lock_money', $vv['day_unlock_money'])->update();
                            } else {
                                $day_unlock = bcadd($day_unlock, $vv['lock_money'], 8);
                                UserMining::where('id', $vv['id'])->dec('lock_money', $vv['lock_money'])->update();
                            }
                        }
                        $day_get = bcmul($machine['day_get'] > 0 ? $machine['day_get'] : $day_gets[$machine['get_money_type']], $v['num'], 8);
                        if ($v['get_money_type'] == 'XCH')
                            $day_get = bcmul($day_get, 0.84, 8);
                        if ($v['get_money_type'] == 'MASS')
                            $day_get = bcmul($day_get, 1.35 - $p * 0.01, 8);
                        $service_ratio = $machine['service_ratio'];
                        $service_ratio = UserMiningService::where('uid', $v['uid'])->where('mid', $machine['id'])->value('ratio') ?: $service_ratio;
                        $service_ratio = bcsub(1, bcdiv($service_ratio, 100, 4), 4);
                        $day_service_get = bcmul($service_ratio, $day_get, 8);
                        $second_step_get_ratio = bcdiv($machine['second_step_get_ratio'], 100, 4);
                        $day_real_get = bcmul($second_step_get_ratio, $day_service_get, 8);
                        $day_lock = bcsub($day_service_get, $day_real_get, 8);
                        if ($day_real_get > 0) {
                            $res = $res && UserMining::create([
                                    'umid' => $v['id'],
                                    'get_money' => bcadd($day_real_get, $day_unlock, 8),
                                    'get_money_type' => $v['get_money_type'],
                                    'add_time' => time(),
                                    'add_date' => date('Y-m-d'),
                                    'lock_money' => $day_lock,
                                    'all_lock' => $day_lock,
                                    'unlock' => $day_unlock,
                                    'step' => 2,
                                    'day_unlock_money' => bcdiv($day_lock, $machine['third_step_time'], 8),
                                ]) && UserMoney::incomeMoney($v['uid'], $v['get_money_type'], bcadd($day_real_get, $day_unlock, 8), 'mining', '挖矿', '第二阶段每日释放' . $day_get . init_money_type()[$v['get_money_type']] . ',扣除技术服务费后实际到账' . $day_real_get . init_money_type()[$v['get_money_type']] . ($day_lock > 0 ? ',锁定' . $day_lock . init_money_type()[$v['get_money_type']] : '') . ($day_unlock > 0 ? ',解锁第二阶段锁定金' . $day_unlock . init_money_type()[$v['get_money_type']] : ''))
                                && self::sendGroupAward($v['uid'], $v['mid'], $v['get_money_type'], bcadd($day_real_get, $day_unlock, 8))
//                                && self::sendGroupAward($v['uid'], $v['mid'], $v['get_money_type'], $day_get)
                                && self::sendSystemAward($v['uid'], $v['get_money_type'], bcadd($day_real_get, $day_unlock, 8));
                        }
                    } else {
//                        var_dump($day_gets);
                        $day_get = bcmul($machine['day_get'] > 0 ? $machine['day_get'] : $day_gets[$machine['get_money_type']], $v['num'], 8);
//                        var_dump($day_get);
                        if ($v['get_money_type'] == 'XCH')
                            $day_get = bcmul($day_get, 0.84, 8);
                        if ($v['get_money_type'] == 'MASS')
                            $day_get = bcmul($day_get, 1.35 - $p * 0.01, 8);
                        $service_ratio = $machine['service_ratio'];
                        $service_ratio = UserMiningService::where('uid', $v['uid'])->where('mid', $machine['id'])->value('ratio') ?: $service_ratio;
                        $service_ratio = bcsub(1, bcdiv($service_ratio, 100, 4), 4);
                        $day_service_get = bcmul($service_ratio, $day_get, 8);
                        $first_step_get_ratio = bcdiv($machine['first_step_get_ratio'], 100, 4);
                        $day_real_get = bcmul($first_step_get_ratio, $day_service_get, 8);
                        $day_stand = bcsub($day_service_get, $day_real_get, 8);
//                        var_dump($day_real_get);
//                        var_dump(compact('day_get', 'service_ratio', 'day_service_get', 'first_step_get_ratio', 'day_real_get', 'day_stand'));
                        if ($day_real_get > 0) {
                            $res = $res && UserMining::create([
                                    'umid' => $v['id'],
                                    'get_money' => $day_real_get,
                                    'get_money_type' => $v['get_money_type'],
                                    'add_time' => time(),
                                    'step' => 1,
                                    'add_date' => date('Y-m-d'),
                                ]) && UserMoney::incomeMoney($v['uid'], $v['get_money_type'], bcadd($day_real_get, 0, 8), 'mining', '挖矿', '第一阶段每日释放' . $day_get . init_money_type()[$v['get_money_type']] . ',扣除技术服务费后实际到账' . $day_real_get . init_money_type()[$v['get_money_type']] . ($day_stand > 0 ? ',质押' . $day_stand . init_money_type()[$v['get_money_type']] : ''))
                                && self::sendGroupAward($v['uid'], $v['mid'], $v['get_money_type'], bcadd($day_real_get, 0, 8))
//                                && self::sendGroupAward($v['uid'], $v['mid'], $v['get_money_type'], $day_get)
                                && self::sendSystemAward($v['uid'], $v['get_money_type'], bcadd($day_real_get, 0, 8));
                        }
                        if ($day_stand > 0) {
                            $res = $res && self::where('id', $v['id'])->inc('stand_money', $day_stand)->update();
                        }
                    }
                    MiningLog::create(['day' => date('Y-m-d'), 'mid' => $v['id'], 'mining' => $day_get]);
                }
            }
//            var_dump($res);
            if ($res) {
                BaseModel::commitTrans();
                return true;
            } else
                return self::setErrorInfo(self::getErrorInfo(), false);
        } catch (Exception $e) {
            return self::setErrorInfo($e->getMessage(), true);
        }
    }

    public static function sendGroupAward($uid, $mid, $money_type, $num)
    {
        $user = User::getUserInfo($uid);
        $spread = User::getUserInfo($user['spread_uid']);
        $ratio = UserMiningService::where('uid', $uid)->where('mid', $mid)->value('ratio');
        if (!$ratio) $ratio = MiningMachine::where('id', $mid)->value('service_ratio');
        $num = bcdiv($num, bcsub(1, bcdiv($ratio, 100, 4), 4), 8);
        $res = true;
        //var_dump($ratio);
        //var_dump($num);
        //var_dump($user);
        //var_dump($spread);
//        $send = 0;
        $v = 0;
        while ($spread) {
            $ratio2 = UserMiningService::where('uid', $spread['uid'])->where('mid', $mid)->value('ratio');
            if (!$ratio2) $ratio2 = MiningMachine::where('id', $mid)->value('service_ratio');
            //var_dump($ratio2);
            if ($ratio2 >= $ratio) {
                $spread = User::getUserInfo($spread['spread_uid']);
            } else {
                $brokerage = bcmul($num, bcdiv(bcsub($ratio, $ratio2), 100, 4), 8);
                if ($brokerage > 0) {
                    //if (bcsub($brokerage, $send, 8) > 0) {
                    $v++;
                    //$v = UserLevel::getUserLevelInfo(UserLevel::getUserLevel($spread['uid']), 'level_id');
                    $res = $res && UserMoney::incomeMoney($spread['uid'], $money_type, $brokerage, 'group_create_brokerage', '分享算力', '获得分享算力V' . $v . ':' . $user['nickname'] . '(' . $user['uid'] . ')' . '今日矿机收益分红(' . bcsub($ratio, $ratio2) . '%×' . $num . ')' . ',合计' . $brokerage . init_money_type()[$money_type]);
//                }
//                $send = $brokerage;
                    $ratio = $ratio2;
                }
                $spread = User::getUserInfo($spread['spread_uid']);
            }
        }
        return $res;
    }

    public static function sendSystemAward($uid, $money_type, $num)
    {
        $user = User::getUserInfo($uid);
        $ratio = sys_config('system_create_award_ratio', 0);
        if (!$ratio) return true;
        $brokerage = bcmul($num, bcdiv($ratio, 100, 4), 8);
        if ($brokerage <= 0) return true;
        $users = UserLevel::valiWhere()->where(function ($query) {
            $query->where('is_forever', 1)->whereOr('valid_time', '>', time());
        })->where('system_create_award_ratio', 1)->column('uid');
        foreach ($users as &$v) {
            if (!UserLevel::getUserLevelInfo(UserLevel::getUserLevel($v), 'system_create_award_ratio')) {
                unset($v);
            }
        }
        $res = true;
        if (count($users) > 0)
            $brokerage = bcdiv($brokerage, count($users), 8);
        else
            $brokerage = 0;
        if ($brokerage > 0) {
            foreach ($users as $v) {
                $res = $res && UserMoney::incomeMoney($v, $money_type, $brokerage, 'system_create_brokerage', '系统产币分红', '获得系统用户' . $user['nickname'] . '(' . $user['uid'] . ')' . '今日矿机收益分红');
            }
        }
        return $res;
    }

    public static function getList($where)
    {
        $model = self::getOrderWhere($where, self::alias('a')
            ->join('user r', 'r.uid=a.uid', 'LEFT'), 'a.', 'r')
            ->field('a.*,r.nickname,r.phone,r.spread_uid');
        $model = $model->order('a.id desc');
        $data = ($data = $model->page((int)$where['page'], (int)$where['limit'])->select()->each(function ($item) use ($where) {
            $item['machine'] = MiningMachine::get($item['mid']);
            $item['user'] = User::getUserInfo($item['uid'])['nickname'] . '/' . $item['uid'];
            $item['_user'] = User::getUserInfo($item['uid']);
            $item['sum_get'] = UserMining::where('umid', $item['id'])->sum('get_money');
            $item['sum_lock'] = UserMining::where('umid', $item['id'])->sum('lock_money');
            $item['_add_time'] = date('Y-m-d H:i:s', $item['add_time']);
            $item['_stop_time'] = date('Y-m-d H:i:s', $item['mining_end_time']);
            $item['mining_end_time'] = $item['_stop_time'];
            $item['_cost_money'] = $item['cost_money'] * 1 . init_money_type()[$item['cost_money_type']];
            $item['_stand_money'] = $item['stand_money'] * 1 . init_money_type()[$item['get_money_type']];
            $item['mining_end_time'] = $item['_stop_time'];
            $item['_start_time'] = date('Y-m-d H:i:s', $item['mining_start_time']);
            $item['_pay_time'] = date('Y-m-d H:i:s', $item['pay_time']);
            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['mid'])->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['mid'])->value('ratio') ?: $item['machine']['service_ratio'];
                $item['lower_service_ratio'] = UserMiningService::where('mid', $item['mid'])->where('uid', 'in', $uids)->min('ratio') ?: $item['machine']['service_ratio'];
            }
        })) && count($data) ? $data->toArray() : [];
        $count = self::getOrderWhere($where, self::alias('a')->join('user r', 'r.uid=a.uid', 'LEFT'), 'a.', 'r')->count();
        return compact('count', 'data');
    }

    public static function orderCount()
    {
        $data['wf'] = self::statusByWhere(-1, new self())->count();
        $data['dd'] = self::statusByWhere(0, new self())->count();
        $data['wk'] = self::statusByWhere(1, new self())->count();
        $data['js'] = self::statusByWhere(2, new self())->count();
        return $data;
    }

    public static function statusByWhere($status, $model = null, $alert = '')
    {
        if ($model == null) $model = new self;
        if ('' === $status)
            return $model;
        else if ($status == 0)//等待种
            return $model->where($alert . 'paid', 1)->where($alert . 'status', 0);
        else if ($status == 1)//已支付 未发货
            return $model->where($alert . 'paid', 1)->where($alert . 'status', 1);
        else if ($status == 2)//已支付  待收货
            return $model->where($alert . 'paid', 1)->where($alert . 'status', 2);
        else if ($status == -1)//未支付
            return $model->where($alert . 'paid', 0);
        else
            return $model;
    }

    public static function getBadge($where)
    {
        $price = self::getOrderPrice($where);
        $data = [
            [
                'name' => '订单数量',
                'field' => '件',
                'count' => $price['count_sum'],
                'background_color' => 'layui-bg-blue',
                'col' => 2
            ],
            [
                'name' => '算力总量',
                'field' => 'T',
                'count' => $price['total_num'],
                'background_color' => 'layui-bg-blue',
                'col' => 2
            ],
        ];
        $money_type = init_money_type();
        foreach ($money_type as $k => $v) {
            $data = array_merge(
                $data,
                [[
                    'name' => $v . '购买支付',
                    'field' => $k,
                    'count' => $price[$k . '_pay'] * 1,
                    'background_color' => 'layui-bg-blue',
                    'col' => 2
                ], [
                    'name' => $v . '质押',
                    'field' => $k,
                    'count' => $price[$k . '_stand'] * 1,
                    'background_color' => 'layui-bg-blue',
                    'col' => 2
                ]]
            );
        }
        return $data;
    }

    public static function getOrderWhere($where, $model, $aler = '', $join = '')
    {
        $model = self::statusByWhere($where['status'] ?? '', $model, $aler);
        if (isset($where['uid']) && $where['uid'] != '' && $where['uid'] != []) {
            if (is_array($where['uid']))
                $model = $model->where($aler . 'uid', 'in', $where['uid']);
            else
                $model = $model->where($aler . 'uid', $where['uid']);
        }
        if (isset($where['real_name']) && $where['real_name'] != '') {
            $model = $model->where($aler . 'id' . ($join ? '|' . $join . '.nickname|' . $join . '.uid|' . $join . '.phone' : ''), 'LIKE', "%$where[real_name]%");
        }
        if (isset($where['data']) && $where['data'] !== '') {
            $model = self::getModelTime($where, $model, $aler . 'add_time');
        }
        if (isset($where['cost_money_type']) && $where['cost_money_type'] !== '') {
            $model = $model->where($aler . 'cost_money_type', $where['cost_money_type']);
        }
//        var_dump($model);
        return $model;
    }

    /**
     * 处理订单金额
     * @param $where
     * @return array
     */
    public static function getOrderPrice($where)
    {
        $model = new self;
        $price = [];
        $price['count_sum'] = 0;//支付金额
        $price['total_num'] = 0;
        $money_type = init_money_type();
        foreach ($money_type as $k => $v) {
            $whereData['cost_money_type'] = $k;
            $sumNumber = self::getOrderWhere(array_merge($where, $whereData), $model)->field([
                'sum(cost_money) as sum',
                'sum(stand_money) as stand_sum',
            ])->find();
//            var_dump($sumNumber);
//            var_dump(self::getLastSql());

            $price[$k . '_pay'] = $sumNumber['sum'];
            $price[$k . '_stand'] = $sumNumber['stand_sum'];
        }
//        var_dump($where);
        $sumNumber = self::getOrderWhere($where, $model)->field([
            'sum(num) as sum_total_num',
            'count(id) as count_sum',
        ])->find();
        if ($sumNumber) {
            $price['count_sum'] = $sumNumber['count_sum'];
            $price['total_num'] = $sumNumber['sum_total_num'];
        }
        return $price;
    }
}