package mfer

import (
	"bytes"
	"strings"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestNewBuilder(t *testing.T) {
	b := NewBuilder()
	assert.NotNil(t, b)
	assert.Equal(t, 0, b.FileCount())
}

func TestBuilderAddFile(t *testing.T) {
	b := NewBuilder()
	content := []byte("test content")
	reader := bytes.NewReader(content)

	bytesRead, err := b.AddFile("test.txt", FileSize(len(content)), ModTime(time.Now()), reader, nil)
	require.NoError(t, err)
	assert.Equal(t, FileSize(len(content)), bytesRead)
	assert.Equal(t, 1, b.FileCount())
}

func TestBuilderAddFileWithHash(t *testing.T) {
	b := NewBuilder()
	hash := make([]byte, 34) // SHA256 multihash is 34 bytes

	err := b.AddFileWithHash("test.txt", 100, ModTime(time.Now()), hash)
	require.NoError(t, err)
	assert.Equal(t, 1, b.FileCount())
}

func TestBuilderAddFileWithHashValidation(t *testing.T) {
	t.Run("empty path", func(t *testing.T) {
		b := NewBuilder()
		hash := make([]byte, 34)
		err := b.AddFileWithHash("", 100, ModTime(time.Now()), hash)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "path")
	})

	t.Run("negative size", func(t *testing.T) {
		b := NewBuilder()
		hash := make([]byte, 34)
		err := b.AddFileWithHash("test.txt", -1, ModTime(time.Now()), hash)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "size")
	})

	t.Run("nil hash", func(t *testing.T) {
		b := NewBuilder()
		err := b.AddFileWithHash("test.txt", 100, ModTime(time.Now()), nil)
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "hash")
	})

	t.Run("empty hash", func(t *testing.T) {
		b := NewBuilder()
		err := b.AddFileWithHash("test.txt", 100, ModTime(time.Now()), []byte{})
		assert.Error(t, err)
		assert.Contains(t, err.Error(), "hash")
	})

	t.Run("valid inputs", func(t *testing.T) {
		b := NewBuilder()
		hash := make([]byte, 34)
		err := b.AddFileWithHash("test.txt", 100, ModTime(time.Now()), hash)
		assert.NoError(t, err)
		assert.Equal(t, 1, b.FileCount())
	})
}

func TestBuilderBuild(t *testing.T) {
	b := NewBuilder()
	content := []byte("test content")
	reader := bytes.NewReader(content)

	_, err := b.AddFile("test.txt", FileSize(len(content)), ModTime(time.Now()), reader, nil)
	require.NoError(t, err)

	var buf bytes.Buffer
	err = b.Build(&buf)
	require.NoError(t, err)

	// Should have magic bytes
	assert.True(t, strings.HasPrefix(buf.String(), MAGIC))
}

func TestBuilderBuildEmpty(t *testing.T) {
	b := NewBuilder()

	var buf bytes.Buffer
	err := b.Build(&buf)
	require.NoError(t, err)

	// Should still produce valid manifest with 0 files
	assert.True(t, strings.HasPrefix(buf.String(), MAGIC))
}
