package mysql

import (
	"context"
	"encoding/json"
	"slices"
	"strings"
)

func (r *Repository) countResourceRows(ctx context.Context, table string, where string, args ...any) (int64, error) {
	var total int64
	if err := r.db.QueryRowContext(ctx, `SELECT COUNT(*) FROM `+table+` `+where, args...).Scan(&total); err != nil {
		return 0, err
	}
	return total, nil
}

func normalizePage(page int32, pageSize int32) (int32, int32) {
	return normalizePageWithMax(page, pageSize, 100)
}

func normalizePageWithMax(page int32, pageSize int32, maxPageSize int32) (int32, int32) {
	if page < 1 {
		page = 1
	}
	if pageSize < 1 {
		pageSize = 20
	}
	if maxPageSize <= 0 {
		maxPageSize = 100
	}
	if pageSize > maxPageSize {
		pageSize = maxPageSize
	}
	return page, pageSize
}

func resourceOffset(page int32, pageSize int32) int32 {
	return (page - 1) * pageSize
}

func placeholders(count int) string {
	if count <= 0 {
		return ""
	}
	items := make([]string, count)
	for index := range items {
		items[index] = "?"
	}
	return strings.Join(items, ",")
}

func int64AnyArgs(values []int64) []any {
	args := make([]any, 0, len(values))
	for _, value := range values {
		args = append(args, value)
	}
	return args
}

func stringAnyArgs(values []string) []any {
	args := make([]any, 0, len(values))
	for _, value := range values {
		args = append(args, value)
	}
	return args
}

func compactPositiveInt64s(values []int64) []int64 {
	seen := make(map[int64]struct{}, len(values))
	out := make([]int64, 0, len(values))
	for _, value := range values {
		if value <= 0 {
			continue
		}
		if _, exists := seen[value]; exists {
			continue
		}
		seen[value] = struct{}{}
		out = append(out, value)
	}
	return out
}

func parseStringArray(value string) []string {
	var out []string
	if err := json.Unmarshal([]byte(value), &out); err != nil {
		return nil
	}
	return normalizeStringList(out)
}

func normalizeRegionIDs(values []int64) []int64 {
	if len(values) == 0 {
		return []int64{0}
	}
	seen := make(map[int64]struct{}, len(values))
	out := make([]int64, 0, len(values))
	for _, value := range values {
		if value < 0 {
			out = append(out, value)
			continue
		}
		if _, ok := seen[value]; ok {
			continue
		}
		seen[value] = struct{}{}
		out = append(out, value)
	}
	slices.Sort(out)
	return out
}
