import 'dart:convert';
import 'dart:math';
import 'dart:typed_data';
import 'package:bs58check/bs58check.dart';
// import 'package:dartsv/dartsv.dart' as dartsv;
import 'package:flutter_bitcoin/flutter_bitcoin.dart';
import 'package:flutter_wallet/tools/YSNetWork.dart';
import 'package:flutter_wallet/tools/YSTools.dart';
import 'package:http/http.dart' as http;
import 'package:web3dart/web3dart.dart' as web3;

import 'YSAes.dart';

const baseUrl = 'https://btcscan.org/api/';

class YSBtc{

  static Future<String> getBalance(String address) async{
    try{
      final utxosRes = await http.get(Uri.parse('https://blockchain.info/unspent?active=$address'));
      double balance = 0.00;
      List utxos = jsonDecode(utxosRes.body)['unspent_outputs']??[];
      for (var element in utxos) {
        balance += element['value']??0.00;
      }
      // final response = await http.get(Uri.parse('https://blockchain.info/q/addressbalance/$address'));
      balance = balance / 100000000;
      LogUtil.d('余额: $balance BTC');
      return '$balance';
    }catch(error){
      LogUtil.d('余额: https://blockchain.info/q/addressbalance/$address BTC');
      return '0.0';
    }
  }

  static Future<String> transferData({required String from,required String to,required String private,required String amount}) async{
    LogUtil.d(YSData().rpc);
    LogUtil.d('transferData======$from====$to====$private====$amount');
    try{
      // transferContractData3(from: from, to: to, private: private, amount: amount);
      // return '';
      // transferData2(from: from, to: to, private: private, amount: amount);
      // return '';
      // 创建一个网络对象
      final network = bitcoin;
      final utxosRes = await http.get(Uri.parse('https://blockchain.info/unspent?active=$from'));
      List utxos = jsonDecode(utxosRes.body)['unspent_outputs']??[];
      if(utxos.isNotEmpty){
        LogUtil.d('transferData======$utxos');
        Map utxo = utxos.first;
        int total = utxo['value'];
        final txb = TransactionBuilder(network: network);
        // int number = (double.parse(amount) * pow(10, 8))~/1;
        // 添加输入（来自哪个地址的比特币）
        txb.addInput(utxo['tx_hash'], 0);
        // LogUtil.d('transferData======$number');
        // 添加输出（要发送到哪个地址）
        Uint8List toList = base58.decode(to);
        // 计算交易费
        const byteCount = 180 + (2 * 34) + 10;
        const feeSatoshis = byteCount * 15;
        // //console.log(feeSatoshis)
        // // 添加输出
        int sendSatoshis = total - feeSatoshis;
        txb.addOutput(toList, sendSatoshis);
        // 创建一个私钥对象
        final keyPair = ECPair.fromWIF(private, network: network);
        // return '';
        // 对交易进行签名
        txb.sign(vin: 0, keyPair: keyPair);
        // 构建交易
        final tx = txb.build();
        // 打印交易的十六进制表示
        LogUtil.d('交易数据: ${tx.ins} ====== ${tx.outs}');
        final rawTx = tx.toHex();
        final url = YSData().rpc;
        final headers = {'Content-Type': 'application/json'};
        final body = jsonEncode({
          'jsonrpc': '1.0',
          'id': 'curltest',
          'method': 'sendrawtransaction',
          'params': [rawTx]
        });
        final response = await http.post(Uri.parse(url), headers: headers, body: body);
        final data = jsonDecode(response.body);
        LogUtil.d('交易结果: $data');
        if(data['result']!=null){
          return data['result'];
        }else{
          return '';
        }
      }else{
        return '';
      }
    }catch(error){
      LogUtil.d('transferData======$error');
      return '';
    }
  }
  static Future<String> transferData3({required String from,required String to,required String private,required String amount}) async{
    LogUtil.d('transferData3======$from====$to====$private====$amount');
    Map request = {};
    String privateS = YSAes.aesEncode3('${private}_${DateTime.now().microsecond}');
    request['prikey'] = privateS;
    request['to'] = to;
    int number = (double.parse(amount) * pow(10, 8))~/1;
    request['value'] = number;
    Map dict = await YSNetWork.httpNetwork(api: 'bithash', request: request);
    if(dict.isNotEmpty){
      Map data = dict['data']??'';
      final pushTxRes = await http.post(Uri.parse('https://blockchain.info/pushtx'), body: {'tx': data['hex']});
      LogUtil.d('Transaction ID: https://blockchain.info/pushtx ======= ${pushTxRes.body}');
      // Map body = jsonDecode(pushTxRes.body);
      if(pushTxRes.body=='Transaction Submitted'){
        return data['hash']??'';
      }else{
        return '';
      }
    }
    return '';
  }
  static Future<String> transferContractData3({required String from,required String to,required String private,required String amount}) async{
    LogUtil.d('transferContractData3======$from====$to====$private====$amount');
    Map request = {};
    String privateS = YSAes.aesEncode3('${private}_${DateTime.now().microsecond}');
    request['prikey'] = privateS;
    request['to'] = to;
    int number = (double.parse(amount) * pow(10, 8))~/1;
    request['value'] = number;
    Map dict = await YSNetWork.httpNetwork(api: 'bithash', request: request);
    if(dict.isNotEmpty){
      Map data = dict['data']??'';
      final pushTxRes = await http.post(Uri.parse('ttps://api.omniwallet.org/v1/transaction/pushtx/'), body: {'tx': data['hex']});
      LogUtil.d('Transaction ID: ttps://api.omniwallet.org/v1/transaction/pushtx/ ======= ${pushTxRes.body}');
      // Map body = jsonDecode(pushTxRes.body);
      if(pushTxRes.body=='Transaction Submitted'){
        return data['hash']??'';
      }else{
        return '';
      }
    }
    return '';
    // final httpClient = http.Client();
    // final ethClient = web3.Web3Client('https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID', httpClient);
    // final tokenAddress = web3.EthereumAddress.fromHex('TOKEN_CONTRACT_ADDRESS');
    // final tokenAbi = jsonDecode('TOKEN_CONTRACT_ABI');
    // final tokenContract = web3.DeployedContract(web3.ContractAbi.fromJson(tokenAbi, 'Token'), tokenAddress);
    // final transferFunction = tokenContract.function('transfer');
    // final transferArgs = [web3.EthereumAddress.fromHex('RECIPIENT_ADDRESS'), BigInt.from(100)]; // 将100个代币转账给RECIPIENT_ADDRESS
    // final transferTx = await ethClient.sendTransaction(
    //   credentials,
    //   web3.Transaction.callContract(
    //     contract: tokenContract,
    //     function: transferFunction,
    //     parameters: transferArgs,
    //   ),
    // );
  }

