package storage_test

import (
	"bytes"
	"os"
	"path/filepath"
	"testing"
	"time"

	"archivmail/internal/storage"
)

func TestSaveAndLoad(t *testing.T) {
	dir := t.TempDir()
	store, err := storage.New(dir)
	if err != nil {
		t.Fatalf("New: %v", err)
	}

	raw := []byte("From: alice@example.com\r\nSubject: Test\r\n\r\nHello World")
	id, err := store.Save(raw, time.Now())
	if err != nil {
		t.Fatalf("Save: %v", err)
	}
	if len(id) != 64 {
		t.Errorf("expected 64-char SHA256 hex, got %d chars", len(id))
	}

	got, err := store.Load(id)
	if err != nil {
		t.Fatalf("Load: %v", err)
	}
	if !bytes.Equal(raw, got) {
		t.Errorf("loaded content mismatch")
	}
}

func TestDeduplication(t *testing.T) {
	dir := t.TempDir()
	store, err := storage.New(dir)
	if err != nil {
		t.Fatal(err)
	}

	raw := []byte("From: alice@example.com\r\n\r\nDuplicate test")
	id1, err := store.Save(raw, time.Now())
	if err != nil {
		t.Fatal(err)
	}
	id2, err := store.Save(raw, time.Now())
	if err != nil {
		t.Fatal(err)
	}
	if id1 != id2 {
		t.Errorf("duplicate mail produced different IDs: %s vs %s", id1, id2)
	}

	// Only one file should exist
	count := 0
	filepath.Walk(filepath.Join(dir, "store"), func(p string, info os.FileInfo, _ error) error {
		if !info.IsDir() { count++ }
		return nil
	})
	if count != 1 {
		t.Errorf("expected 1 stored file after dedup, got %d", count)
	}
}

func TestDelete(t *testing.T) {
	dir := t.TempDir()
	store, err := storage.New(dir)
	if err != nil {
		t.Fatal(err)
	}

	raw := []byte("From: alice@example.com\r\n\r\nDelete me")
	id, _ := store.Save(raw, time.Now())

	if err := store.Delete(id); err != nil {
		t.Fatalf("Delete: %v", err)
	}
	if _, err := store.Load(id); err == nil {
		t.Error("Load after Delete should return error")
	}
}

func TestStats(t *testing.T) {
	dir := t.TempDir()
	store, err := storage.New(dir)
	if err != nil {
		t.Fatal(err)
	}

	mails := [][]byte{
		[]byte("From: a@x.com\r\n\r\nMail 1"),
		[]byte("From: b@x.com\r\n\r\nMail 2"),
		[]byte("From: c@x.com\r\n\r\nMail 3"),
	}
	for _, m := range mails {
		store.Save(m, time.Now())
	}

	stats, err := store.Stats()
	if err != nil {
		t.Fatalf("Stats: %v", err)
	}
	if stats.TotalMails != 3 {
		t.Errorf("expected 3 mails, got %d", stats.TotalMails)
	}
	if stats.TotalBytes <= 0 {
		t.Error("expected positive TotalBytes")
	}
}

func TestStorageDirectoryCreation(t *testing.T) {
	dir := filepath.Join(t.TempDir(), "nested", "path")
	_, err := storage.New(dir)
	if err != nil {
		t.Fatalf("New with nested path: %v", err)
	}
	for _, sub := range []string{"store", "attachments", "meta"} {
		if _, err := os.Stat(filepath.Join(dir, sub)); os.IsNotExist(err) {
			t.Errorf("expected subdirectory %s to be created", sub)
		}
	}
}
