<?php
namespace app\api\controller;

use support\Request;
use support\think\Db;
use taoser\facade\Validate;
use app\model\Recharge as RechargeModel;
use app\model\User as UserModel;
use hg\apidoc\annotation as Apidoc;

/**
 * 充值模块
 */
class RechargeController extends BaseController{
    /**
     * 不需要鉴权的方法
     * @var array
     */
    public $noNeedAuth = ['*'];

    /**
     * 无需登录及鉴权的方法
     * @var array
     */
    public $noNeedLogin = ['notify','watch_list','updateUserBalance'];
    /**
     * 列表
     * @Apidoc\Method("POST")
     * @Apidoc\Query("page", type="int", require=true, desc="页码",default=1)
     * @Apidoc\Query("limit", type="int", require=true, desc="分页大小",default=10)
     */
    public function list()
    {
        $limit = (int)input('limit',10);
        $status = Input('status',null);
        if(!is_null($status)){
            $list = RechargeModel::where('user_id',\support\Jwt\JwtToken::getCurrentId())->where('status',$status)->order('id desc')->paginate($limit);
        }else{
            $list = RechargeModel::where('user_id',\support\Jwt\JwtToken::getCurrentId())->order('id desc')->paginate($limit);
        }
        return $this->success(__('successful'),$list->toArray());

    }
    /**
     * 创建
     * @Apidoc\Method("POST")
     * @Apidoc\Param("amount", type="string", require=true, desc="金额")
     * @Apidoc\Param("network", type="string", require=true, desc="网络")
     */
    function create(){
        return $this->create1();
    }
    public  function create2()
    {
        $user = \support\Jwt::getUser();
        $data = [
            'user_id'   => $user->id,
            'amount'    => input('amount',0),
            'network'   => input('network',''),
            'status'    =>  \app\enum\WithdrawlStatus::CREATED->value
        ];
        //验证最小金额
        if($data['amount'] < Config('site.recharge_minimum')){
            return $this->error(__('Minimum recharge of %num%',[
                '%num%' =>  Config('site.recharge_minimum')
            ]));
        }
        if (!$data['network'] || !in_array($data['network'],['BEP-20','TRC-20','wxpay','alipay','qqpay'])) {
            return $this->error(__('Network is incorrect'));
        }
        if(in_array($data['network'],['BEP-20','TRC-20'])){
            $ing_count = RechargeModel::where('user_id',$data['user_id'])->where('status',\app\enum\RechargeStatus::CREATED->value)->count('id');
            if($ing_count >= 2){
                return $this->error(__('You have reached the limit of uncompleted orders ( %max% ). Please complete the existing orders before trying to create another one.',[
                    '%max%' =>  2
                ]));
            }
            Db::startTrans();
            try {
                /** @var RechargeModel $order */
                $order = RechargeModel::create($data);
                //$order->notify_url = Request()->domain().'/api/recharge/notify';
                $order->notify_url = config('pay.notify_server').'/api/recharge/notify';
                $order->out_trade_no = $order->id;
                $order->env = 'product';
                $order->appid = Config('pay.appid');
                $order->created_at = time();
                $postdata = $order->toArray();
                unset($postdata['id']);
                //转换成USDT
                $postdata['amount'] = bcdiv($order->amount,Config('site.money_to_usdt_rate'),4);
                //折扣
                $postdata['amount'] = bcdiv($postdata['amount'],Config('site.usdt_recharge_discount'),4);
                $res = post(Config('pay.server').'/recharge/create',$postdata);
                \support\Log::alert("create res:".$res);
                //cp($res);
                $res = json_decode($res,true);
                if($res['code'] === 0){
                    $order->address = $res['data']['address'];
                }else{
                    Db::rollback();
                    return $this->error(__('Failed to create recharge order, please try again later'));
                }
                $order->allowField(['address'])->save();
                Db::commit();
                return $this->success(__('successful'),[
                    'order' =>  $order
                ]);
            } catch (\Exception $e) {
                Db::rollback();
                \support\Log::alert("create error".$e->getMessage());
                return $this->error(__('Failed to create recharge order, please try again later'));
            }
        }else{
            $sign = aesencode(json_encode($data));
            return $this->success(__('successful'),[
                'order' =>  [
                    'id'        =>  0,
                    'network'   => $data['network'],
                    'amount'    => $data['amount'],
                    "url"       => 'http://43.240.74.89:9595/pay/index?sign='.$sign
                ]
            ]);
        }
    }
    public  function create1()
    {
        $user = \support\Jwt::getUser();
        $data = [
            'user_id'   => $user->id,
            'amount'    => input('amount',0),
            'network'   => input('network',''),
            'status'    =>  \app\enum\WithdrawlStatus::CREATED->value
        ];
        //验证最小金额
        if($data['amount'] < Config('site.recharge_minimum')){
            return $this->error(__('Minimum recharge of %num%',[
                '%num%' =>  Config('site.recharge_minimum')
            ]));
        }
        if (!$data['network'] || !in_array($data['network'],['BEP-20','TRC-20','wxpay','alipay','qqpay'])) {
            return $this->error(__('Network is incorrect'));
        }
        if(in_array($data['network'],['BEP-20','TRC-20'])){
            $ing_count = RechargeModel::where('user_id',$data['user_id'])->where('status',\app\enum\RechargeStatus::CREATED->value)->count('id');
            if($ing_count >= 2){
                return $this->error(__('You have reached the limit of uncompleted orders ( %max% ). Please complete the existing orders before trying to create another one.',[
                    '%max%' =>  2
                ]));
            }
            
        }
        Db::startTrans();
        try {
            /** @var RechargeModel $order */
            $order = RechargeModel::create($data);
            if(in_array($data['network'],['BEP-20','TRC-20'])){
                //$order->notify_url = Request()->domain().'/api/recharge/notify';
                $order->notify_url = config('pay.notify_server').'/api/recharge/notify';
                $order->out_trade_no = $order->id;
                $order->env = 'product';
                $order->appid = Config('pay.appid');
                $order->created_at = time();
                $postdata = $order->toArray();
                unset($postdata['id']);
                //转换成USDT
                $postdata['amount'] = bcdiv($order->amount,Config('site.money_to_usdt_rate'),4);
                //折扣
                $postdata['amount'] = bcmul($postdata['amount'],Config('site.usdt_recharge_discount'),4);
                
                $res = post(Config('pay.server').'/recharge/create',$postdata);
                \support\Log::alert("create res:".$res);
                //cp($res);
                $res = json_decode($res,true);
                if($res['code'] === 0){
                    $order->address = $res['data']['address'];
                }else{
                    Db::rollback();
                    return $this->error(__('Failed to create recharge order, please try again later'));
                }
                $order->allowField(['address'])->save();
            }else{
                $postdata = [
                    "pid"   =>  '144604',
                    "type"   =>  $order->network,
                    "out_trade_no"   =>  $order->id,
                    "notify_url"   =>  Config('pay.notify_server').'/api/recharge/notify_ok',
                    "return_url"   =>  Config('pay.notify_server').'/api/recharge/notify_ok',
                    "name"   =>  'VIP会员',
                    "money"   =>  $order->amount,
                    "device"    => "mobile",
                    "clientip"  =>  request()->getRealIp()
                ];
                $postdata['money'] = bcdiv($postdata['money'] ,Config('site.rmb_recharge_discount'),2);

                //\support\Log::alert("create postdata:".json_encode($postdata));
                $this->getsign($postdata);
                $res = post('https://pay.yf2.cn/mapi.php',$postdata);
                \support\Log::alert("create res:".$res);
                $res = json_decode($res,true);
                if($res['code'] === 1){
                    if(isset($res['payurl'])){
                        $order->address = $res['qrcode'];
                    }elseif(isset($res['qrcode'])){
                        $order->address = $res['qrcode'];
                    }elseif(isset($res['urlscheme'])){
                        $order->address = $res['urlscheme'];
                    }
                }else{
                    Db::rollback();
                    \support\Log::error(json_encode($res));
                    throw new \Exception($res['msg']);
                }
                $order->allowField(['address'])->save();
            }
            Db::commit();
            return $this->success(__('successful'),[
                'order' =>  $order
            ]);
        } catch (\Exception $e) {
            Db::rollback();
            \support\Log::alert("create error".$e->getMessage());
            return $this->error(__('Failed to create recharge order, please try again later'));
        }
    }
    /**
     * 更新
     * @Apidoc\Method("POST")
     * @Apidoc\Param("id", type="int", require=true, desc="ID")
     * @Apidoc\Param("amount", type="string", require=true, desc="金额")
     * @Apidoc\Param("network", type="string", require=true, desc="网络")
     */
    function update(){
        $id = input('id');
        $amount = input('amount');
        $network = input('network');
        $data = [];
        if(!$id){
            return $this->error(__('Invalid parameters'));
        }
        /** @var RechargeModel $order */
        $order = RechargeModel::where('id',$id)->find();
        if(!$order){
            return $this->error(__('Order not exsit'));
        }
        if($amount && $amount != $order->amount){
            $data['amount'] = $amount;
            //验证最小金额
            if($data['amount'] < Config('site.recharge_minimum')){
                return $this->error(__('Minimum recharge of %num%',[
                    '%num%' =>  Config('site.recharge_minimum')
                ]));
            }
            $data['amount'] = bcdiv($data['amount'],Config('site.money_to_usdt_rate'),4);
        }
        if($network && $network != $order->network){
            $data['network'] = $network;
            if (!$data['network'] || !in_array($data['network'],['BEP-20','TRC-20'])) {
                return $this->error(__('Network is incorrect'));
            }
        }
        if(empty($data)){
            return $this->error(__('Invalid parameters'));
        }
        foreach($data as $field=>$value){
            $order->$field = $value;
        }
        $data['out_trade_no'] = $order->id;
        $data['action'] = 'update';
        $data['appid'] = Config('pay.appid');
        $res = post(Config('pay.server').'/recharge/create',$data);
        //\support\Log::alert("update res:".$res);
        $res = json_decode($res,true);
        //cp($res);
        if($res['code'] === 0){
            if($order->address != $res['data']['address']){
                $order->address = $res['data']['address'];
            }
        }else{
            return $this->error(__('Failed to create recharge order, please try again later'));
        }
        $order->save();
        return $this->success(__('successful'),[
            'order' =>  $order
        ]);
    }
    /**
     * 详情
     * @Apidoc\Query("id", type="string", require=true, desc="ID")
     */
    public function detail(){
        $appid = input('id');
        $vo = RechargeModel::where('id',$appid)->find();
        if($vo) {
            return $this->success(__('successful'),[
                'order' =>  $vo
            ]);
        }
        return $this->error(__("Record does not exist"));
    }
    /**
     * 转账成功异步通知
     * @Apidoc\NotParse()
     * @Apidoc\NotDebug()
     */
    public function notify(){
        $data = aesdecode(input('data'));
        $data = json_decode($data,true);
        /** @var RechargeModel $vo */
        $vo = RechargeModel::where('id',$data['out_trade_no'])->find();
        if($vo){
            if($data['result'] == 'SUCCESS'){
                if($vo->status  != \app\enum\RechargeStatus::COMPLETE->value){
                    try{
                        $vo->status  = \app\enum\RechargeStatus::COMPLETE->value;
                        $vo->txid = $data['txid'];
                        $vo->real_amount = isset($data['real_amount']) ? $data['real_amount'] : 0;
                        $vo->transfer_at = $data['transfer_at'] ?: time();
                        $vo->save();
                        //消除USDT和人民币的误差,因为USDT支付可能不是一模一样的金额
                        $money = bcmul($vo->amount ,Config('site.rmb_to_money_rate'));
                        UserModel::money($vo->user_id,$money,\app\enum\BalanceType::RECHARGE,$vo->id);
                        Hook('recharge.success',$vo);
                    }catch(\Exception $e){
                        log_write('充值回调失败:'.$e->getMessage());
                        log_write($data);
                    }
                }
            }else{
                $vo->status  = \app\enum\RechargeStatus::FAIL->value;
                $vo->txid = $data['txid'];
                $vo->reason = $data['reason'];
                $vo->save();
            }
        }
        return response("SUCCESS");
    }
    /**
     * 人民币转账成功异步通知
     * @Apidoc\NotParse()
     * @Apidoc\NotDebug()
     */
    public function notify_ok(){
        $data = Input('post.');
        $sign  = get_pay_sign($data);
        if($sign != $data['sign']){
            return response("FAIL");
        }
        /** @var RechargeModel $vo */
        $vo = RechargeModel::where('id',$data['out_trade_no'])->find();
        if($vo && isset($data['trade_status'])){
            if($data['trade_status'] === 'TRADE_SUCCESS'){
                if($vo->status  != \app\enum\RechargeStatus::COMPLETE->value){
                    try{
                        $vo->status  = \app\enum\RechargeStatus::COMPLETE->value;
                        $vo->txid = isset($data['trade_no'])  ? $data['trade_no'] : '';
                        $vo->from='pay.yf2.cn';
                        $vo->real_amount = isset($data['money']) ? $data['money'] : 0;
                        $vo->save();
                        $money = bcmul($vo->real_amount ,Config('site.rmb_to_money_rate'));
                        UserModel::money($vo->user_id,$money,\app\enum\BalanceType::RECHARGE,$vo->id);
                        Hook('recharge.success',$vo);
                    }catch(\Exception $e){
                        log_write('充值回调失败:'.$e->getMessage());
                        log_write($data);
                        return response("FAIL");
                    }
                }
            }
        }
        return response("SUCCESS");
    }
    /**
     * 根据TXID更新用户余额,补单的功能
     * @Apidoc\NotParse()
     * @Apidoc\NotDebug()
     * @return \support\Response
     */
    function update_balance_by_txid(){
        $user_id   = \support\Jwt\JwtToken::getCurrentId();
        $data = [
            'txid'    => input('txid'),
            'id'   => input('id'),
            'status'    =>  \app\enum\WithdrawlStatus::CREATED->value
        ];
        /** @var RechargeModel $vo */
        $vo = RechargeModel::where('id',$data['id'])->find();
        if($vo->user_id !=$user_id){
            return $this->error(__('permission denied'));
        }
        //验证最小金额
        if(!$data['txid']){
            return $this->error(__('Invalid parameters'));
        }
        $res = get(Config('pay.server').'/Util/txid?txid='.$data['txid']);
        $res = json_decode($res,true);
        if($res['code'] !== 0){
            return $this->error($res['msg']);
        }
        $vo->txid = $data['txid'];
        $vo->result = $res['result'];
        if($res['result'] == 'SUCCESS'){
            $vo->from = $res['from'];
            $vo->real_amount = $res['real_amount'];
            $vo->pay_time = $res['timestamp'];
            $vo->status = \app\enum\RechargeStatus::COMPLETE->value;
        }else{
            $vo->result = $res['from'];
            $vo->reason = $res['real_amount'];
            $vo->status = \app\enum\RechargeStatus::FAIL->value;
        }
        $vo->save();
        return $this->success(__('successful'));
    }
    /**
     * 根据监视上报数据更新用户余额
     * @Apidoc\NotParse()
     * @Apidoc\NotDebug()
     */
    function updateUserBalance(Request $request){
        $decimal_part = $request->post('decimal_part');
        $data = [
            'user_id'   => 0 ,  
            'amount'    =>  $request->post('amount'),
            'network'   =>  $request->post('chain'),
            'address'        =>  $request->post('to'),
            'from'      =>  $request->post('from'),
            'txid'      =>  $request->post('txid'),
            'pay_time'      =>  $request->post('pay_time'),
            'created_at'      =>  $request->post('pay_time'),
        ];
        if($data['network'] == 'TRC-20'){
            $data['user_id'] = UserModel::where('trc_recharge_address',$data['address'])->where('decimal_part',$decimal_part)->value('id');
        }else{
            $data['user_id'] = UserModel::where('bep_recharge_address',$data['address'])->where('decimal_part',$decimal_part)->value('id');
        }
        if(!$data['user_id']){
            return $this->success(__('user not exist'));
        }
        $data['real_amount'] = $data['amount'];
        //$data['pay_time'] = time();
        $data['status'] = 2;
        $vo = RechargeModel::where('txid',$data['txid'])->find();
        if($vo){
            return $this->success(__('exist'));
        }
        
        Db::startTrans();
        try{
            $idata = RechargeModel::create($data);
            UserModel::score($data['user_id'],$data['amount'],\app\enum\BalanceType::RECHARGE,$idata['id'].'');
            
            Db::commit();
            Hook('recharge.success',$idata);
            return $this->success(__('successful'));
        }catch(\Exception $e){
            Db::rollback();
            return $this->error($e->getMessage());
        }
        

    }
    /**
     * 监视列表
     * @Apidoc\NotParse()
     * @Apidoc\NotDebug()
     */
    function watch_list(){
        //$bep = UserModel::distinct(true)->column('LOWER(bep_recharge_address)');
        //$trc = UserModel::distinct(true)->column('LOWER(trc_recharge_address)');
        $bep = UserModel::distinct(true)->column('bep_recharge_address');
        $trc = UserModel::distinct(true)->column('trc_recharge_address');
        return $this->success(__('successful'),[
            'BEP-20'=>$bep,
            'TRC-20'=>$trc,
        ]);
    }
    protected function getsign(&$data, $key = "3E7551E3707DFB6B6E8A6E83B01FF437") {
        return get_pay_sign($data,$key);
    }
}