<?php

namespace api\controllers;

use Yii;
use common\components\Tools;
use api\base\BaseController;
use common\models\psources\AirDrop;
use common\service\chain33\Chain33Service;
use common\models\psources\AirDropRulePool;
use common\models\psources\CoinAirDropTrade;
use common\models\psources\AirDropApplyRecord;

class AirDropController extends BaseController
{
    public function actionValidateIdentifier()
    {
        $data = Yii::$app->request->get();

        $identifier = $data['identifier'] ?? null;
        if (false == $identifier) {
            $this->code = -1;
            $this->msg = '设备号错误,请重新输入.';
            goto doEnd;
        }

        $exist = AirDropRulePool::find()->where(['identifier' => $identifier])->one();
        if (false == $exist || false == $exist->rule) {
            $this->code = -1;
            $this->msg = '设备号错误,请重新输入.';
            goto doEnd;
        }

//        $miner_address = $data['miner_address'] ?? null;
//        if (!empty($miner_address)) {
//            $exist = AirDrop::find()->where(['identifier' => $identifier, 'miner_address' => $miner_address])->one();
//            if (false == $exist) {
//                $this->code = -1;
//                $this->msg = '设备号和矿工地址不匹配,请重新确认.';
//                goto doEnd;
//            }
//        }

        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
    }


    /**
     * 参于空投申请/空投申请列表
     * @param identifier    树莓派编号
     * @param miner_address 矿工地址
     * @param apply_ids
     * @return array
     */
    public function actionApply()
    {
        if (Yii::$app->request->isPost) {
            $data = Yii::$app->request->post();

            $identifier = $data['identifier'] ?? null;
            if (false == $identifier) {
                $this->code = -1;
                $this->msg = 'Validation failed.';
                goto doEnd;
            }
            $exist = AirDropRulePool::find()->where(['identifier' => $identifier])->one();
            if (false == $exist || false == $exist->rule) {
                $this->code = -1;
                $this->msg = 'Validation failed.';
                goto doEnd;
            }

            $model = new AirDrop();
            $model->setScenario(AirDrop::SCENARIOS_CREATE);
            $model->load($data, '');
            if (!$model->validate()) {
                $this->code = -1;
                $this->msg = $model->errors;
                goto doEnd;
            }
            $model->save();
            $apply_id = $model->id;

            $time = $exist->rule->duration - 1;
            $create_time = date('Y-m-d');
            $finish_time = date('Y-m-d', strtotime("+$time day"));
            $expiry_date = Tools::getDatesFromRange($create_time, $finish_time);
            $apply_record_model = new AirDropApplyRecord();
            foreach ($expiry_date as $key => $val) {
                $apply_record_model->setIsNewRecord(true);
                $apply_record_model->apply_id = $apply_id;
                $apply_record_model->reach = AirDropApplyRecord::REACH_NO;
                $apply_record_model->amount = $exist->rule->amount;
                $apply_record_model->token = $exist->rule->token;
                $apply_record_model->draw_status = AirDropApplyRecord::STATUS_UNDRAW;
                $apply_record_model->create_time = $val;
                $apply_record_model->update_time = $val;
                $apply_record_model->save() && $apply_record_model->id = 0;;
            }

            $redis = Yii::$app->redis_app;
            $redis->hmset('airdrop:' . $data['identifier'], 'reach', 0, 'draw_success', 0, 'income', 0, 'un_draw', 0);
            goto doEnd;
        }

        if (Yii::$app->request->isGet) {
            $page = \Yii::$app->request->get('page', 1);
            $size = \Yii::$app->request->get('size', 10);

            $data = Yii::$app->request->get();
            $identifier = $data['identifier'] ?? '';
            $miner_address = $data['miner_address'] ?? '';
            $apply_ids = isset($data['apply_ids']) ? $data['apply_ids'] : '';
            if (false == $identifier || false == $miner_address) {
                $this->code = -1;
                $this->msg = 'Validation failed.';
                goto doEnd;
            }
            $model = AirDrop::find()->select('id')->where(['identifier' => $identifier, 'miner_address' => $miner_address])->one();
            if (empty($model) || empty($model->record)) {
                goto doEnd;
            }

            $query = AirDropApplyRecord::find()
                ->select('id, reach, amount, token,draw_status, create_time, update_time')
                ->where(['apply_id' => $model['id']]);
            if (!empty($apply_ids)) {
                $apply_ids = rtrim($apply_ids, ',');
                $apply_id_arr = explode(',', $apply_ids);
                $query->andWhere(['in', 'id', $apply_id_arr]);
            }
            $query->andWhere(['>', 'draw_status', AirDropApplyRecord::STATUS_UNDRAW]);

            $items = $query->offset(($page - 1) * $size)->orderBy('update_time desc')->limit($size)->all();
            $countQuery = clone $query;
            $total = (int)$countQuery->count();

            $this->data = [
                'items' => $items,
                'total' => $total,
            ];
        }

        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
    }

