const apiBase = process.env.VUE_APP_API_URL.replace('/api', '');
import { SiweMessage } from './common/SiweMessage';
import { ethers } from 'ethers';
import assert from 'assert'
import { AllChains } from "@/wallet/allchain.ts";
import { Deferred } from '@/utils/promise.util';
// import { CURRENCYS } from "@/configs/configchain";
// import { useMarketplaceStore } from "@/store/marketplace"
// import {priceCalculated} from "@/configs/priceCalculate.js"
import {Buffer} from 'buffer';


// export const cfgChainId = parseInt('97');

// assert(cfgChainId, 'VUE_APP_NET_ID not configured');

// let chainCfg;
// for (const d of AllChains) {
//   if (d.id === cfgChainId) {
//     chainCfg = d;
//     break;
//   }
// }
// assert(chainCfg, 'chain config not found');

// export const currencyMap = CURRENCYS[cfgChainId]
// assert(currencyMap, 'currencys not configured')

// export const currentChainCfg = chainCfg;


const request = async(url, data, method = 'POST') => {
  let headers = {
    'Content-Type': 'application/json',
    'api_version': 2,
    'api_platform': 'marketplace',
    'api_env': process.env.NODE_ENV === 'production' ? 'release' : 'dev'
  };
  return fetch(url, {
    method,
    body: JSON.stringify(data),
    headers
  }).then(res => res.json());
}

const loginWithSignature = async(message, signature) => {
  const url = `${apiBase}/api/bigget/login`;
  const data = {
    channel: 13,
    code: signature,
    message,
    nb: 1
  }
  return request(url, data);
}

export const genRefreshToken = async(refreshToken) => {
  const url = `${apiBase}/wallet/refresh_token`;
  const data = { refreshToken }
  const res = await request(url, data);
  if (res.errcode) {
    throw new Error(res.errmsg);
  }
  return res.data;
}
/**
 * query token->usd price from coingecko
 * @param {*} ids 
 * @returns 
 */
export const queryTokenPriceCg = async(ids) => {
  const idstr = ids.join(',');
  const url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=USD&ids=${idstr}`
  return fetch(url).then(res => res.json());
}

const utf8ToHex = (str) => {
  return '0x' + Buffer.from(str).toString('hex');
}


export const signLogin = async (provider, address) => {
  const nonce = Date.now()+'';
  address = ethers.utils.getAddress(address);
  let chainId = await provider.request({ method: "eth_chainId" });
  chainId = parseInt(chainId);
  const message = new SiweMessage({
    domain: document.location.host,
    address,
    chainId, 
    uri: document.location.origin,
    version: "1",
    statement: "CF MarketPlace",
    nonce,
  });
  const msgSign = message.toMessage();
  const signature = await provider.request({
    "method": "personal_sign",
    "params": [
      utf8ToHex(msgSign),
      address
    ]
  });
  const res = await loginWithSignature(message, signature);
  if (res.errcode) {
    throw new Error(res.errmsg);
  }
  return res.data;
}


export function parseTokenData(token) {
  if (!token) {
    return {};
  }
  let datas = token.split(".");
  if (datas.length < 2) {
    return {};
  }
  try {
    return JSON.parse(window.atob(datas[1]));
  } catch (err) {
    return {};
  }
}

/**
 * check if token expired
 * @param token jwt token string
 * @param fixed fixed seconds
 * @returns 
 */
export function isTokenExpired(fixed, token) {
  if (!token) {
    return true;
  }
  let data = parseTokenData(token);
  if (!data.exp) {
    return true;
  }
  let now = Date.now() / 1000 | 0;
  return data.exp < now - fixed;
}

/**
 * number to hex string
 * @param {number} chainId
 * @return {string}
 */
export function toHexChainId(chainId) {
  return '0x' + chainId.toString(16)
}

export const switchEthereumChain = async (provider, targetChainId) => {
let chainCfg;
for (const d of AllChains) {
  if (d.id === targetChainId) {
    chainCfg = d;
    break;
  }
}
  const hexChainId = toHexChainId(targetChainId)
  const deferred = new Deferred();
  const onChainChange = (chainId) => {
    const chainIdNum = parseInt(chainId)
    console.log('switchEthereumChain: ', chainIdNum)
    provider.removeListener('chainChanged', onChainChange)
    if (chainIdNum !== targetChainId) {
      deferred.reject(new Error('switch chain failed'))
      return
    }
    deferred.resolve(chainIdNum)
  }
  provider.on('chainChanged', onChainChange)
  try {
    await provider.request({
      method: 'wallet_switchEthereumChain',
      params: [{ chainId: hexChainId }]
    })
    console.log('success send switch chain request')
  } catch (e) {
    console.log('error switch chain: ', e)
    if (e.code === 4902 || e.message.indexOf('Unrecognized chain ID') >= 0) {
      console.log(chainCfg)
      try {
        const data = chainCfg
        await provider.request({
          method: 'wallet_addEthereumChain',
          params: [
            {
              chainId: hexChainId,
              chainName: data.name,
              nativeCurrency: {
                name: data.symbol,
                symbol: data.symbol,
                decimals: data.decimals || 18
              },
              blockExplorerUrls: [data.explorerurl],
              rpcUrls: [data.rpc]
            }
          ]
        })
        console.log('success send add chain request')
      } catch (addError) {
        console.error('error add chain: ', addError)
        provider.removeListener('chainChanged', onChainChange)
        deferred.reject(addError)
      }
    } else {
      console.error('error add chain: ', e.message)
      provider.removeListener('chainChanged', onChainChange)
      deferred.reject(e)
    }
  }
  return deferred.promise
}
