package handlers

import (
	"encoding/json"
	"fmt"
	"fusenapi/constants"
	"strconv"
	"strings"
	"unicode"

	"gorm.io/gorm"
)

// FilterData 条件过滤
func FilterData(filterMap map[string]string) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		// 组合索引
		db = db.Where("id <> ?", 0)
		for fieldName, item := range filterMap {
			options := strings.Split(item, "|")
			conditionKey := options[1]

			var conditionValueType string
			if len(options) == 3 {
				conditionValueType = options[2]
			}

			var conditionValue interface{}

			if conditionKey == "=" || conditionKey == "<>" || conditionKey == ">=" || conditionKey == "<=" {
				conditionStr := options[0]
				if conditionValueType == "string" {
					conditionValue = options[0]
				} else {
					if ss := CheckIsDigit(conditionStr); ss != 0 {
						conditionValue = ss
					} else {
						conditionValue = options[0]
					}
				}
			} else {
				var conditionArrNew []int64
				conditionArr := strings.Split(options[0], ",")
				for _, s := range conditionArr {
					if ss := CheckIsDigit(s); ss != 0 {
						conditionArrNew = append(conditionArrNew, ss)
					}
				}
				if len(conditionArrNew) > 0 {
					conditionValue = conditionArrNew
				} else {
					conditionValue = conditionArr
				}
			}

			switch conditionKey {
			case "LIKE":
				db = db.Where(fmt.Sprintf("%v LIKE ?", fieldName), fmt.Sprintf("%%%v%%", conditionValue))
			case "BETWEEN":
				db = db.Where(fmt.Sprintf("%v BETWEEN  ? AND ?", fieldName), conditionValue.([]interface{})[0], conditionValue.([]interface{})[1])
			default:
				db = db.Where(fmt.Sprintf("%v %v ?", fieldName, conditionKey), conditionValue)
			}
		}
		return db
	}
}

// OrderCheck 公共排序--检测
func OrderCheck(orderData string, fields map[string]struct{}) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		var orderType = "desc"
		if orderData != "" {
			var sortData []map[string]interface{}
			_ = json.Unmarshal([]byte(orderData), &sortData)

			sortCount := len(sortData)
			for i := 0; i < sortCount; i++ {
				data := sortData[i]
				prop, existProp := data["prop"]
				sort, existSort := data["order"]
				if existProp && existSort {
					propData := strings.TrimSpace(prop.(string))
					sortData := strings.TrimSpace(sort.(string))
					if propData != "" && sortData != "" {
						// 判断数据库字段
						_, existFields := fields[propData]
						if existFields {
							if sortData == "descending" || sortData == "desc" {
								orderType = "desc"
							} else {
								orderType = "asc"
							}
							db.Order(fmt.Sprintf("%v %v", prop, orderType))
						}
					}
				}
			}
			return db
		} else {
			return db.Order("id asc")
		}
	}
}

// Paginate 公共分页
func Paginate(page *int64, pageSize *int64) func(db *gorm.DB) *gorm.DB {
	return func(db *gorm.DB) *gorm.DB {
		page, _ := strconv.Atoi(strconv.FormatInt(*page, 10))

		switch {
		case page == 0:
			page = constants.DEFAULT_PAGE
		case page > constants.MAX_PAGE:
			page = constants.MAX_PAGE
		}

		pageSize, _ := strconv.Atoi(strconv.FormatInt(*pageSize, 10))
		switch {
		case pageSize > constants.MAX_PAGE_SIZE:
			pageSize = constants.MAX_PAGE_SIZE
		case pageSize <= 0:
			pageSize = constants.DEFAULT_PAGE_SIZE
		}

		offset := (page - 1) * pageSize
		return db.Offset(offset).Limit(pageSize)
	}
}

// CheckIsDigit 判断int
func CheckIsDigit(s string) int64 {
	isDigit := true
	for _, r := range s {
		if !unicode.IsDigit(r) {
			isDigit = false
			break
		}
	}
	if isDigit {
		ss, _ := strconv.ParseInt(s, 10, 64)
		return ss
	} else {
		return 0
	}
}