package pveApi

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego"
	hashrateCommon "hashrateNode/common"
	"hashrateNode/log"
	"hashrateNode/models"
	"io/ioutil"
	"net/http"
	"net/url"
)

var pveTicketApi, pveNodesPrefixApi string
var client *http.Client
var hostName string

func init() {
	ip := beego.AppConfig.String("pve::ip")
	port := beego.AppConfig.String("pve::port")
	path := beego.AppConfig.String("pve::ticket_api")
	hostName = beego.AppConfig.String("pve::host_name")
	url := "https://" + ip + ":" + port
	pveNodesPrefixApi = url + beego.AppConfig.String("pve::nodes_api") + fmt.Sprintf("/%s/qemu", hostName)
	pveTicketApi = url + path
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, // 忽略 SSL 证书错误
	}
	client = &http.Client{Transport: tr}
}

// GetCreateVmTicket 获取调用api的ticket
func GetCreateVmTicket() (*models.HeaderInfo, error) {
	data := url.Values{}
	data.Set("username", beego.AppConfig.String("pve::user"))
	data.Set("password", beego.AppConfig.String("pve::pass"))
	isSuccess, _, result, err := sendPostForm(pveTicketApi, data, nil)
	if err != nil || !isSuccess {
		return nil, err
	}
	ticket := new(models.HeaderInfo)
	dataMarshal, err := json.Marshal(result)
	if err != nil {
		log.Error("GetCreateVmTicket json marshal error:", err)
		return nil, err
	}
	err = json.Unmarshal(dataMarshal, ticket)
	if err != nil {
		log.Error("GetCreateVmTicket json Unmarshal error:", err)
		return nil, err
	}
	ticket.Ticket = beego.AppConfig.String("pve::access_prefix") + ticket.Ticket
	return ticket, nil
}

func StartVm(vm *models.VM) (interface{}, error) {
	uriSuffix := fmt.Sprintf("/%s/status/start", vm.NewId)
	uri := pveNodesPrefixApi + uriSuffix
	data := url.Values{}
	data.Set("node", hostName)
	data.Set("vmid", vm.NewId)
	isSuccess, _, result, err := sendPostForm(uri, data, vm.HeaderInfo)
	if err != nil || !isSuccess {
		return nil, err
	}
	return result, nil
}

// CreateVm 通过模版克隆对应的vm
func CreateVm(vm *models.VM) (interface{}, error) {
	uriSuffix := fmt.Sprintf("/%s/clone", vm.VmId)
	uri := pveNodesPrefixApi + uriSuffix
	data := url.Values{}
	data.Set("node", hostName)
	data.Set("vmid", vm.VmId)
	data.Set("newid", vm.NewId)
	data.Set("name", vm.Name)
	isSuccess, _, result, err := sendPostForm(uri, data, vm.HeaderInfo)
	if err != nil || !isSuccess {
		return nil, err
	}
	return result, nil
}

// SetVmConfig 设置vm的配置信息
func SetVmConfig(vm *models.VM) (interface{}, error) {
	uriSuffix := fmt.Sprintf("/%s/config", vm.NewId)
	uri := pveNodesPrefixApi + uriSuffix
	data := url.Values{}
	data.Set("node", hostName)
	data.Set("vmid", vm.NewId)
	data.Set("cores", vm.VmCfg.Cores.String())
	data.Set("sockets", vm.VmCfg.Sockets.String())
	data.Set("memory", vm.VmCfg.Memory.String())
	isSuccess, _, result, err := sendPostForm(uri, data, vm.HeaderInfo)
	if err != nil || !isSuccess {
		return nil, err
	}
	return result, nil
}

func GetVmNetWork(vm *models.VM) ([]*models.NetworkInfo, error) {
	uriSuffix := fmt.Sprintf("/%s/agent/network-get-interfaces", vm.NewId)
	uri := pveNodesPrefixApi + uriSuffix
	isSuccess, _, resp, err := sendGetRequest(uri, vm.HeaderInfo)
	if err != nil || !isSuccess {
		return nil, err
	}
	networkResult := &models.NetWorkResult{}
	respMarshal, err := json.Marshal(resp)
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(respMarshal, networkResult); err != nil {
		fmt.Println("JSON解析错误:", err)
		return nil, err
	}
	return networkResult.Result, nil
}

