package utility

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gctx"
	"io/ioutil"
	"link_homework/internal/consts"
	"link_homework/internal/model/dto"
	"net/http"
	"strconv"
	"strings"
)

// 获取 URL
func getUrl(key, hashKey string) *dto.Result {
	ctx := gctx.New()

	// 1. 从 Redis 获取 URL
	redisUrl, err := g.Redis().Do(ctx, "HGET", key, hashKey)
	if err == nil && redisUrl.String() != "" {
		g.Log().Infof(ctx, "从 Redis 获取到 URL: %s", redisUrl.String())
		return dto.SuccessWithData(redisUrl.String())
	}

	// 2. 如果 Redis 中没有,查询数据库
	urlResult := selectBaseUrl(hashKey)
	if urlResult.Code != 200 {
		return urlResult // 数据库查询失败,返回错误
	}
	url := urlResult.Data.(string)

	// 3. 将 URL 存入 Redis
	if _, err = g.Redis().Do(ctx, "HSET", key, hashKey, url); err != nil {
		g.Log().Warningf(ctx, "将数据存入 Redis 失败: %v", err)
	}

	g.Log().Infof(ctx, "将 URL 存入 Redis: %s", url)
	return dto.SuccessWithData(url)
}

// 查询数据库中的 URL
func selectBaseUrl(hashKey string) *dto.Result {
	ctx := gctx.New()

	// 查询数据库
	value, err := g.DB("cms").Model("env").Where("`key` = ?", hashKey).Value("value")
	if err != nil {
		//g.Log().Errorf(ctx, "数据库查询失败, 错误: %v, key: %s", err, hashKey)
		return dto.Error("数据库查询失败")
	}

	if value.IsNil() || value.String() == "" {
		g.Log().Errorf(ctx, "未找到对应数据, key: %s", hashKey)
		return dto.Error("未找到对应数据")
	}

	return dto.SuccessWithData(value.String())
}

// 获取 jwcode
// 获取 jwcode
func GetJwcodeJSON(token string) (int, error) { // 返回类型为 int
	//ctx := gctx.New()

	// 1. 获取基础 URL
	urlResult := getUrl(consts.URL_KEY, consts.URL_HASH_KEY)
	if urlResult.Code != 200 {
		//g.Log().Errorf(ctx, "获取基础 URL 失败: %s", urlResult.Message)
		return 0, errors.New("获取基础 URL 失败: " + urlResult.Message)
	}
	baseUrl := urlResult.Data.(string)
	//g.Log().Debugf(ctx, "成功获取基础 URL: %s", baseUrl)

	// 2. 拼接完整的 URL
	url := baseUrl + "/api/v2/member/info"
	requestBody := strings.NewReader(`{"token":"` + token + `"}`)

	// 3. 创建 HTTP 请求
	req, err := http.NewRequest("POST", url, requestBody)
	if err != nil {
		//g.Log().Errorf(ctx, "HTTP 请求创建失败: %v", err)
		return 0, fmt.Errorf("HTTP 请求创建失败: %w", err)
	}
	req.Header.Set("Content-Type", "application/json")

	// 4. 发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		//g.Log().Errorf(ctx, "HTTP 请求失败: %v", err)
		return 0, fmt.Errorf("HTTP 请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 5. 检查 HTTP 状态码
	if resp.StatusCode != http.StatusOK {
		//g.Log().Errorf(ctx, "HTTP 状态码错误: %d", resp.StatusCode)
		return 0, fmt.Errorf("HTTP 状态码错误: %d", resp.StatusCode)
	}

	// 6. 读取并解析响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		//g.Log().Errorf(ctx, "读取响应失败: %v", err)
		return 0, fmt.Errorf("读取响应失败: %w", err)
	}
	//g.Log().Debugf(ctx, "响应体内容: %s", string(body))

	// 7. 解析 JSON 数据
	var jsonResponse map[string]interface{}
	if err = json.Unmarshal(body, &jsonResponse); err != nil {
		//g.Log().Errorf(ctx, "解析 JSON 失败: %v", err)
		return 0, fmt.Errorf("解析 JSON 失败: %w", err)
	}
	//g.Log().Debugf(ctx, "解析后的 JSON: %+v", jsonResponse)

	// 8. 提取 data 节点
	data, ok := jsonResponse["data"].(map[string]interface{})
	if !ok {
		//g.Log().Errorf(ctx, "响应体中没有 data 节点,完整响应: %+v", jsonResponse)
		return 0, errors.New("响应体中没有 data 节点")
	}

	// 9. 提取 jwcode 并转换为整数
	jwcode, ok := data["jwcode"].(string) // 首先尝试解析为字符串
	if ok {
		jwcodeInt, err := strconv.Atoi(jwcode) // 将字符串转换为整数
		if err != nil {
			//g.Log().Errorf(ctx, "解析 jwcode 字段失败: %v", err)
			return 0, fmt.Errorf("解析 jwcode 字段失败: %w", err)
		}
		//g.Log().Infof(ctx, "成功获取 jwcode: %d", jwcodeInt)
		return jwcodeInt, nil
	}

	// 如果 jwcode 不是字符串,记录错误日志
	//g.Log().Errorf(ctx, "data 节点中没有 jwcode 字段,或字段格式不正确,data: %+v", data)
	return 0, errors.New("响应体中没有有效的 jwcode 字段")
}