package storage

import (
	"bytes"
	"context"
	"io"
	"os"
	"path/filepath"
	"testing"

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

func TestLocalFS_PutGetDelete_Roundtrip(t *testing.T) {
	dir := t.TempDir()
	fs, err := NewLocalFS(dir)
	require.NoError(t, err)

	res, err := fs.Put(context.Background(), "2026/05/abc.txt",
		bytes.NewReader([]byte("hello")), "text/plain")
	require.NoError(t, err)
	require.Equal(t, "2026/05/abc.txt", res.StoragePath)
	require.Equal(t, int64(5), res.Size)
	require.Equal(t, "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824", res.SHA256)

	r, err := fs.Get(context.Background(), res.StoragePath)
	require.NoError(t, err)
	got, err := io.ReadAll(r)
	require.NoError(t, err)
	r.Close()
	require.Equal(t, "hello", string(got))

	full := filepath.Join(dir, res.StoragePath)
	_, err = os.Stat(full)
	require.NoError(t, err)

	require.NoError(t, fs.Delete(context.Background(), res.StoragePath))
	_, err = os.Stat(full)
	require.True(t, os.IsNotExist(err))
}

func TestLocalFS_RejectPathTraversal(t *testing.T) {
	fs, _ := NewLocalFS(t.TempDir())
	_, err := fs.Put(context.Background(), "../escape.txt", bytes.NewReader(nil), "text/plain")
	require.Error(t, err)
	_, err = fs.Get(context.Background(), "../etc/passwd")
	require.Error(t, err)
	require.Error(t, fs.Delete(context.Background(), "../oops"))
}

func TestLocalFS_DeleteNonexistentIsNoop(t *testing.T) {
	fs, _ := NewLocalFS(t.TempDir())
	require.NoError(t, fs.Delete(context.Background(), "nope/nope.txt"))
}

func TestLocalFS_RejectEmptyKey(t *testing.T) {
	fs, _ := NewLocalFS(t.TempDir())
	_, err := fs.Put(context.Background(), "", bytes.NewReader(nil), "text/plain")
	require.Error(t, err)
	_, err = fs.Put(context.Background(), ".", bytes.NewReader(nil), "text/plain")
	require.Error(t, err)
	_, err = fs.Get(context.Background(), "")
	require.Error(t, err)
	require.Error(t, fs.Delete(context.Background(), ""))
}

func TestLocalFS_GetMissingFileReturnsNilCloser(t *testing.T) {
	// 验证错误路径下不会返回 typed-nil io.ReadCloser
	fs, _ := NewLocalFS(t.TempDir())
	r, err := fs.Get(context.Background(), "missing/file.txt")
	require.Error(t, err)
	require.Nil(t, r)
}
