package utils

import (
	"fmt"
	"io"
	"os"
	"sync"

	"github.com/cespare/xxhash/v2"
)

var hashBufferPool = sync.Pool{
	New: func() any {
		buf := make([]byte, 128*1024)
		return &buf
	},
}

func getHashBuffer() *[]byte {
	return hashBufferPool.Get().(*[]byte)
}

func putHashBuffer(buf *[]byte) {
	hashBufferPool.Put(buf)
}

// ComputeXXH64 computes the XXH64 hash of a file using streaming I/O.
// Uses a constant ~128KB buffer regardless of file size.
// Returns the hash as a 16-character lowercase hexadecimal string.
func ComputeXXH64(filepath string) (string, error) {
	file, err := os.Open(filepath)
	if err != nil {
		return "", fmt.Errorf("failed to open file: %w", err)
	}
	defer func() { _ = file.Close() }()

	hashBufPtr := getHashBuffer()
	defer putHashBuffer(hashBufPtr)

	h := xxhash.New()
	if _, err := io.CopyBuffer(h, file, *hashBufPtr); err != nil {
		return "", fmt.Errorf("failed to read file: %w", err)
	}

	return fmt.Sprintf("%016x", h.Sum64()), nil
}