package cli

import (
	"bytes"
	"context"
	"testing"

	"github.com/spf13/afero"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"sneak.berlin/go/mfer/mfer"
)

func TestFreshenUnchanged(t *testing.T) {
	// Create filesystem with test files
	fs := afero.NewMemMapFs()

	require.NoError(t, fs.MkdirAll("/testdir", 0o755))
	require.NoError(t, afero.WriteFile(fs, "/testdir/file1.txt", []byte("content1"), 0o644))
	require.NoError(t, afero.WriteFile(fs, "/testdir/file2.txt", []byte("content2"), 0o644))

	// Generate initial manifest
	opts := &mfer.ScannerOptions{Fs: fs}
	s := mfer.NewScannerWithOptions(opts)
	require.NoError(t, s.EnumeratePath("/testdir", nil))

	var manifestBuf bytes.Buffer
	require.NoError(t, s.ToManifest(context.Background(), &manifestBuf, nil))

	// Write manifest to filesystem
	require.NoError(t, afero.WriteFile(fs, "/testdir/.index.mf", manifestBuf.Bytes(), 0o644))

	// Parse manifest to verify
	manifest, err := mfer.NewManifestFromFile(fs, "/testdir/.index.mf")
	require.NoError(t, err)
	assert.Len(t, manifest.Files(), 2)
}

func TestFreshenWithChanges(t *testing.T) {
	// Create filesystem with test files
	fs := afero.NewMemMapFs()

	require.NoError(t, fs.MkdirAll("/testdir", 0o755))
	require.NoError(t, afero.WriteFile(fs, "/testdir/file1.txt", []byte("content1"), 0o644))
	require.NoError(t, afero.WriteFile(fs, "/testdir/file2.txt", []byte("content2"), 0o644))

	// Generate initial manifest
	opts := &mfer.ScannerOptions{Fs: fs}
	s := mfer.NewScannerWithOptions(opts)
	require.NoError(t, s.EnumeratePath("/testdir", nil))

	var manifestBuf bytes.Buffer
	require.NoError(t, s.ToManifest(context.Background(), &manifestBuf, nil))

	// Write manifest to filesystem
	require.NoError(t, afero.WriteFile(fs, "/testdir/.index.mf", manifestBuf.Bytes(), 0o644))

	// Verify initial manifest has 2 files
	manifest, err := mfer.NewManifestFromFile(fs, "/testdir/.index.mf")
	require.NoError(t, err)
	assert.Len(t, manifest.Files(), 2)

	// Add a new file
	require.NoError(t, afero.WriteFile(fs, "/testdir/file3.txt", []byte("content3"), 0o644))

	// Modify file2 (change content and size)
	require.NoError(t, afero.WriteFile(fs, "/testdir/file2.txt", []byte("modified content2"), 0o644))

	// Remove file1
	require.NoError(t, fs.Remove("/testdir/file1.txt"))

	// Note: The freshen operation would need to be run here
	// For now, we just verify the test setup is correct
	exists, _ := afero.Exists(fs, "/testdir/file1.txt")
	assert.False(t, exists)

	exists, _ = afero.Exists(fs, "/testdir/file3.txt")
	assert.True(t, exists)

	content, _ := afero.ReadFile(fs, "/testdir/file2.txt")
	assert.Equal(t, "modified content2", string(content))
}
