package http

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
)

type HttpClient struct {
	host   string
	port   string
	apiKey string
}

func NewHttpClient(host, port, apiKey string) *HttpClient {
	return &HttpClient{
		host:   host,
		port:   port,
		apiKey: apiKey,
	}
}

func (client *HttpClient) parseJson(resp *http.Response, data []byte) (map[string]interface{}, error) {
	// 尝试解析为 JSON 对象
	var dataJson map[string]interface{}
	if err := json.Unmarshal(data, &dataJson); err != nil {
		// 如果解析为 JSON 对象失败，检查是否是布尔值
		var booleanValue bool
		if err := json.Unmarshal(data, &booleanValue); err == nil {
			// 如果是布尔值，包装成一个 map 返回
			return map[string]interface{}{"success": booleanValue}, nil
		}
		// 如果既不是 JSON 对象也不是布尔值，返回错误
		return nil, fmt.Errorf("invalid JSON response: %s", string(data))
	}

	// 检查 HTTP 状态码
	if resp.StatusCode != http.StatusOK {
		errMessage, _ := dataJson["detail"].(string) // 如果没有 "detail"，默认为空字符串
		dataJson["statusCode"] = resp.StatusCode
		dataJson["error"] = errMessage
		return dataJson, fmt.Errorf("HTTP error: %d - %s", resp.StatusCode, errMessage)
	}

	return dataJson, nil
}

func (client *HttpClient) httpRequest(method, path string, headers map[string]string, requestData []byte) (map[string]interface{}, error) {
	var url string
	if client.port == "" {
		url = "http://" + client.host + path
	} else {
		url = fmt.Sprintf("%s://%s:%s%s", "http", client.host, client.port, path)
	}

	req, err := http.NewRequest(method, url, bytes.NewBuffer(requestData))
	if err != nil {
		return nil, err
	}

	for key, value := range headers {
		req.Header.Set(key, value)
	}

	clientResponse, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, err
	}
	defer clientResponse.Body.Close()

	body, err := ioutil.ReadAll(clientResponse.Body)
	if err != nil {
		return nil, err
	}

	return client.parseJson(clientResponse, body)
}

func (client *HttpClient) Get(path string) (map[string]interface{}, error) {
	headers := map[string]string{
		"Accept": "application/json",
	}
	if client.apiKey != "" {
		headers["X-API-KEY"] = client.apiKey
	}
	return client.httpRequest("GET", path, headers, nil)
}

func (client *HttpClient) Post(path string, data interface{}) (map[string]interface{}, error) {
	headers := map[string]string{
		"Content-Type": "application/json",
	}
	if client.apiKey != "" {
		headers["X-API-KEY"] = client.apiKey
	}

	jsonData, err := json.Marshal(data)
	if err != nil {
		return nil, err
	}

	fmt.Println("POST 请求的数据:", string(jsonData))

	response, err := client.httpRequest("POST", path, headers, jsonData)
	if err != nil {
		return nil, err
	}

	fmt.Println("POST 响应的数据:", response)
	return response, nil
}
func (client *HttpClient) WalletStatus(walletName string) (map[string]interface{}, error) {
	path := fmt.Sprintf("/wallets/%s", walletName)
	return client.Get(path)
}

func (client *HttpClient) UnlockWallet(walletName, password, mnemonicPassphrase string) (map[string]interface{}, error) {
	path := fmt.Sprintf("/wallets/%s/unlock", walletName)
	data := map[string]string{"password": password}
	if mnemonicPassphrase != "" {
		data["mnemonicPassphrase"] = mnemonicPassphrase
	}
	return client.Post(path, data)
}

func (client *HttpClient) BuildUnsignedTx(fromPubKey string, destinations []interface{}) (map[string]interface{}, error) {
	path := "/transactions/build"
	data := map[string]interface{}{
		"fromPublicKey": fromPubKey,
		"destinations":  destinations,
	}
	return client.Post(path, data)
}

func (client *HttpClient) SelfClique() (map[string]interface{}, error) {
	path := "/infos/self-clique"
	return client.Get(path)
}

func (client *HttpClient) GetBlockHash(fromGroup uint32, toGroup uint32, height uint32) (string, error) {
	// 构建请求路径
	path := fmt.Sprintf("/blockflow/hashes?fromGroup=%d&toGroup=%d&height=%d", fromGroup, toGroup, height)

	// 调用客户端的 Get 方法
	result, err := client.Get(path)
	if err != nil {
		fmt.Println("获取hash失败：", err)
		return "", err
	}

	// 断言 result 是 map[string]interface{}
	data := result

	// 获取 headers 字段并断言为 []interface{}
	headers, ok := data["headers"].([]interface{})
	if !ok {
		fmt.Println("headers 字段格式不正确")
		return "", errors.New("headers 字段格式不正确")
	}

	// 转换为字符串切片
	var headerStrings []string
	for _, header := range headers {
		if str, ok := header.(string); ok {
			headerStrings = append(headerStrings, str)
		} else {
			fmt.Println("headers 中存在非字符串类型数据")
			return "", errors.New("headers 中存在非字符串类型数据")
		}
	}

	// 如果只需要第一个字符串，返回它
	if len(headerStrings) > 0 {
		return headerStrings[0], nil
	}

	// 如果 headers 是空的，返回空字符串
	return "", nil
}

