package zoho

import (
	"crm-api/api"
	"crm-api/pkg/lfshook"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"

	"github.com/gin-gonic/gin"
	"gopkg.in/ini.v1"
)

// @tags PBX-zoho
// @Summary 获取zoho数据中心列表
// @Description 获取zoho数据中心列表
// @Security oauth-serverinfo
// @Accept  json
// @Produce  json
// @Router /api/zoho/oauth-serverinfo [get]
func getOauthServerinfo(ctx *gin.Context) {
	fmt.Printf("getOauthServerinfo ............\n")

	// var ZohoOauthServerUrl = "https://accounts.zoho.com/oauth/serverinfo"
	// data := httpRequest(ctx, "GET", ZohoOauthServerUrl)
	// 获取配置文件信息
	confPath := "/etc/asterisk/crm_api.conf"
	cfg, err := ini.Load(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		return
	}
	ZohoOauthServerUrl := cfg.Section("general").Key("zohoAuthUrl").String()
	if ZohoOauthServerUrl == "" {
		lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoAuthUrl")
		return
	}
	getURL := fmt.Sprintf("%s/oauth/serverinfo", ZohoOauthServerUrl)
	fmt.Printf("getURL = %s\n", getURL)
	data := httpRequest(ctx, "GET", getURL)
	/* =====================================================================================
	// 创建HTTP客户端
	client := &http.Client{}

	// 创建请求
	req, err := http.NewRequest("GET", ZohoOauthServerUrl, nil)
	if err != nil {
		fmt.Println("创建请求时发生错误:", err)
		return
	}

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("发送请求时发生错误:", err)
		return
	}
	defer resp.Body.Close()

	// 读取请求后的响应
	data, err := ioutil.ReadAll(resp.Body)
	// if err != nil {
	// 	fmt.Println("读取请求后的响应时发生错误:", err)
	// 	return
	// }
	if err != nil {
		// 读取数据错误
		lfshook.NewLogger().Warn("ioutil ReadAll failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}
	lfshook.NewLogger().Infof("data %+v", string(data))
	// * ===================================================================================== */
	infoData := OauthServerInfoResp{}
	err = json.Unmarshal([]byte(data), &infoData)
	if err != nil {
		// 转换数据错误
		lfshook.NewLogger().Warn("json unmarshal failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 打印请求后的响应
	fmt.Printf("data = %+v\n", string(data))
	// api.Success(ctx, string(data))
	api.Success(ctx, infoData)

}

// @tags PBX-zoho
// @Summary 获取device_code
// @Description 获取device_code
// @Security device_code
// @Accept  json
// @Produce  json
// @Router /api/zoho/device-code [post]
func getDeviceCode(ctx *gin.Context) {
	fmt.Printf("getDeviceCode ............\n")

	// 获取配置文件信息
	confPath := "/etc/asterisk/crm_api.conf"
	cfg, err := ini.Load(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		return
	}
	ZohoOauthUrl := cfg.Section("general").Key("zohoAuthUrl").String()
	ZohoClientId := cfg.Section("general").Key("zohoClientId").String()
	if ZohoOauthUrl == "" || ZohoClientId == "" {
		lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoAuthUrl or zohoClientId")
		return
	}

	// 创建请求
	// https://accounts.zoho.com/oauth/v3/device/code?scope=PhoneBridge.call.log,PhoneBridge.zohoone.search&client_id=1004.LWJCJZD5O9DB6SZLL5YJEWHT7LH0BV
	// &grant_type=device_request&access_type=offline
	getURL := fmt.Sprintf("%s/oauth/v3/device/code?scope=PhoneBridge.call.log,PhoneBridge.zohoone.search&client_id=%s&grant_type=device_request&access_type=offline", ZohoOauthUrl, ZohoClientId)
	fmt.Printf("getURL = %s\n", getURL)

	data := httpRequest(ctx, "POST", getURL)
	/* =====================================================================================
	req, err := http.NewRequest("POST", getURL, nil)
	if err != nil {
		fmt.Println("创建请求时发生错误:", err)
		return
	}

	// 创建HTTP客户端
	client := &http.Client{}

	// req.Header.Set("Authorization", "Bearer "+accessToken)  // 获取token时不需要

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("发送请求时发生错误:", err)
		return
	}
	defer resp.Body.Close()

	// 读取请求后的响应
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// 读取数据错误
		lfshook.NewLogger().Warn("ioutil ReadAll failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}
	lfshook.NewLogger().Infof("data %+v", string(data))
	// * ===================================================================================== */
	userCodeData := UserCodeResp{}
	err = json.Unmarshal([]byte(data), &userCodeData)
	if err != nil {
		// 转换数据错误
		lfshook.NewLogger().Warn("json unmarshal failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 将获取的 device_code 写入文件 crm_api.conf
	cfg.Section("general").Key("zohoCode").SetValue(userCodeData.DeviceCode)
	err = cfg.SaveTo(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 打印请求后的响应
	fmt.Printf("data = %+v\n", string(data))
	// api.Success(ctx, string(data))
	api.Success(ctx, userCodeData)
}

// @tags PBX-zoho
// @Summary 获取token
// @Description 获取token
// @Security ZohoToken
// @Accept  json
// @Produce  json
// @Router /api/zoho/gettoken [post]
func getToken(ctx *gin.Context) {
	fmt.Printf("getToken ............\n")

	// 获取配置文件信息
	confPath := "/etc/asterisk/crm_api.conf"
	cfg, err := ini.Load(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		return
	}
	ZohoAuthUrl := cfg.Section("general").Key("zohoAuthUrl").String()
	ZohoCode := cfg.Section("general").Key("zohoCode").String()
	ZohoClientId := cfg.Section("general").Key("zohoClientId").String()
	ZohoClientSecret := cfg.Section("general").Key("zohoClientSecret").String()
	if ZohoAuthUrl == "" || ZohoCode == "" || ZohoClientId == "" || ZohoClientSecret == "" {
		lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoAuthUrl or zohoCode or zohoClientId or zohoClientSecret")
		return
	}

	// 创建请求
	// https://accounts.zoho.com/oauth/v3/device/token?code=1004.d4c145db9ec33e64f955290f0905ff1e.eebc39b33f228c3bee806d6f8200c50f
	// &client_id=1004.LWJCJZD5O9DB6SZLL5YJEWHT7LH0BV&client_secret=fc3aef43dc58af8a49d3ed597710924200b03f74d0&grant_type=device_token
	getURL := fmt.Sprintf("%s/oauth/v3/device/token?code=%s&client_id=%s&client_secret=%s&grant_type=device_token", ZohoAuthUrl, ZohoCode, ZohoClientId, ZohoClientSecret)
	fmt.Printf("getURL = %s\n", getURL)
	data := httpRequest(ctx, "POST", getURL)
	/* =====================================================================================
	req, err := http.NewRequest("POST", getURL, nil)
	if err != nil {
		fmt.Println("创建请求时发生错误:", err)
		return
	}

	// 创建HTTP客户端
	client := &http.Client{}

	// req.Header.Set("Authorization", "Bearer "+accessToken)  // 获取token时不需要

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("发送请求时发生错误:", err)
		return
	}
	defer resp.Body.Close()

	// 读取请求后的响应
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// 读取数据错误
		lfshook.NewLogger().Warn("ioutil ReadAll failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}
	lfshook.NewLogger().Infof("data %+v", string(data))
	// * ===================================================================================== */
	tokenData := TokenResp{}
	err = json.Unmarshal([]byte(data), &tokenData)
	if err != nil {
		// 转换数据错误
		lfshook.NewLogger().Warn("json unmarshal failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 将获取的 refresh_token access_token 写入文件 crm_api.conf
	cfg.Section("general").Key("zohoRefreshToken").SetValue(tokenData.RefreshToken)
	cfg.Section("general").Key("zohoAccessToken").SetValue(tokenData.AccessToken)
	err = cfg.SaveTo(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 打印请求后的响应
	fmt.Printf("data = %+v\n", string(data))
	// api.Success(ctx, string(data))
	api.Success(ctx, tokenData)

}

// @tags PBX-zoho
// @Summary 刷新token
// @Description 刷新token
// @Security ZohoToken
// @Accept  json
// @Produce  json
// @Router /api/zoho/refresh-token [post]
func refreshToken(ctx *gin.Context) {
	fmt.Printf("refreshToken ............\n")

	// 获取配置文件信息
	// confPath := "/etc/asterisk/vtiger_api.conf"
	confPath := "/etc/asterisk/crm_api.conf"
	cfg, err := ini.Load(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		return
	}
	ZohoAuthUrl := cfg.Section("general").Key("zohoAuthUrl").String()
	ZohoRefreshToken := cfg.Section("general").Key("zohoRefreshToken").String()
	ZohoClientId := cfg.Section("general").Key("zohoClientId").String()
	ZohoClientSecret := cfg.Section("general").Key("zohoClientSecret").String()
	if ZohoAuthUrl == "" || ZohoRefreshToken == "" || ZohoClientId == "" || ZohoClientSecret == "" {
		lfshook.NewLogger().Error("/etc/asterisk/crm_api.conf not set zohoAuthUrl or zohoRefreshToken or zohoClientId or zohoClientSecret")
		return
	}

	// 创建请求
	// https://accounts.zoho.com/oauth/v2/token?refresh_token=1004.86c8c0e3db7bfe9133598825bef28eb9.17a82a3bf3e675c504f478c1b0b5c456
	// &client_id=1004.LWJCJZD5O9DB6SZLL5YJEWHT7LH0BV&client_secret=fc3aef43dc58af8a49d3ed597710924200b03f74d0&grant_type=refresh_token
	getURL := fmt.Sprintf("%s/oauth/v2/token?refresh_token=%s&client_id=%s&client_secret=%s&grant_type=refresh_token", ZohoAuthUrl, ZohoRefreshToken, ZohoClientId, ZohoClientSecret)
	fmt.Printf("getURL = %s\n", getURL)
	data := httpRequest(ctx, "POST", getURL)
	/* =====================================================================================
	req, err := http.NewRequest("POST", getURL, nil)
	if err != nil {
		fmt.Println("创建请求时发生错误:", err)
		return
	}

	// 创建HTTP客户端
	client := &http.Client{}

	// req.Header.Set("Authorization", "Bearer "+accessToken) // 刷新token时不需要

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("发送请求时发生错误:", err)
		return
	}
	defer resp.Body.Close()

	// 读取请求后的响应
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// 读取数据错误
		lfshook.NewLogger().Warn("ioutil ReadAll failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}
	lfshook.NewLogger().Infof("data %+v", string(data))
	// * ===================================================================================== */
	refreshTokenData := RefreshTokenResp{}
	err = json.Unmarshal([]byte(data), &refreshTokenData)
	if err != nil {
		// 转换数据错误
		lfshook.NewLogger().Warn("json unmarshal failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 将获取的 access_token 写入文件 crm_api.conf
	cfg.Section("general").Key("zohoAccessToken").SetValue(refreshTokenData.AccessToken)
	err = cfg.SaveTo(confPath)
	if err != nil {
		lfshook.NewLogger().Error(err)
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return
	}

	// 打印请求后的响应
	fmt.Printf("data = %+v\n", string(data))
	// api.Success(ctx, string(data))
	api.Success(ctx, refreshTokenData)

}

// HTTP请求
func httpRequest(ctx *gin.Context, method string, url string) []byte {
	fmt.Printf("httpRequest ............\n")

	// 创建HTTP客户端
	client := &http.Client{}

	// 创建请求
	// req, err := http.NewRequest("POST", getURL, nil)
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		fmt.Println("创建请求时发生错误:", err)
		return nil
	}

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("发送请求时发生错误:", err)
		return nil
	}
	defer resp.Body.Close()

	// 读取请求后的响应
	data, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		// 读取数据错误
		lfshook.NewLogger().Warn("ioutil ReadAll failed :", err.Error())
		api.Error(ctx, http.StatusInternalServerError, err.Error())
		return nil
	}
	lfshook.NewLogger().Infof("data %+v", string(data))

	// 打印请求后的响应
	fmt.Printf("data = %+v\n", string(data))
	return data
}
