package erasure_coding

import (
	"fmt"
	"os"
	"testing"

	"github.com/stretchr/testify/assert"

	"github.com/seaweedfs/seaweedfs/weed/pb/volume_server_pb"
	"github.com/seaweedfs/seaweedfs/weed/storage/needle"
	"github.com/seaweedfs/seaweedfs/weed/storage/types"
	"github.com/seaweedfs/seaweedfs/weed/storage/volume_info"
)

func TestPositioning(t *testing.T) {

	ecxFile, err := os.OpenFile("./test_files/389.ecx", os.O_RDONLY, 0)
	if err != nil {
		t.Errorf("failed to open ecx file: %v", err)
	}
	defer ecxFile.Close()

	stat, _ := ecxFile.Stat()
	fileSize := stat.Size()

	tests := []struct {
		needleId string
		offset   int64
		size     int
	}{
		{needleId: "0f0edb92", offset: 31300679656, size: 1167},
		{needleId: "0ef7d7f8", offset: 11513014944, size: 66044},
	}

	for _, test := range tests {
		needleId, _ := types.ParseNeedleId(test.needleId)
		offset, size, err := SearchNeedleFromSortedIndex(ecxFile, fileSize, needleId, nil)
		assert.Equal(t, nil, err, "SearchNeedleFromSortedIndex")
		fmt.Printf("offset: %d size: %d\n", offset.ToActualOffset(), size)
	}

	needleId, _ := types.ParseNeedleId("0f087622")
	offset, size, err := SearchNeedleFromSortedIndex(ecxFile, fileSize, needleId, nil)
	assert.Equal(t, nil, err, "SearchNeedleFromSortedIndex")
	fmt.Printf("offset: %d size: %d\n", offset.ToActualOffset(), size)

	var shardEcdFileSize int64 = 1118830592 // 1024*1024*1024*3
	intervals := LocateData(ErasureCodingLargeBlockSize, ErasureCodingSmallBlockSize, shardEcdFileSize, offset.ToActualOffset(), types.Size(needle.GetActualSize(size, needle.GetCurrentVersion())))

	for _, interval := range intervals {
		shardId, shardOffset := interval.ToShardIdAndOffset(ErasureCodingLargeBlockSize, ErasureCodingSmallBlockSize)
		fmt.Printf("interval: %+v, shardId: %d, shardOffset: %d\n", interval, shardId, shardOffset)
	}

}

// TestNewEcVolumeLoadsEncodeTsNs pins that the per-encode identity stamped into
// .vif is loaded onto the EcVolume, so reads can reject a shard from a different
// encode run.
func TestNewEcVolumeLoadsEncodeTsNs(t *testing.T) {
	dir := t.TempDir()
	const vid = needle.VolumeId(123)
	base := EcShardFileName("", dir, int(vid))

	// A 0-byte .ecx is a valid index (no live needles) and lets NewEcVolume mount.
	if err := os.WriteFile(base+".ecx", nil, 0o644); err != nil {
		t.Fatalf("write .ecx: %v", err)
	}

	const tsNs int64 = 1717000000000000123
	vi := &volume_server_pb.VolumeInfo{
		Version: uint32(needle.Version3),
		EcShardConfig: &volume_server_pb.EcShardConfig{
			DataShards:   10,
			ParityShards: 4,
			EncodeTsNs:   tsNs,
		},
	}
	if err := volume_info.SaveVolumeInfo(base+".vif", vi); err != nil {
		t.Fatalf("save .vif: %v", err)
	}

	ev, err := NewEcVolume(types.HardDriveType, dir, dir, "", vid)
	if err != nil {
		t.Fatalf("NewEcVolume: %v", err)
	}
	defer ev.Close()

	if ev.EncodeTsNs != tsNs {
		t.Errorf("EncodeTsNs = %d, want %d", ev.EncodeTsNs, tsNs)
	}
}