func (client *HttpClient) CheckBlk(hash string) bool {
	path := fmt.Sprintf("/blockflow/is-block-in-main-chain?blockHash=%s", hash)
	result, err := client.Get(path)
	if err != nil {
		fmt.Println("获取hash失败：", err)
		return false
	}
	// 从返回结果中提取布尔值
	if success, ok := result["success"].(bool); ok {
		return success
	}
	// 如果结果不包含布尔值或格式不对
	fmt.Println("返回的结果格式不正确：", result)
	return false
}

type Block struct {
	ChainFrom    int         `json:"chainFrom"`
	ChainTo      int         `json:"chainTo"`
	DepStateHash string      `json:"depStateHash"`
	Deps         []string    `json:"deps"`
	GhostUncles  interface{} `json:"ghostUncles"`
	Hash         string      `json:"hash"`
	Height       int64       `json:"height"`
	Nonce        string      `json:"nonce"`
	Target       string      `json:"target"`
	Timestamp    float64     `json:"timestamp"`
	Transactions []TxDetail  `json:"transactions"`
	TxsHash      string      `json:"txsHash"`
	Version      int         `json:"version"`
}

type TxDetail struct {
	Unsigned UnsignedTx `json:"unsigned"`
}

type UnsignedTx struct {
	Inputs       []Input       `json:"inputs"`
	FixedOutputs []FixedOutput `json:"fixedOutputs"`
}
type Input struct {
}
type FixedOutput struct {
	Address        string  `json:"address"`
	AttoAlphAmount string  `json:"attoAlphAmount"`
	Hint           float64 `json:"hint"`
	Key            string  `json:"key"`
	LockTime       int64   `json:"lockTime"`
}

func (client *HttpClient) GetBlcokInfo(hash string) Block {
	path := fmt.Sprintf("/blockflow/blocks/%s", hash)
	result, err := client.Get(path)
	if err != nil {
		fmt.Println("获取区块信息失败：", err)
		return Block{}
	} // 将 map[string]interface{} 转换为 JSON 字符串
	jsonData, err := json.Marshal(result)
	if err != nil {
		fmt.Println("转换为 JSON 字符串失败：", err)
		return Block{}
	}

	var blockInfo Block
	err = json.Unmarshal(jsonData, &blockInfo)
	if err != nil {
		fmt.Println("解析失败:", err)
		return Block{}
	}
	return blockInfo
}

// func (client *HttpClient) GetBlockCount(fromGroup uint32, toGroup uint32) (int, error) {

// }

func (client *HttpClient) ChangeActiveAddress(walletName string, address string) (map[string]interface{}, error) {
	path := fmt.Sprintf("/wallets/%s/change-active-address", walletName)
	data := map[string]interface{}{
		"address": address,
	}
	return client.Post(path, data)
}

func (client *HttpClient) SignTx(walletName string, txId string) (map[string]interface{}, error) {
	path := fmt.Sprintf("/wallets/%s/sign", walletName)
	data := map[string]interface{}{
		"data": txId,
	}
	return client.Post(path, data)
}

func (client *HttpClient) GetAddressInfo(walletName string, address string) (map[string]interface{}, error) {
	path := fmt.Sprintf("/wallets/%s/addresses/%s", walletName, address)
	return client.Get(path)
}

func (client *HttpClient) SweepActiveAddress(walletName string, toAddress string) (map[string]interface{}, error) {
	path := fmt.Sprintf("/wallets/%s/sweep-active-address", walletName)
	data := map[string]interface{}{
		"toAddress": toAddress,
	}
	return client.Post(path, data)
}

func (client *HttpClient) CheckAccount(coin string, account string) bool {
	path := "/api/pool/checkAccount"
	data := map[string]interface{}{
		"coin": coin,
		"ma":   account,
	}
	result, err := client.Post(path, data)
	if err != nil {
		fmt.Println("校验挖矿账号失败：", err)
		return false
	}

	// 检查返回值中的 "success" 字段
	success, ok := result["success"].(bool)
	if !ok {
		fmt.Println("响应格式错误或 success 字段不存在:", result)
		return false
	}
	return success
}
