<?php

namespace api\controllers;

use Yii;
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
{
    /**
     * 参于空投申请/空投申请列表
     * @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();

            $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();
            $total = 0;
            $items = [];
            if (empty($model) || empty($model->record)) {
                goto doEnd;
            }

            $query = AirDropApplyRecord::find()
                ->select('id, reach, amount, token,draw_status, create_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]);
            }
            $expiry_date = date("Y-m-d");
            $query->andWhere(['<', 'create_time', $expiry_date]);

            $items = $query->offset(($page - 1) * $size)->orderBy('create_time')->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'], 'reach' => AirDropApplyRecord::REACH_YES])
            ->sum('amount');
        if (empty($this->data)) {
            $this->data = 0;
            goto doEnd;
        }
        doEnd :
        return ['code' => $this->code, 'msg' => $this->msg, 'data' => (int)$this->data];
    }

    public function actionBatchDraw()
    {
        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];
    }

    public function actionDraw()
    {
        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;
        }

        $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'];
    }
}