package infra

import (
	"fmt"
	"sort"
)

// MigrationValidate checks a slice of migrations for consistency errors.
// It verifies that:
//   - Versions are sequential starting from 1 with no gaps (1, 2, 3...)
//   - No duplicate versions exist
//   - Each migration has non-empty UpSQL
//   - Each migration has a non-empty Name
//
// Returns a slice of human-readable error strings. An empty slice means all
// migrations are valid. The function does not mutate the input slice.
func MigrationValidate(migrations []Migration) []string {
	var errs []string

	if len(migrations) == 0 {
		return errs
	}

	// Work on a sorted copy to detect gaps and duplicates
	sorted := make([]Migration, len(migrations))
	copy(sorted, migrations)
	sort.Slice(sorted, func(i, j int) bool {
		return sorted[i].Version < sorted[j].Version
	})

	// Check individual fields and collect duplicates
	seen := make(map[int]int) // version -> count
	for _, m := range sorted {
		seen[m.Version]++

		if m.Name == "" {
			errs = append(errs, fmt.Sprintf("version %d has empty name", m.Version))
		}
		if m.UpSQL == "" {
			errs = append(errs, fmt.Sprintf("version %d (%s) has empty up_sql", m.Version, m.Name))
		}
	}

	// Report duplicates
	for v, count := range seen {
		if count > 1 {
			errs = append(errs, fmt.Sprintf("duplicate version %d appears %d times", v, count))
		}
	}

	// Check sequential numbering starting from 1 (no gaps)
	// Build unique sorted versions
	versions := make([]int, 0, len(seen))
	for v := range seen {
		versions = append(versions, v)
	}
	sort.Ints(versions)

	if len(versions) > 0 && versions[0] != 1 {
		errs = append(errs, fmt.Sprintf("versions must start at 1, got %d", versions[0]))
	}

	for i := 1; i < len(versions); i++ {
		expected := versions[i-1] + 1
		if versions[i] != expected {
			errs = append(errs, fmt.Sprintf("gap in versions: missing %d (have %d then %d)", expected, versions[i-1], versions[i]))
		}
	}

	return errs
}
