package infra

import (
	"testing"
)

func makeVF(relPath, sha256 string) VaultFile {
	return VaultFile{
		VaultID:   "test_vault",
		VaultName: "test",
		RelPath:   relPath,
		Sha256:    sha256,
	}
}

func TestVaultDiff_NoChanges(t *testing.T) {
	files := []VaultFile{
		makeVF("data/a.csv", "aaa"),
		makeVF("data/b.csv", "bbb"),
	}
	report := VaultDiff(files, files)
	if len(report.Added) != 0 {
		t.Errorf("Added: want 0, got %d", len(report.Added))
	}
	if len(report.Removed) != 0 {
		t.Errorf("Removed: want 0, got %d", len(report.Removed))
	}
	if len(report.Changed) != 0 {
		t.Errorf("Changed: want 0, got %d", len(report.Changed))
	}
	if report.Unchanged != 2 {
		t.Errorf("Unchanged: want 2, got %d", report.Unchanged)
	}
}

func TestVaultDiff_AllAdded(t *testing.T) {
	curr := []VaultFile{
		makeVF("data/a.csv", "aaa"),
		makeVF("data/b.csv", "bbb"),
	}
	report := VaultDiff(nil, curr)
	if len(report.Added) != 2 {
		t.Errorf("Added: want 2, got %d", len(report.Added))
	}
	if len(report.Removed) != 0 {
		t.Errorf("Removed: want 0, got %d", len(report.Removed))
	}
	if report.Added[0].RelPath != "data/a.csv" {
		t.Errorf("Added[0]: want data/a.csv, got %s", report.Added[0].RelPath)
	}
	if report.Added[1].RelPath != "data/b.csv" {
		t.Errorf("Added[1]: want data/b.csv, got %s", report.Added[1].RelPath)
	}
}

func TestVaultDiff_AllRemoved(t *testing.T) {
	prev := []VaultFile{
		makeVF("data/a.csv", "aaa"),
		makeVF("data/b.csv", "bbb"),
	}
	report := VaultDiff(prev, nil)
	if len(report.Removed) != 2 {
		t.Errorf("Removed: want 2, got %d", len(report.Removed))
	}
	if len(report.Added) != 0 {
		t.Errorf("Added: want 0, got %d", len(report.Added))
	}
	if report.Removed[0].RelPath != "data/a.csv" {
		t.Errorf("Removed[0]: want data/a.csv, got %s", report.Removed[0].RelPath)
	}
}

func TestVaultDiff_ContentChanged(t *testing.T) {
	prev := []VaultFile{
		makeVF("data/a.csv", "old_hash"),
	}
	curr := []VaultFile{
		makeVF("data/a.csv", "new_hash"),
	}
	report := VaultDiff(prev, curr)
	if len(report.Changed) != 1 {
		t.Fatalf("Changed: want 1, got %d", len(report.Changed))
	}
	if report.Changed[0].RelPath != "data/a.csv" {
		t.Errorf("Changed[0].RelPath: want data/a.csv, got %s", report.Changed[0].RelPath)
	}
	if report.Changed[0].Prev.Sha256 != "old_hash" {
		t.Errorf("Changed[0].Prev.Sha256: want old_hash, got %s", report.Changed[0].Prev.Sha256)
	}
	if report.Changed[0].Curr.Sha256 != "new_hash" {
		t.Errorf("Changed[0].Curr.Sha256: want new_hash, got %s", report.Changed[0].Curr.Sha256)
	}
	if len(report.Added) != 0 || len(report.Removed) != 0 {
		t.Errorf("Expected no added/removed, got %d/%d", len(report.Added), len(report.Removed))
	}
	if report.Unchanged != 0 {
		t.Errorf("Unchanged: want 0, got %d", report.Unchanged)
	}
}

func TestVaultDiff_Mixed(t *testing.T) {
	prev := []VaultFile{
		makeVF("data/a.csv", "aaa"),
		makeVF("data/b.csv", "bbb"),
		makeVF("data/c.csv", "ccc"),
	}
	curr := []VaultFile{
		makeVF("data/a.csv", "aaa"),     // unchanged
		makeVF("data/b.csv", "bbb_new"), // changed
		makeVF("data/d.csv", "ddd"),     // added
	}
	report := VaultDiff(prev, curr)

	if len(report.Added) != 1 || report.Added[0].RelPath != "data/d.csv" {
		t.Errorf("Added: want [data/d.csv], got %v", report.Added)
	}
	if len(report.Removed) != 1 || report.Removed[0].RelPath != "data/c.csv" {
		t.Errorf("Removed: want [data/c.csv], got %v", report.Removed)
	}
	if len(report.Changed) != 1 || report.Changed[0].RelPath != "data/b.csv" {
		t.Errorf("Changed: want [data/b.csv], got %v", report.Changed)
	}
	if report.Unchanged != 1 {
		t.Errorf("Unchanged: want 1, got %d", report.Unchanged)
	}
}
