package util

import (
	"fmt"
	"os"
	"strings"
	"time"
)

// LocateLatestOnTheHour get the latest on the hour by ts.
// The result will be used as directory name in s3.
func LocateLatestOnTheHour(ts int64) int64 {
	t := time.Unix(ts, 0)
	latestOnTheHour := t.Truncate(time.Hour)
	return latestOnTheHour.Unix()
}

// LocateLatestOnTheMinute get the latest on the minute by ts.
func LocateLatestOnTheMinute(ts int64) int64 {
	t := time.Unix(ts, 0)
	latestOnTheMinute := t.Truncate(time.Minute)
	return latestOnTheMinute.Unix()
}

func EnsureDir(dir string) error {
	info, err := os.Stat(dir)
	if err != nil {
		err = os.Mkdir(dir, 0777)
		if err != nil {
			return fmt.Errorf("failed to make directory: %s", err)
		}
		return nil
	}
	if info.IsDir() {
		return nil
	}
	return fmt.Errorf("file exsits but not a directory")
}

func IsNotFoundError(err error) bool {
	errStr := err.Error()
	return strings.Contains(errStr, "not found") || strings.Contains(errStr, "no rows in result set")
}

func AverageInt64(arr []int64) float64 {
	if len(arr) == 0 {
		return 0
	}
	var sum int64
	for _, v := range arr {
		sum += v
	}
	return float64(sum) / float64(len(arr))
}

func MaxInt64(arr []int64) int64 {
	if len(arr) == 0 {
		return 0
	}
	max := arr[0]
	for _, v := range arr {
		if v > max {
			max = v
		}
	}
	return max
}

func PercentileInt64(arr []int64, percentile int) float64 {
	if len(arr) == 0 {
		return 0
	}

	// Validate percentile range
	if percentile < 0 || percentile > 100 {
		return 0
	}

	// Create a copy of the array to avoid modifying the original
	sorted := make([]int64, len(arr))
	copy(sorted, arr)

	// Sort the array
	for i := 0; i < len(sorted); i++ {
		for j := i + 1; j < len(sorted); j++ {
			if sorted[i] > sorted[j] {
				sorted[i], sorted[j] = sorted[j], sorted[i]
			}
		}
	}

	// Calculate the index for the percentile
	n := float64(len(sorted))
	index := (float64(percentile) / 100.0) * (n - 1)

	// If index is a whole number, return the value at that index
	if index == float64(int(index)) {
		return float64(sorted[int(index)])
	}

	// Otherwise, interpolate between the two nearest values
	lowerIndex := int(index)
	upperIndex := lowerIndex + 1

	if upperIndex >= len(sorted) {
		return float64(sorted[len(sorted)-1])
	}

	// Linear interpolation
	weight := index - float64(lowerIndex)
	result := float64(sorted[lowerIndex])*(1-weight) + float64(sorted[upperIndex])*weight

	return result
}
