package main

import (
	"strings"
	"testing"
)

func TestParseGoModCapturesRequireVersions(t *testing.T) {
	info := parseGoMod(`
module github.com/nexuscrm/backend

require github.com/pingcap-inc/nexuscrm-contract v0.2.9

require (
	github.com/pingcap-inc/nexuscrm-api-host v0.16.0
	github.com/pingcap-inc/nexuscrm-controlplane v0.2.2 // indirect
)
`)

	for modulePath, want := range map[string]string{
		"github.com/pingcap-inc/nexuscrm-contract":     "v0.2.9",
		"github.com/pingcap-inc/nexuscrm-api-host":     "v0.16.0",
		"github.com/pingcap-inc/nexuscrm-controlplane": "v0.2.2",
	} {
		if got := info.requireVersions[modulePath]; got != want {
			t.Errorf("require version %s = %q, want %q", modulePath, got, want)
		}
	}
}

func TestEvaluateExternalPinMismatches(t *testing.T) {
	ownerVersions := map[string]string{}
	for _, modulePath := range synchronizedExternalModules {
		ownerVersions[modulePath] = "v1.2.3"
	}

	tests := []struct {
		name              string
		distributionPins  map[string]string
		deleteOwnerPin    string
		wantMismatchCount int
		want              string
	}{
		{
			name: "matching consumer",
			distributionPins: map[string]string{
				"github.com/pingcap-inc/nexuscrm-contract": "v1.2.3",
			},
		},
		{
			name: "consumer may omit module",
		},
		{
			name: "drift is rejected",
			distributionPins: map[string]string{
				"github.com/pingcap-inc/nexuscrm-contract": "v1.2.2",
			},
			wantMismatchCount: 1,
			want:              "distributions requires github.com/pingcap-inc/nexuscrm-contract v1.2.2",
		},
		{
			name:              "owner pin is required",
			deleteOwnerPin:    "github.com/pingcap-inc/nexuscrm-controlplane",
			wantMismatchCount: 1,
			want:              "is missing required external module github.com/pingcap-inc/nexuscrm-controlplane",
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			owner := cloneVersions(ownerVersions)
			delete(owner, test.deleteOwnerPin)
			modules := map[string]*Module{
				externalPinOwner: {
					Path:            externalPinOwner,
					RequireVersions: owner,
				},
				"github.com/nexuscrm/backend/distributions": {
					Path:            "github.com/nexuscrm/backend/distributions",
					RequireVersions: cloneVersions(test.distributionPins),
				},
			}

			got := evaluateExternalPinMismatches(modules)
			if len(got) != test.wantMismatchCount {
				t.Fatalf("mismatch count = %d, want %d: %+v", len(got), test.wantMismatchCount, got)
			}
			if test.want != "" && !strings.Contains(got[0].String(), test.want) {
				t.Fatalf("mismatch = %q, want substring %q", got[0].String(), test.want)
			}
		})
	}
}

func cloneVersions(in map[string]string) map[string]string {
	out := make(map[string]string, len(in))
	for modulePath, version := range in {
		out[modulePath] = version
	}
	return out
}