    public function actionIncome()
    {
        $this->data = 0;
        $data = Yii::$app->request->get();
        $identifier = $data['identifier'] ?? '';
        $miner_address = $data['miner_address'] ?? '';
        if (false == $identifier || false == $miner_address) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }

        $model = AirDrop::find()->select('id')->where(['identifier' => $identifier, 'miner_address' => $miner_address])->one();
        if (empty($model) || empty($model->record)) {
            goto doEnd;
        }

        $this->data = AirDropApplyRecord::find()
            ->where(['apply_id' => $model['id'], 'draw_status' => AirDropApplyRecord::STATUS_DRAW_SUEEESS])
            ->sum('amount');
        if (empty($this->data)) {
            $this->data = 0;
            goto doEnd;
        }
        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => (int)$this->data];
    }

    /**
     * 验证今日是否可领取
     * @param identifier    树莓派编号
     * @return array
     */
    public function actionValidate()
    {
        $data = Yii::$app->request->get();
        $identifier = $data['identifier'] ?? '';
        if (false == $identifier) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }

        $air_drop = AirDrop::find()->select('id')->where(['identifier' => $identifier])->one();
        if (empty($air_drop) || empty($air_drop->record)) {
            $this->code = -1;
            $this->msg = '设备号错误,请重新确认.';
            goto doEnd;
        }

        $amount = AirDropApplyRecord::find()
            ->where(['apply_id' => $air_drop['id'], 'draw_status' => AirDropApplyRecord::STATUS_DRAW_SUEEESS])
            ->sum('amount');
        if ($amount >= 1000) {
            $this->data = false;
            goto doEnd;
        }

        $redis = Yii::$app->redis_app;
        if (true == $redis->exists($identifier)) {
            $this->data = false;
            goto doEnd;
        }
        $this->data = true;

        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
    }

    /**
     * 空投领取情况
     * @param identifier    树莓派编号
     * @param miner_address 矿工地址
     * @return array
     */
    public function actionInfo()
    {
        if (Yii::$app->request->isPost) {
            $this->code = -1;
            $this->msg = '请求方式错误!';
            goto doEnd;
        }

        $data = Yii::$app->request->get();
        $identifier = $data['identifier'] ?? null;
        if (false == $identifier) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }

        $redis = Yii::$app->redis_app;
        list($reached_times, $draw_success, $income, $un_draw) = $redis->hmget('airdrop:' . $identifier, 'reached_times', 'draw_success', 'income', 'un_draw');
        $exist = AirDropRulePool::find()->where(['identifier' => $identifier])->one();
        if (false == $exist) {
            $reach = 0;
        } else {
            $reach = $exist->rule->duration;
        }
        $this->data = [
            'reach' => empty($reach) ? 0 : (int)$reach,
            'reached_times' => empty($reached_times) ? 0 : (int)$reached_times,
            'draw_success' => empty($draw_success) ? 0 : (int)$draw_success,
            'income' => empty($income) ? 0 : (int)$reach,
            'un_draw' => empty($un_draw) ? 0 : (int)$un_draw,
        ];

        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
    }

    public function actionBatchDraw()
    {
        $this->code = -1;
        $this->msg = '请求方式错误!';
        goto doEnd;

        if (!Yii::$app->request->isPost) {
            $this->code = -1;
            $this->msg = '请求方式错误!';
            goto doEnd;
        }

        $data = Yii::$app->request->post();
        $identifier = $data['identifier'] ?? '';
        $miner_address = $data['miner_address'] ?? '';
        if (false == $identifier || false == $miner_address) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }
        $model = AirDrop::find()->select('id')->where(['identifier' => $identifier, 'miner_address' => $miner_address])->one();

        if (empty($model) || empty($model->record)) {
            $this->code = -1;
            $this->msg = '暂无符合条件的空投申请记录';
            goto doEnd;
        }

        $record = AirDropApplyRecord::find()->where(['apply_id' => $model['id'], 'reach' => AirDropApplyRecord::REACH_YES, 'draw_status' => AirDropApplyRecord::STATUS_UNDRAW])->all();
        if (empty($record)) {
            $this->code = -1;
            $this->msg = '暂无符合条件的领取记录';
            goto doEnd;
        }
        foreach ($record as $val) {
            $val->draw_status = AirDropApplyRecord::STATUS_DRAWING;
            $val->save();
        }

        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
    }

    /**
     * 领取某日空投
     * @param identifier    树莓派编号
     * @param miner_address 矿工地址
     * @return array
     */
    public function actionDraw()
    {
        if (!Yii::$app->request->isPost) {
            $this->code = -1;
            $this->msg = '请求方式错误!';
            goto doEnd;
        }

        $data = Yii::$app->request->post();
        $identifier = $data['identifier'] ?? '';
        $miner_address = $data['miner_address'] ?? '';
        if (false == $identifier || false == $miner_address) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }

        $model = AirDrop::find()->select('id, wallet_address')->where(['identifier' => $identifier, 'miner_address' => $miner_address])->one();

        if (empty($model) || empty($model->wallet_address) || empty($model->record)) {
            $this->code = -1;
            $this->msg = '设备初始化中,请稍后再试.';
            goto doEnd;
        }
        $expiry_date = date("Y-m-d", strtotime("+1 day"));
        $record = AirDropApplyRecord::find()
            ->where(['apply_id' => $model->id, 'draw_status' => AirDropApplyRecord::STATUS_UNDRAW])
            ->andWhere(['<', 'create_time', $expiry_date])
            ->orderBy('id')
            ->limit(1)
            ->one();

        if (empty($record)) {
            $this->code = -1;
            $this->msg = '暂无符合条件的领取记录';
            goto doEnd;
        }

        $redis = Yii::$app->redis_app;
        $value = date('Y-m-d H:i:s');
        $is_locked = $redis->setnx($data['identifier'], $value);
        if (!$is_locked) {
            $this->msg = '已达今日领取上限,请明天再来!';
            $this->code = -1;
            goto doEnd;
        }

        $service = new Chain33Service();
        $execer = 'ticket';
        $result = $service->getBalance($model->wallet_address, $execer);

        if (0 == $result['code']) {
            $balance = $result['result'][0]['balance'] ?? 0;
            $frozen = $result['result'][0]['frozen'] ?? 0;
            if (($balance + $frozen) / 1e8 < 3000) {
                $this->code = -1;
                $this->msg = '未达标,请确认矿机正在挖矿后重新尝试';
                $redis->del($data['identifier']);
                goto doEnd;
            }
        }

        $record->reach = AirDropApplyRecord::REACH_YES;
        $record->draw_status = AirDropApplyRecord::STATUS_DRAWING;
        $record->update_time = date('Y-m-d');
        if (false == $record->save()) {
            $this->code = -1;
            $this->msg = $record->errors;
            goto doEnd;
        }

        $redis->setex($data['identifier'], strtotime('23:59:59') - time(), $value);

        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
    }

    /**
     * 领取某日空投 (暂停用)
     * @param id    某日id
     * @param identifier    树莓派编号
     * @param miner_address 矿工地址
     * @return array
     */
    public function actionDrawBak()
    {
        if (!Yii::$app->request->isPost) {
            $this->code = -1;
            $this->msg = '请求方式错误!';
            goto doEnd;
        }

        $data = Yii::$app->request->post();
        $id = $data['id'] ?? '';
        $identifier = $data['identifier'] ?? '';
        $miner_address = $data['miner_address'] ?? '';
        if (false == $id || false == $identifier || false == $miner_address) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }
        $model = AirDrop::find()->select('id')->where(['identifier' => $identifier, 'miner_address' => $miner_address])->one();

        if (empty($model) || empty($model->record)) {
            $this->code = -1;
            $this->msg = '暂无符合条件的空投申请记录';
            goto doEnd;
        }

        $record = AirDropApplyRecord::find()->where(['id' => $id, 'reach' => AirDropApplyRecord::REACH_YES, 'draw_status' => AirDropApplyRecord::STATUS_UNDRAW])->one();
        if (empty($record)) {
            $this->code = -1;
            $this->msg = '暂无符合条件的领取记录';
            goto doEnd;
        }

        $redis = Yii::$app->redis_app;
        $value = date('Y-m-d H:i:s');
        $is_locked = $redis->setnx($data['identifier'], $value);
        if (!$is_locked) {
            $this->msg = '已达今日领取上限,请明天再来!';
            $this->code = -1;
            goto doEnd;
        }
        $redis->setex($data['identifier'], strtotime('23:59:59') - time(), $value);
        $record->draw_status = AirDropApplyRecord::STATUS_DRAWING;
        if (false == $record->save()) {
            $this->code = -1;
            $this->msg = $record->errors;
            goto doEnd;
        }

        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
    }

    public function actionRule()
    {
        $data = Yii::$app->request->get();
        $identifier = $data['identifier'] ?? null;
        $miner_address = $data['miner_address'] ?? null;
        if (false == $identifier || false == $miner_address) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }
        $exist = AirDropRulePool::find()->where(['identifier' => $identifier])->one();
        if (false == $exist || false == $exist->rule) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }
        $token = $exist->rule->token;
        $amount = $exist->rule->amount;
        $apply = AirDrop::find()->select('id')->where(['identifier' => $identifier, 'miner_address' => $miner_address])->asArray()->one();
        if (empty($apply)) {
            $this->code = -1;
            $this->msg = 'Validation failed.';
            goto doEnd;
        }
        $record = AirDropApplyRecord::find()->select('create_time')->where(['apply_id' => $apply['id']])->orderBy('id')->asArray()->all();
        if (empty($record)) {
            $begin_time = '?';
            $over_time = '?';
        } else {
            $create_time_arr = array_column($record, 'create_time');
            $begin_time = current($create_time_arr);
            $over_time = end($create_time_arr);
        }
        $this->data = [
            'token' => $token,
            'amount' => $amount,
            'begin_time' => $begin_time,
            'over_time' => $over_time
        ];
        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => $this->data];
    }

    public function actionGameTrade()
    {
        $coins_address = Yii::$app->request->post('coins_address', '');

        if (empty($coins_address)) {
            return ['code' => -1, 'msg' => '参数不能为空'];
        }

        $coinTokenTransfer = CoinAirDropTrade::find()->where(['coins_address' => $coins_address, 'type' => CoinAirDropTrade::TYPE_GAME])->one();
        if ($coinTokenTransfer) {
            return ['code' => -1, 'data' => null, 'msg' => 'record already exists'];
        }

        $fee = 100000;
        $amount = CoinAirDropTrade::AMOUNT_GAME * 1e8;
        $execer = 'coins';
        $note = '';

        $service = new Chain33Service();
        $createRawTransaction = $service->createRawTransaction($coins_address, $amount, $fee, $note, $execer);
        if (0 != $createRawTransaction['code']) {
            $msg = $createRawTransaction['msg'];
            $code = -1;
            goto doEnd;
        }

        $txHex = $createRawTransaction['result'];
        $privkey = '72c3879f1f9b523f266a9545b69bd41c0251483a93e21e348e85118afe17a5e2';
        $expire = '1m';

        $signRawTx = $service->signRawTx($privkey, $txHex, $expire);
        if (0 != $signRawTx['code']) {
            $msg = $signRawTx['msg'];
            $code = -1;
            goto doEnd;
        }
        $sign_str = $signRawTx['result'];
        $result = $service->sendTransaction($sign_str);

        if (0 != $result['code']) {
            $msg = $result['msg'];
            $code = -1;
            goto doEnd;
        }
        $code = 1;
        $msg = $result['result'];

        doEnd :
        $airDropModel = new CoinAirDropTrade();
        $airDropModel->coins_address = $coins_address;
        $airDropModel->amount = CoinAirDropTrade::AMOUNT_GAME;
        $airDropModel->msg = $msg;
        $airDropModel->attach = 0;
        $airDropModel->balance = 0;
        $airDropModel->type = CoinAirDropTrade::TYPE_GAME;
        $airDropModel->save();

        return ['code' => $code, 'msg' => $msg];
    }

    public function actionGameTradeUpdate()
    {
        $coinAirDropTrade = CoinAirDropTrade::find()->where(['attach' => 2, 'msg' => '0'])->limit(30)->all();
        foreach ($coinAirDropTrade as $val) {
            $fee = 100000;
            $amount = 1 * 1e8;
            $execer = 'coins';
            $note = '';

            $service = new Chain33Service();
            $createRawTransaction = $service->createRawTransaction($val->coins_address, $amount, $fee, $note, $execer);
            if (0 != $createRawTransaction['code']) {
                continue;
            }

            $txHex = $createRawTransaction['result'];
            $privkey = '72c3879f1f9b523f266a9545b69bd41c0251483a93e21e348e85118afe17a5e2';
            $expire = '1m';

            $signRawTx = $service->signRawTx($privkey, $txHex, $expire);
            if (0 != $signRawTx['code']) {
                continue;
            }
            $sign_str = $signRawTx['result'];
            $result = $service->sendTransaction($sign_str);

            if (0 != $result['code']) {
                continue;
            }
            $currentModel = CoinAirDropTrade::findOne($val->id);
            $currentModel->attach = 2;
            $currentModel->balance = 0;
            $currentModel->msg = $result['result'];
            $currentModel->save();
        }
        return ['code' => 1, 'msg' => 'ok'];
    }

    public function actionGetBalance()
    {
        $coinAirDropTrade = CoinAirDropTrade::find()->where(['balance' => 0])->limit(60)->all();
        $address = [];
        foreach ($coinAirDropTrade as $val) {
            $address[] = $val->coins_address;
        }
        $service = new Chain33Service();
        $execer = 'coins';
        $result = $service->getBalance($address, $execer);
        if (0 == $result['code']) {
            $result_balance = $result['result'];
            foreach ($result_balance as $val) {
                $coinAirDropTrade = CoinAirDropTrade::find()->where(['coins_address' => $val['addr']])->one();
                if (empty($coinAirDropTrade)) continue;
                $coinAirDropTrade->balance = $val['balance'];
                $coinAirDropTrade->save();
            }
        }
        return ['code' => 1, 'msg' => 'ok'];
    }
}