package validate_test

import (
	"testing"
	"time"

	"bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/contracts/events"
	"bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/contracts/metadata"
	"bit.admedia.com/scm/ad/adpilot-indexing-repo-sync.com/internal/contracts/validate"
)

func TestFileChangedValid(t *testing.T) {
	event := events.NewFileChangedEvent(
		"evt_1",
		"company/payment-service",
		"snap_1",
		"a3f9c12b",
		"src/payments/processor.go",
		"go",
		events.FileKindCode,
		events.ChangeTypeModified,
	)

	if err := validate.FileChanged(event); err != nil {
		t.Fatalf("expected valid event, got %v", err)
	}
}

func TestFileChangedMissingRepoID(t *testing.T) {
	event := events.FileChangedEvent{
		Envelope: metadata.Envelope{
			EventID:      "evt_1",
			EventVersion: metadata.EventVersionV1,
			CreatedAt:    time.Now().UTC(),
		},
		SnapshotID: "snap_1",
		CommitSHA:  "a3f9c12b",
		FilePath:   "src/payments/processor.go",
		Language:   "go",
		FileKind:   events.FileKindCode,
		ChangeType: events.ChangeTypeModified,
	}

	if err := validate.FileChanged(event); err == nil {
		t.Fatal("expected validation error")
	}
}

func TestFileChangedMissingLanguage(t *testing.T) {
	event := events.NewFileChangedEvent(
		"evt_1",
		"company/payment-service",
		"snap_1",
		"a3f9c12b",
		"src/payments/processor.go",
		"",
		events.FileKindCode,
		events.ChangeTypeModified,
	)

	if err := validate.FileChanged(event); err == nil {
		t.Fatal("expected validation error for missing language")
	}
}

func TestFileChangedMissingFileKind(t *testing.T) {
	event := events.FileChangedEvent{
		Envelope: metadata.Envelope{
			EventID:      "evt_1",
			EventVersion: metadata.EventVersionV1,
			CreatedAt:    time.Now().UTC(),
		},
		RepoID:     "company/payment-service",
		SnapshotID: "snap_1",
		CommitSHA:  "a3f9c12b",
		FilePath:   "docs/architecture.md",
		Language:   "markdown",
		ChangeType: events.ChangeTypeAdded,
	}

	if err := validate.FileChanged(event); err == nil {
		t.Fatal("expected validation error for missing file_kind")
	}
}

func TestFileChangedInvalidFileKind(t *testing.T) {
	event := events.NewFileChangedEvent(
		"evt_1",
		"company/payment-service",
		"snap_1",
		"a3f9c12b",
		"README.md",
		"markdown",
		events.FileKind("readme"),
		events.ChangeTypeAdded,
	)

	if err := validate.FileChanged(event); err == nil {
		t.Fatal("expected validation error for invalid file_kind")
	}
}

func TestFileChangedInvalidChangeType(t *testing.T) {
	event := events.NewFileChangedEvent(
		"evt_1",
		"company/payment-service",
		"snap_1",
		"a3f9c12b",
		"src/payments/processor.go",
		"go",
		events.FileKindCode,
		events.ChangeType("copied"),
	)

	if err := validate.FileChanged(event); err == nil {
		t.Fatal("expected validation error for invalid change_type")
	}
}

func TestRepoSnapshotReadyValid(t *testing.T) {
	event := events.NewRepoSnapshotReadyEvent(
		"evt_2",
		"company/payment-service",
		"snap_1",
		"a3f9c12b",
		"main",
	)

	if err := validate.RepoSnapshotReady(event); err != nil {
		t.Fatalf("expected valid event, got %v", err)
	}
}

func TestRepoSnapshotReadyMissingRef(t *testing.T) {
	event := events.RepoSnapshotReadyEvent{
		Envelope: metadata.Envelope{
			EventID:      "evt_2",
			EventVersion: metadata.EventVersionV1,
			CreatedAt:    time.Now().UTC(),
		},
		RepoID:     "company/payment-service",
		SnapshotID: "snap_1",
		CommitSHA:  "a3f9c12b",
	}

	if err := validate.RepoSnapshotReady(event); err == nil {
		t.Fatal("expected validation error")
	}
}

func TestCommitsChangedValid(t *testing.T) {
	event := events.NewCommitsChangedEvent(
		"evt_3",
		"company/payment-service",
		"snap_1",
		"a3f9c12b",
	)

	if err := validate.CommitsChanged(event); err != nil {
		t.Fatalf("expected valid event, got %v", err)
	}
}

func TestCommitsChangedMissingCommitSHA(t *testing.T) {
	event := events.CommitsChangedEvent{
		Envelope: metadata.Envelope{
			EventID:      "evt_3",
			EventVersion: metadata.EventVersionV1,
			CreatedAt:    time.Now().UTC(),
		},
		RepoID:     "company/payment-service",
		SnapshotID: "snap_1",
	}

	if err := validate.CommitsChanged(event); err == nil {
		t.Fatal("expected validation error")
	}
}

func TestEnvelopeUnsupportedVersion(t *testing.T) {
	event := events.NewFileChangedEvent(
		"evt_4",
		"company/payment-service",
		"snap_1",
		"a3f9c12b",
		"src/payments/processor.go",
		"go",
		events.FileKindCode,
		events.ChangeTypeModified,
	)
	event.EventVersion = "v2"

	if err := validate.FileChanged(event); err == nil {
		t.Fatal("expected validation error for unsupported version")
	}
}
