package infra

import "sort"

// VaultFileChange holds the before/after state of a file whose content changed.
type VaultFileChange struct {
	RelPath string
	Prev    VaultFile
	Curr    VaultFile
}

// VaultDiffReport is the result of comparing two VaultFile slices.
type VaultDiffReport struct {
	Added     []VaultFile       // in curr but not in prev (by rel_path)
	Removed   []VaultFile       // in prev but not in curr
	Changed   []VaultFileChange // same rel_path, different sha256
	Unchanged int               // files present in both with identical sha256
}

// VaultDiff computes the difference between two vault snapshots.
// It indexes both slices by RelPath, then classifies each entry as
// Added, Removed, Changed, or Unchanged. All output slices are sorted
// by RelPath ascending. The function is pure and deterministic.
func VaultDiff(prev, curr []VaultFile) VaultDiffReport {
	prevMap := make(map[string]VaultFile, len(prev))
	for _, f := range prev {
		prevMap[f.RelPath] = f
	}
	currMap := make(map[string]VaultFile, len(curr))
	for _, f := range curr {
		currMap[f.RelPath] = f
	}

	var report VaultDiffReport

	for _, f := range curr {
		p, exists := prevMap[f.RelPath]
		if !exists {
			report.Added = append(report.Added, f)
		} else if p.Sha256 != f.Sha256 {
			report.Changed = append(report.Changed, VaultFileChange{
				RelPath: f.RelPath,
				Prev:    p,
				Curr:    f,
			})
		} else {
			report.Unchanged++
		}
	}

	for _, f := range prev {
		if _, exists := currMap[f.RelPath]; !exists {
			report.Removed = append(report.Removed, f)
		}
	}

	sort.Slice(report.Added, func(i, j int) bool {
		return report.Added[i].RelPath < report.Added[j].RelPath
	})
	sort.Slice(report.Removed, func(i, j int) bool {
		return report.Removed[i].RelPath < report.Removed[j].RelPath
	})
	sort.Slice(report.Changed, func(i, j int) bool {
		return report.Changed[i].RelPath < report.Changed[j].RelPath
	})

	return report
}
