package exporter

import (
	"fmt"
	"strconv"
	"strings"
	"time"

	"gorm.io/gorm"

	"github.com/break/junhong_cmp_fiber/pkg/constants"
)

const exportTimeLayout = "2006-01-02 15:04:05"

func applyExportShopScope(query *gorm.DB, params ExportParams, column string) *gorm.DB {
	switch params.UserType {
	case constants.UserTypeSuperAdmin, constants.UserTypePlatform:
		return query
	case constants.UserTypeAgent:
		if len(params.ScopeShopIDs) == 0 {
			return query.Where("1 = 0")
		}
		return query.Where(column+" IN ?", params.ScopeShopIDs)
	default:
		return query.Where("1 = 0")
	}
}

func filterInt(filters map[string]any, key string) (int, bool) {
	value, ok := filters[key]
	if !ok || value == nil {
		return 0, false
	}

	switch v := value.(type) {
	case int:
		return v, true
	case int64:
		return int(v), true
	case uint:
		return int(v), true
	case uint64:
		return int(v), true
	case float64:
		return int(v), true
	case string:
		if strings.TrimSpace(v) == "" {
			return 0, false
		}
		parsed, err := strconv.Atoi(v)
		if err != nil {
			return 0, false
		}
		return parsed, true
	default:
		return 0, false
	}
}

func filterUint(filters map[string]any, key string) (uint, bool) {
	value, ok := filterInt(filters, key)
	if !ok || value <= 0 {
		return 0, false
	}
	return uint(value), true
}

func filterString(filters map[string]any, key string) (string, bool) {
	value, ok := filters[key]
	if !ok || value == nil {
		return "", false
	}
	text := strings.TrimSpace(fmt.Sprint(value))
	if text == "" {
		return "", false
	}
	return text, true
}

func filterBool(filters map[string]any, key string) bool {
	value, ok := filters[key]
	if !ok || value == nil {
		return false
	}

	switch v := value.(type) {
	case bool:
		return v
	case string:
		parsed, err := strconv.ParseBool(strings.TrimSpace(v))
		return err == nil && parsed
	default:
		return false
	}
}

// filterOptionalBool 解析可选布尔筛选项。
// 返回第二个值标识调用方是否明确传入该筛选项，避免 false 被误判为未传。
func filterOptionalBool(filters map[string]any, key string) (bool, bool) {
	value, ok := filters[key]
	if !ok || value == nil {
		return false, false
	}

	switch v := value.(type) {
	case bool:
		return v, true
	case string:
		if strings.TrimSpace(v) == "" {
			return false, false
		}
		parsed, err := strconv.ParseBool(strings.TrimSpace(v))
		if err != nil {
			return false, false
		}
		return parsed, true
	case int:
		return v != 0, true
	case int64:
		return v != 0, true
	case uint:
		return v != 0, true
	case uint64:
		return v != 0, true
	case float64:
		return v != 0, true
	default:
		return false, false
	}
}

// filterUintSlice 解析前端 JSON 或查询参数中的 uint 数组筛选项。
// 空数组按未传处理；数组存在但过滤后为空时由调用方决定是否返回空结果。
func filterUintSlice(filters map[string]any, key string) ([]uint, bool) {
	value, ok := filters[key]
	if !ok || value == nil {
		return nil, false
	}

	switch v := value.(type) {
	case []uint:
		if len(v) == 0 {
			return nil, false
		}
		return normalizeUintSlice(v), true
	case []int:
		if len(v) == 0 {
			return nil, false
		}
		result := make([]uint, 0, len(v))
		for _, item := range v {
			if item > 0 {
				result = append(result, uint(item))
			}
		}
		return normalizeUintSlice(result), true
	case []float64:
		if len(v) == 0 {
			return nil, false
		}
		result := make([]uint, 0, len(v))
		for _, item := range v {
			if item > 0 {
				result = append(result, uint(item))
			}
		}
		return normalizeUintSlice(result), true
	case []any:
		if len(v) == 0 {
			return nil, false
		}
		result := make([]uint, 0, len(v))
		for _, item := range v {
			switch typed := item.(type) {
			case int:
				if typed > 0 {
					result = append(result, uint(typed))
				}
			case int64:
				if typed > 0 {
					result = append(result, uint(typed))
				}
			case uint:
				if typed > 0 {
					result = append(result, typed)
				}
			case uint64:
				if typed > 0 {
					result = append(result, uint(typed))
				}
			case float64:
				if typed > 0 {
					result = append(result, uint(typed))
				}
			case string:
				if parsed, err := strconv.ParseUint(strings.TrimSpace(typed), 10, 64); err == nil && parsed > 0 {
					result = append(result, uint(parsed))
				}
			}
		}
		return normalizeUintSlice(result), true
	case string:
		if strings.TrimSpace(v) == "" {
			return nil, false
		}
		parts := strings.Split(v, ",")
		result := make([]uint, 0, len(parts))
		for _, part := range parts {
			parsed, err := strconv.ParseUint(strings.TrimSpace(part), 10, 64)
			if err == nil && parsed > 0 {
				result = append(result, uint(parsed))
			}
		}
		return normalizeUintSlice(result), true
	default:
		return nil, false
	}
}

// normalizeUintSlice 去除无效值和重复 ID，保留原始顺序。
func normalizeUintSlice(values []uint) []uint {
	seen := make(map[uint]struct{}, len(values))
	result := make([]uint, 0, len(values))
	for _, value := range values {
		if value == 0 {
			continue
		}
		if _, ok := seen[value]; ok {
			continue
		}
		seen[value] = struct{}{}
		result = append(result, value)
	}
	return result
}

func filterTime(filters map[string]any, key string) (time.Time, bool) {
	text, ok := filterString(filters, key)
	if !ok {
		return time.Time{}, false
	}

	layouts := []string{
		time.RFC3339,
		"2006-01-02 15:04:05",
		"2006-01-02",
	}
	for _, layout := range layouts {
		parsed, err := time.ParseInLocation(layout, text, time.Local)
		if err == nil {
			return parsed, true
		}
	}
	return time.Time{}, false
}

// filterEndDate 解析截止时间；纯日期输入覆盖到当天结束，带时分秒输入保持原值。
func filterEndDate(filters map[string]any, key string) (time.Time, bool) {
	text, ok := filterString(filters, key)
	if !ok {
		return time.Time{}, false
	}
	if parsed, err := time.ParseInLocation("2006-01-02", text, time.Local); err == nil {
		return parsed.Add(24*time.Hour - time.Nanosecond), true
	}
	return filterTime(filters, key)
}

func formatOptionalUint(value *uint) string {
	if value == nil {
		return ""
	}
	return strconv.FormatUint(uint64(*value), 10)
}

func formatOptionalTime(value *time.Time) string {
	if value == nil {
		return ""
	}
	return value.Format(exportTimeLayout)
}