  static transferData2({required String from,required String to,required String private,required String amount}) async {
    final config = {
      'privateKey': private,
      'network': 'bitcoin', // 更改为主网络
      'toAddress': to,
      'fromAddress': from,
      'satoshisPerByte': double.parse(amount),
      'fee': 1000,
    };

    final network = config['network'] == 'testnet' ? testnet : bitcoin;
    final keyPair = ECPair.fromWIF('${config['privateKey']}', network: network);
    // final psbt = Psbt(network: network);
    final txb = TransactionBuilder(network: network);

    // 获取UTXO
    final utxosRes = await http.get(Uri.parse('https://blockchain.info/unspent?active=${config['fromAddress']}'));
    final utxos = jsonDecode(utxosRes.body)['unspent_outputs'];//
    LogUtil.d('transferData======$utxos');
    // for (var i = 0; i < utxos.length; i++) {
    //   Map value = txb.sign(keyPair: keyPair, vin: i);
    //   LogUtil.d('transferData======$value');
    // }
    // return;
    int totalSatoshis = 0;
    for (var utxo in utxos) {
      // final txRes = await http.get(Uri.parse('https://blockchain.info/rawtx/${utxo['tx_hash_big_endian']}?format=hex'));
      // final nonWitnessUtxo = HEX.decode(txRes.body);
      totalSatoshis += txb.addInput(utxo['tx_hash'], utxo['tx_output_n']);
      // txb.addInput(txHash, vout)
      // psbt.addInput({
      //   'hash': utxo['tx_hash_big_endian'],
      //   'index': utxo['tx_output_n'],
      //   'nonWitnessUtxo': nonWitnessUtxo,
      // });
      //
      // totalSatoshis += int.parse('${utxo['value']}');
    }
    //
    // 计算交易费
    final byteCount = (utxos.length * 180) + (2 * 34) + 10;
    final feeSatoshis = byteCount * config['satoshisPerByte'];

    // 添加输出
    final sendSatoshis = totalSatoshis - feeSatoshis;
    txb.addOutput(config['toAddress'], sendSatoshis~/1);
    // psbt.addOutput({
    //   'address': config['toAddress'],
    //   'value': sendSatoshis,
    // });

    // 签名所有的输入
    for (var i = 0; i < utxos.length; i++) {
      txb.sign(vin: i, keyPair: keyPair);
      // psbt.signInput(i, keyPair);
    }

    // 完成交易并将其转换为十六进制
    // psbt.finalizeAllInputs();
    // final txHex = psbt.extractTransaction().toHex();
    //
    // // 广播交易
    // final pushTxRes = await http.post(Uri.parse('https://blockchain.info/pushtx'), body: {'tx': txHex});
    //
    // LogUtil.d('Transaction ID: ${pushTxRes.body}');
  }


}