package ctx

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"path/filepath"
	"strings"

	"be.ems/lib/core/vo"
	commonConstants "be.ems/src/framework/constants/common"
	tokenConst "be.ems/src/framework/constants/token"
	"github.com/gorilla/mux"
	"golang.org/x/text/language"
)

// Param 地址栏参数{id}
func Param(r *http.Request, key string) string {
	vars := mux.Vars(r)
	v, ok := vars[key]
	if ok {
		return v
	}
	return ""
}

// GetQuery 查询参数
func GetQuery(r *http.Request, key string) string {
	return r.URL.Query().Get(key)
}

// GetHeader 请求头参数
func GetHeader(r *http.Request, key string) string {
	return r.Header.Get(key)
}

// QueryMap 查询参数转换Map
func QueryMap(r *http.Request) map[string]any {
	queryValues := r.URL.Query()
	queryParams := make(map[string]any)
	for key, values := range queryValues {
		queryParams[key] = values[0]
	}
	return queryParams
}

// ShouldBindQuery 查询参数读取json请求结构团体
func ShouldBindQuery(r *http.Request, args any) error {
	queryParams := QueryMap(r)
	body, err := json.Marshal(queryParams)
	if err != nil {
		return err
	}
	return json.Unmarshal(body, args)
}

// 读取json请求结构团体
func ShouldBindJSON(r *http.Request, args any) error {
	body, err := io.ReadAll(io.LimitReader(r.Body, 1<<20)) // 设置较大的长度，例如 1<<20 (1MB)
	if err != nil {
		return err
	}
	err = json.Unmarshal(body, args)
	return err
}

// JSON 相应json数据
func JSON(w http.ResponseWriter, code int, data any) {
	w.Header().Set("Content-Type", "application/json;charset=UTF-8")

	response, err := json.Marshal(data)
	if err != nil {
		w.WriteHeader(500)
		w.Write([]byte(err.Error()))
	} else {
		w.WriteHeader(code)
		w.Write(response)
	}
}

// 将文件导出到外部下载
func FileAttachment(w http.ResponseWriter, r *http.Request, filepath, filename string) {
	w.Header().Set("Content-Disposition", `attachment; filename=`+url.QueryEscape(filename))
	w.Header().Set("Content-Type", "application/octet-stream")
	http.ServeFile(w, r, filepath)
}

// 将文件上传保存到指定目录
// file, handler, err := r.FormFile("file")
// SaveUploadedFile uploads the form file to specific dst.
func SaveUploadedFile(r *http.Request, dst string) error {
	// 解析请求中的文件
	_, handler, err := r.FormFile("file")
	if err != nil {
		return err
	}

	src, err := handler.Open()
	if err != nil {
		return err
	}
	defer src.Close()

	if err = os.MkdirAll(filepath.Dir(dst), 0750); err != nil {
		return err
	}

	out, err := os.Create(dst)
	if err != nil {
		return err
	}
	defer out.Close()

	_, err = io.Copy(out, src)
	return err
}

/// ==== 登录用户信息， 通过中间件后预置入

// Authorization 解析请求头
func Authorization(r *http.Request) string {
	authHeader := r.Header.Get(tokenConst.HEADER_KEY)
	if authHeader == "" {
		return ""
	}
	// 拆分 Authorization 请求头，提取 JWT 令牌部分
	arr := strings.Split(authHeader, tokenConst.HEADER_PREFIX)
	if len(arr) == 2 && arr[1] == "" {
		return ""
	}
	return arr[1]
}

// AcceptLanguage 解析客户端接收语言 zh：中文 en: 英文
func AcceptLanguage(r *http.Request) string {
	preferredLanguage := language.English

	// Query请求查询
	if v := GetQuery(r, "language"); v != "" {
		tags, _, _ := language.ParseAcceptLanguage(v)
		if len(tags) > 0 {
			preferredLanguage = tags[0]
		}
	}
	//  Header请求头
	if v := GetHeader(r, "Accept-Language"); v != "" {
		tags, _, _ := language.ParseAcceptLanguage(v)
		if len(tags) > 0 {
			preferredLanguage = tags[0]
		}
	}

	// 只取前缀
	lang := preferredLanguage.String()
	arr := strings.Split(lang, "-")
	return arr[0]
}

// ContextKey 定义自定义类型作为键
type ContextKey string

// LoginUser 登录用户信息需要Authorize中间件
func LoginUser(r *http.Request) (vo.LoginUser, error) {
	// 上下文
	v := r.Context().Value(ContextKey(commonConstants.CTX_LOGIN_USER))
	if v != nil {
		return v.(vo.LoginUser), nil
	}
	return vo.LoginUser{}, fmt.Errorf("No user information")
}

// LoginUserToUserID 登录用户信息-用户ID
func LoginUserToUserID(r *http.Request) string {
	loginUser, err := LoginUser(r)
	if err != nil {
		return ""
	}
	return loginUser.UserID
}

// LoginUserToUserName 登录用户信息-用户名称
func LoginUserToUserName(r *http.Request) string {
	loginUser, err := LoginUser(r)
	if err != nil {
		return ""
	}
	return loginUser.UserName
}
