<?php

namespace App\Http\Controllers;

use App\Models\MemberClans;
use App\Servers\Eth\Address;
use App\Servers\Eth\EthereumRPC;
use App\Servers\Eth\Utils;
use App\Servers\MemberServer;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ApiJsonController extends Controller
{
    /**
     * 合约地址
     * @var string
     */
    private $token_address = '0x6718DC858bC2EA664e6a8752E1320F1de6e0Dc52';
    /**
     * 系统钱包地址
     * @var string
     */
    private $sys_address='0x9202c91a5181dbfa44f5bd219c1065016c1d23ad';
    /**
     * 系统秘钥
     * @var string
     */
    private $sys_key='4b649bc90ece239238a3c513fb4b9d445d681c52086b91bb250280b5054639c2';

    protected $sing_key = "lu0ziiun8znpxtv8o9sdfhggfhfgsw9p6eooxw2efk";

    protected  function getNonce($address)
    {
        /** @var static $tx */
        $nonce='0x51';
        if (!empty($nonce)) {
            return Utils::dec2hex(Utils::hex2dec($nonce) + 1);
        }

//        return self::rpc()->getTransactionCount($address);
    }

    public function index()
    {

//        exit;
        //测试币名称:nntt
//        合约地址:0x6718DC858bC2EA664e6a8752E1320F1de6e0Dc52
        //0x378fb524c5dfcc2a42fbea91b9652c6457042c19
        //75c50cb3f53e579e0ac3a12897a37ce23f31ae19dcc4ef08054761b90b833465
        //测试地址主账户
        //0x9202c91a5181dbfa44f5bd219c1065016c1d23ad
        //4b649bc90ece239238a3c513fb4b9d445d681c52086b91bb250280b5054639c2
        //收款账户
        //0x51eba8cdd9d14193cb4321a63395eef616f395c3
        //925baa5153e40866a474bd1311baf058c9f3466260b2fc7e1cf1ace8065e9658

        //生成钱包地址  返回数组
        //-------------------------------生成钱包地址
//        $address = Address::generate();
//        var_dump($address);exit;
        //交易测试
//        $eth = new EthereumRPC();
//        $serviceFee = Utils::dec2hex('1500000000000000'); // 手续费
//        var_dump($serviceFee);exit;
//        $eth_num = $eth->getBalance('0x51eba8cdd9d14193cb4321a63395eef616f395c3');
//        $eth_num = '0x5d21dba00';
//        $eth_num = Utils::hex2dec($eth_num);
//        var_dump($eth_num);
//        $eth_num = Utils::int2fund($eth_num, 18);
//        var_dump($eth_num);exit;
//                $eth_num = $eth->getBalance('0x51eba8cdd9d14193cb4321a63395eef616f395c3');
//        $eth_num = Utils::hex2dec($eth_num);
//        $eth_num = Utils::int2fund($eth_num, 18);
//        var_dump($eth_num);exit;
//        var_dump($this->getTransactionReceipt('0xadc978f46ba41dc1b56bb37b37bd90b9ba63f9809678e16751693d9e130f0429'));exit;
        $from='0x02b9132724a056b43944426bbebebf07a064e972';
        $to='0xc3d7901a8eebbcd8b0873e9aa7e20440b3014761';
//        $from='0x39e505a18e29d5cb9e746b86f31771385e3b3b7b';
//        $to='0x51eba8cdd9d14193cb4321a63395eef616f395c3';
        $money=1000;
        $tx = $this->build($from, '0x2d874077a83618aab75624cc1a4974510a0eb1ae', '0x0', Utils::decodeSolMethod('transfer(address,uint256)', [$to, Utils::fund2int($money, 18)]));

//        var_dump($tx);exit;
//        $tx = $this->build($from,$to, '0x0', Utils::decodeSolMethod('transfer(address,uint256)', [$to, Utils::fund2int($money, 18)]));
//        $service_info=$this->nytrWithholdServiceCharge($tx);
//        var_dump($service_info);exit;
        $ret=$this->ntrTransferAccounts($tx,'527a4fd9bdb84d02ffb8046cb5704642969c95ca67cfa5535511fd38c358c2a1');
        var_dump($ret);exit;
//        if($from!=$this->sys_address){
//            $service_info=$this->nytrWithholdServiceCharge($tx);
//            if(!empty($service_info['data']['hash']))return ['code'=>'0','msg'=>'手续费代扣失败'];
//            //手续费哈希值
//            //0xf553bff171816ff5704aad45661f828d6b0b15e7fd84cfaaf545a71269a906eb
//            var_dump($service_info);exit;
//        }else{
//
//        }
//
        //----------------------------------------查询用户余额--------------
//        $receipt = $eth->getTransactionReceipt('0x70c6b91bb92841bcb459e91ab8255fd8352370a545a7291ae1b8d19c97d371fa');//交易查询

//        $tx = [];
//        $tx['from'] = '0x9202c91a5181dbfa44f5bd219c1065016c1d23ad';//用户地址
//        $tx['to'] = $this->token_address;//系统钱包地址
//        $tx['data'] = Utils::decodeSolMethod('balanceOf(address)', ['0x9202c91a5181dbfa44f5bd219c1065016c1d23ad']);
//        $balance = $eth->call($tx);
//        $balance = Utils::hex2dec($balance);
//        $balance = Utils::int2fund($balance); // 18位小数
//        $balance = Utils::fund2int($balance, 2);
//        var_dump('-------------------nntt余额');
//        return Utils::int2fund($balance, 2);
        //--------------获取eth的余额

//        var_dump('-------------------ETH余额');
        //-----------------代币NYTR转账测试
//        $gasPrice = $eth->getGasPrice(); // 手续费
//        var_dump($gasPrice);
//        var_dump('-------------------交易手续费');
//        $money = 100;
//         token 交易
//        $tx = $this->build('0x51eba8cdd9d14193cb4321a63395eef616f395c3', '0x6718DC858bC2EA664e6a8752E1320F1de6e0Dc52', '0x0', Utils::decodeSolMethod('transfer(address,uint256)', ['0x9202c91a5181dbfa44f5bd219c1065016c1d23ad', Utils::fund2int($money, 18)]));
//        $tx = [];
//        $tx['from'] = '0x9202c91a5181dbfa44f5bd219c1065016c1d23ad';
//        $tx['to'] = '0x6718DC858bC2EA664e6a8752E1320F1de6e0Dc52';
//        $tx['value'] = Utils::dec2hex(Utils::fund2int($money));
//        $tx['data'] = Utils::fixHex(bin2hex('transfer'));
//        if ($tx['from'] != $this->token_address) {
//            $gasLimit = $eth->estimateGas($tx);
        // 手续费交易
//            $serviceFee = Utils::dec2hex(bcmul(Utils::hex2dec($gasPrice), Utils::hex2dec($gasLimit))); // 手续费
//            $serviceTx = $this->build($this->token_address, $tx['from'], $serviceFee, Utils::fixHex(bin2hex('service charge')));
        // 广播手续费
//            $depend = EthTransaction::push($serviceTx, $this->masterKey, null);
//            if (!$depend) {
//                return false;
//            }
//        }
        $transaction = [
            'depend' => 0,
            'from' => '0x9202c91a5181dbfa44f5bd219c1065016c1d23ad',
            'to' => '0x6718DC858bC2EA664e6a8752E1320F1de6e0Dc52',
            'nonce' => '',
            'value' => !empty($tx['value']) ? $tx['value'] : '0x0',
            'data' => !empty($tx['data']) ? $tx['data'] : Utils::fixHex(bin2hex('NYT')),
            'chain_id' => $eth->chainId,
            'gas_price' => '',
            'gas_limit' => '',
            'sign' => '',
            'hash' => '',
        ];
        $nonce = $eth->getTransactionCount($transaction['from']);
        $transaction['nonce'] = $nonce;//交易顺序十六进制。由eth_getTransactionCount获取
        $gas_price = $eth->getGasPrice();
        $transaction['gas_price'] = $gas_price;//燃料十六进制。由eth_estimateGas获取
        $gas_limit = $this->getGasLimit($transaction);
        $transaction['gas_limit'] = $gas_limit;
        $sign = $this->sign($transaction, '4b649bc90ece239238a3c513fb4b9d445d681c52086b91bb250280b5054639c2');//交易签名
        $hash = $eth->sendRawTransaction($sign, $error);//广播交易
        $receipt = $eth->getTransactionReceipt($hash);//交易查询

        if (!$hash) {
            var_dump('---------------');
            var_dump($error);
            var_dump('---------------');
        }
        var_dump($receipt);
        var_dump($hash);
        var_dump($sign);
        var_dump($gas_limit);
        var_dump($gas_price);
        var_dump($nonce);
        exit;
    }

    /**
     * 查询用户NYTR余额
     * @param $eth_address  用户钱包地址
     * @return bool|mixed|string
     */
    function getNytrNum($eth_address)
    {
        $eth = new EthereumRPC();
        $tx = [];
        $tx['from'] = $eth_address;//用户地址
        $tx['to'] = $this->token_address;//系统钱包地址
        $tx['data'] = Utils::decodeSolMethod('balanceOf(address)', [$eth_address]);
        $balance = $eth->call($tx);
        $balance = Utils::hex2dec($balance);
        $balance = Utils::int2fund($balance); // 18位小数
        $balance = Utils::fund2int($balance, 2);
        return $balance;
    }

    /**
     * 获取ETH余额
     * @param $eth_address 用户钱包地址
     * @return bool|mixed|string
     */
    function getEthNum($eth_address)
    {
        $eth = new EthereumRPC();
        $eth_num = $eth->getBalance($eth_address);
        $eth_num = Utils::hex2dec($eth_num);
        $eth_num = Utils::int2fund($eth_num, 18);
        return $eth_num;
    }

    function nytrWithholdServiceCharge($tx){
        $eth = new EthereumRPC();
        $gasPrice = $eth->getGasPrice(); // 手续费
        $tx = [
            'from' => '0x02b9132724a056b43944426bbebebf07a064e972',
            'to' => '0xc3d7901a8eebbcd8b0873e9aa7e20440b3014761',
            'value'=>'0x0',
            'data'=>$tx['data'],
        ];

        $gasLimit = $eth->estimateGas($tx);
        // 手续费交易
        $serviceFee = Utils::dec2hex('2000000000000000'); // 手续费
        // 广播手续费
        //0x51eba8cdd9d14193cb4321a63395eef616f395c3
        //925baa5153e40866a474bd1311baf058c9f3466260b2fc7e1cf1ace8065e9658
        $transaction = [
            'depend' => 0,
//            'from' =>$this->sys_address,
            'from' =>'0x02b9132724a056b43944426bbebebf07a064e972',
            'to' => '0xc3d7901a8eebbcd8b0873e9aa7e20440b3014761',
            'nonce' => '',
            'value' =>$serviceFee,
            'data' => '',
            'gas' => $gasLimit,
            'chain_id' => $eth->chainId,
            'gas_price' => '',
            'gas_limit' => '',
            'sign' => '',
            'hash' => '',
        ];
        $nonce = $eth->getTransactionCount($transaction['from']);
        $transaction['nonce'] = $nonce;//交易顺序十六进制。由eth_getTransactionCount获取
        var_dump($nonce);
//        $transaction['nonce'] = $this->getNonce($tx['from']);//交易顺序十六进制。由eth_getTransactionCount获取
        var_dump($gasPrice);
        $transaction['gas_price'] =  $gasPrice;//燃料十六进制。由eth_estimateGas获取
//        $transaction['gas_price'] =  $gasPrice;//燃料十六进制。由eth_estimateGas获取
        $transaction['gas_limit'] = $gasLimit;
        var_dump($transaction);
//        $sign = $this->sign($transaction, $this->sys_key);//交易签名
        $sign = $this->sign($transaction, '527a4fd9bdb84d02ffb8046cb5704642969c95ca67cfa5535511fd38c358c2a1');//交易签名
        $hash = $eth->sendRawTransaction($sign, $error);//广播交易
        var_dump($hash);
        var_dump($error);exit;
        if (!$hash) {
            return ['code'=>'0','data'=>$error,'msg'=>empty($error['message'])?'广播交易失败':$error['message']];
        } else {
            return ['code'=>'1','data'=>['hash'=>$hash],'msg'=>'广播交易成功'];
        }


    }

    /**
     * NYTR 转账
     * @param $tx
     * @param $from_key
     * @return array
     */
    function ntrTransferAccounts($tx, $from_key)
    {
        $eth = new EthereumRPC();
        // token 交易
        $transaction = [
            'depend' => 0,//代扣手续费ID
            'from' => $tx['from'],
            'to' => $tx['to'],
            'nonce' => '',
            'value' => !empty($tx['value']) ? $tx['value'] : '0x0',
            'data' => !empty($tx['data']) ? $tx['data'] : Utils::fixHex(bin2hex('NYT')),
            'chain_id' => $eth->chainId,
            'gas_price' => '',
            'gas_limit' => '',
            'sign' => '',
            'hash' => '',
        ];
        $nonce = $eth->getTransactionCount($transaction['from']);
        $transaction['nonce'] = $nonce;//交易顺序十六进制。由eth_getTransactionCount获取
        $gas_price = $eth->getGasPrice();
        $gas_price =  Utils::dec2hex(Utils::toWei("5gwei") + Utils::hex2dec($gas_price));
        $transaction['gas_price'] = $gas_price;//燃料十六进制。由eth_estimateGas获取

        $gas_limit = $this->getGasLimit($transaction);
        $transaction['gas_limit'] = $gas_limit;
        var_dump($transaction);
        //
        $sign = $this->sign($transaction, $from_key);          //交易签名
        var_dump($sign);
        $hash = $eth->sendRawTransaction($sign, $error);//广播交易
        var_dump($hash);exit;
        if (!$hash) {
            return ['code'=>'0','data'=>$error,'msg'=>empty($error['message'])?'广播交易失败':$error['message']];
        } else {
            return ['code'=>'1','data'=>['hash'=>$hash],'msg'=>'广播交易成功'];
        }
    }

    function getSendTransaction($transaction){
        $tx = [];
        $tx['from'] = $transaction['from'];
        $tx['to'] =$transaction['to'];
        $tx['value'] =$transaction['value'];
        $tx['gas'] =$transaction['gas'];
        $tx['gasPrice'] =$transaction['gas_price'];
        $tx['nonce'] =$transaction['nonce'];
        $tx['data'] = '';

        return $tx;
    }

    /**
     * 查询交易结果
     * @param $hash
     * @return bool|mixed 成功返回交易信息  失败返回false
     */
    function getTransactionReceipt($hash)
    {
        $eth = new EthereumRPC();
        $receipt = $eth->getTransactionReceipt($hash);//交易查询
        return $receipt;
    }

    /**
     * 转账内容拼接
     * @param $from
     * @param $to
     * @param $value
     * @param $data
     * @return array
     * @throws
     */
    protected function build($from, $to, $value, $data)
    {
        $tx = [];
        $tx['from'] = $from;
        $tx['to'] = $to;
        $tx['value'] = $value;
        $tx['data'] = $data;

        return $tx;
    }


    /**
     * @param  $transaction
     * @return string
     */
    public static function getGasLimit($transaction)
    {
        $tx = [
            'from' => $transaction['from'],
            'to' => $transaction['to'],
            'nonce' => $transaction['nonce'],
            'value' => $transaction['value'],
            'data' => $transaction['data'],
            'chainId' => $transaction['chain_id'],
            'gasPrice' => $transaction['gas_price'],
        ];
        $eth = new EthereumRPC();
        $gasLimit = $eth->estimateGas($tx);
        if (!$gasLimit) {
            $gasLimit = 10 * 10000; // 预估失败, 最高10万
        }
        return $gasLimit;
    }


    protected static function sign($transaction, $key)
    {
        $tx = [
            'from' => $transaction['from'],
            'to' => $transaction['to'],
            'nonce' => $transaction['nonce'],
            'value' => $transaction['value'],
            'data' => $transaction['data'],
            'chainId' => $transaction['chain_id'],
            'gasPrice' => $transaction['gas_price'],
            'gasLimit' => $transaction['gas_limit'],
        ];
        // 数据签名
        $tr = new Transaction($tx);
        $tr->sign($key);
        return Utils::fixHex($tr->serialize()->toString('hex'));
    }

    public function nytr()
    {
        $member = Member::where('username', request()->input('user_name', ''))->first();

        if( empty($member) ){
            return response()->json([
                'msg'   => '账户不存在',
                'data'  => [],
                'code'  => 0,
            ]);
        }

        $sign = $this->wxSign([
            'user_name' => request()->input('user_name', ''),
            'money' => request()->input('money', ''),
            'send_time' => request()->input('send_time', ''),
            'token' => request()->input('token', ''),
        ]);

        if( $sign != strtoupper(request()->input('token', '')) ){
            return response()->json([
                'msg'   => 'token错误',
                'data'  => [],
                'code'  => 0,
            ]);
        }

        if( request()->input('money', '') <= 0 ){
            return response()->json([
                'msg'   => '数目小于等于零',
                'data'  => [],
                'code'  => 0,
            ]);
        }

        // 会员添加NYTR
        try{
            DB::beginTransaction();

            Member::where('id', $member->{'id'})->increment('old_nytr', request()->input('money', '') * MemberServer::$NYTR);
            DB::table('nytr_nyts')->insert([
                'member_id'     => $member->{'id'},
                'username'      => $member->{'username'},
                'money'         => request()->input('money', ''),
                'updated_at'    => date('Y-m-d H:i:s', time()),
                'created_at'    => date('Y-m-d H:i:s', time()),
            ]);

            Log::info('OLD-NYTR(SUCCESS):'.request()->input('money', ''));

            DB::commit();

            return response()->json([
                'msg'   => '成功',
                'data'  => [],
                'code'  => 1,
            ]);
        }catch (\Exception $e){
            DB::rollBack();

            Log::info('OLD-NYTR:'.$e->getMessage()." ".$e->getFile()." ".$e->getCode());

            return response()->json([
                'msg'   => '失败',
                'data'  => [],
                'code'  => 0,
            ]);
        }
    }

    /**
     * 签名
     * @param $data
     * @return string
     */
    private function wxSign($data)
    {
        ksort($data);
        $str = '';
        foreach ($data as $key => $val) {
            if ($val && $key != 'token') {
                if ($str != '') $str .= '&';
                $str .= "{$key}={$val}";
            }
        }
        $str .= '&key=' . $this->sing_key;
        $sign = strtoupper(md5($str));
        return $sign;
    }

}