// VmStatus 获取虚拟机的状态  stopped｜running
func VmStatus(vm *models.VM) (*models.VmStatusRep, error) {
	uriSuffix := fmt.Sprintf("/%s/status/current", vm.NewId)
	uri := pveNodesPrefixApi + uriSuffix
	isSuccess, _, resp, err := sendGetRequest(uri, vm.HeaderInfo)
	if err != nil || !isSuccess {
		return nil, err
	}
	vmStatus := &models.VmStatusRep{}
	respMarshal, err := json.Marshal(resp)
	if err != nil {
		return nil, err
	}
	if err := json.Unmarshal(respMarshal, vmStatus); err != nil {
		fmt.Println("JSON解析错误:", err)
		return nil, err
	}
	return vmStatus, nil
}

func GetQemuList(headerInfo *models.HeaderInfo) ([]*models.QemuList, error) {
	isSuccess, responseArr, _, err := sendGetRequest(pveNodesPrefixApi, headerInfo)
	if err != nil || !isSuccess {
		return nil, err
	}
	qemuList := make([]*models.QemuList, len(responseArr))
	for i, resp := range responseArr {
		qemu := &models.QemuList{}
		respMarshal, err := json.Marshal(resp)
		if err != nil {
			return nil, err
		}
		if err := json.Unmarshal(respMarshal, qemu); err != nil {
			log.Error("JSON解析错误:", err)
			return nil, err
		}
		qemuList[i] = qemu
	}
	return qemuList, nil
}

func SetVmLoginUser(vm *models.VM) (interface{}, error) {
	uriSuffix := fmt.Sprintf("/%s/agent/set-user-password", vm.NewId)
	uri := pveNodesPrefixApi + uriSuffix
	data := url.Values{}
	data.Set("node", hostName)
	data.Set("vmid", vm.NewId)
	data.Set("password", vm.VmCfg.Cores.String())
	data.Set("username", vm.VmCfg.Sockets.String())
	isSuccess, _, result, err := sendPostForm(uri, data, vm.HeaderInfo)
	if err != nil || !isSuccess {
		return nil, err
	}
	return result, nil
}

// sendPostForm 发送postForm请求
func sendPostForm(uri string, data url.Values, headInfo *models.HeaderInfo) (bool, []interface{}, map[string]interface{}, error) {
	request, err := http.NewRequest("POST", uri, bytes.NewBufferString(data.Encode()))
	if err != nil {
		return false, nil, nil, err
	}
	if headInfo != nil {
		request.Header.Set("Cookie", headInfo.Ticket)
		request.Header.Set("CSRFPreventionToken", headInfo.CSRFPreventionToken)
	}
	request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	isSuccess, responseArr, response, err := handlerResponse(request)
	if err != nil {
		return false, nil, nil, err
	}
	log.Infof("request uri:%s , request method:%s,request result:%s", uri, "post", response)
	return isSuccess, responseArr, response, nil
}

// sendGetRequest 发送Get请求
func sendGetRequest(uri string, headInfo *models.HeaderInfo) (bool, []interface{}, map[string]interface{}, error) {
	request, err := http.NewRequest("GET", uri, nil)
	if headInfo != nil {
		request.Header.Set("Cookie", headInfo.Ticket)
		request.Header.Set("CSRFPreventionToken", headInfo.CSRFPreventionToken)
	}
	isSuccess, responseArr, response, err := handlerResponse(request)
	if err != nil {
		return false, nil, nil, err
	}
	log.Infof("request uri:%s,request method:%s,request result:%s", uri, "get", response)
	return isSuccess, responseArr, response, nil
}

// handlerResponse 处理相应数据
func handlerResponse(request *http.Request) (bool, []interface{}, map[string]interface{}, error) {
	resp, err := client.Do(request)
	if err != nil {
		log.Errorf("Send get request error: %s , uri: %s", err.Error(), request.URL.String())
		return false, nil, nil, err
	}
	defer resp.Body.Close()
	if resp.StatusCode != hashrateCommon.SuccessCode {
		log.Error("Send post request failed:", resp.Status)
		return false, nil, nil, nil
	}
	readAllResult, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("读取响应内容错误:", err)
		return false, nil, nil, err
	}
	result1 := &models.ResponseStr{}
	err = json.Unmarshal(readAllResult, result1)
	if err != nil {
		log.Warning("json unmarshal responseStr error:", err)
	}
	if result1.Data != "" {
		return true, nil, nil, nil
	}

	result2 := &models.ResponseArr{}
	err = json.Unmarshal(readAllResult, result2)
	if err != nil {
		log.Warning("json unmarshal responseStr error:", err)
	}
	if len(result2.Data) > 0 {
		return true, result2.Data, nil, nil
	}

	result := &models.Response{}
	err = json.Unmarshal(readAllResult, result)
	if err != nil {
		log.Error("json Unmarshal error:", err)
		return false, nil, nil, err
	}
	return true, nil, result.Data, nil
}
