package boundary_test

import (
	"os"
	"path/filepath"
	"strings"
	"testing"
)

func TestL0AnalyticsDoesNotOwnDashboardProductShell(t *testing.T) {
	root := repoRoot(t)
	analyticsDir := goModuleDir(t, root, "github.com/nexuscrm/analytics")
	for _, file := range productionGoFiles(t, analyticsDir) {
		rel := toRepoRelative(t, root, file)
		body := readFile(t, file)
		for _, token := range []string{
			"DashboardService",
			"DashboardEffectiveUserPolicy",
			"DashboardType",
			"RunningUserId",
			"TableDashboard",
			"TableDashboardComponent",
		} {
			if strings.Contains(body, token) {
				t.Fatalf("%s contains %q; Dashboard product orchestration must live outside L0 analytics", rel, token)
			}
		}
	}
}

func TestDefaultServiceManagerDoesNotImportCRMProductPackages(t *testing.T) {
	root := repoRoot(t)
	servicesDir := filepath.Join(root, "backend/internal/application/services")
	for _, file := range productionGoFiles(t, servicesDir) {
		rel := toRepoRelative(t, root, file)
		body := readFile(t, file)
		if strings.Contains(body, `"github.com/nexuscrm/backend/internal/application/crm/`) {
			t.Fatalf("%s imports a CRM product package; default ServiceManager wiring must stay app-blind", rel)
		}
	}
}

func TestBackendInternalDoesNotOwnCRMDashboardServiceSlot(t *testing.T) {
	root := repoRoot(t)
	servicesDir := filepath.Join(root, "backend/internal/application/services")
	for _, file := range productionGoFiles(t, servicesDir) {
		rel := toRepoRelative(t, root, file)
		body := readFile(t, file)
		for _, token := range []string{"DashboardService", "DashboardSvc"} {
			if strings.Contains(body, token) {
				t.Fatalf("%s contains %q; CRM Dashboard service slots must stay out of backend-internal ServiceManager", rel, token)
			}
		}
	}
}

func TestBackendRESTDoesNotOwnCRMDashboardHandler(t *testing.T) {
	root := repoRoot(t)
	path := filepath.Join(root, "backend/internal/interfaces/rest/dashboard_handler.go")
	if _, err := os.Stat(path); err == nil {
		t.Fatalf("%s exists; CRM Dashboard route and DTO ownership must live in dialect-sf-crm", toRepoRelative(t, root, path))
	} else if !os.IsNotExist(err) {
		t.Fatalf("stat %s: %v", toRepoRelative(t, root, path), err)
	}
}

func TestBackendInternalDoesNotOwnCRMDashboardProductService(t *testing.T) {
	root := repoRoot(t)
	dashboardDir := filepath.Join(root, "backend/internal/application/crm/dashboard")
	entries, err := os.ReadDir(dashboardDir)
	if err != nil {
		if os.IsNotExist(err) {
			return
		}
		t.Fatalf("read backend CRM dashboard dir: %v", err)
	}
	for _, entry := range entries {
		if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") || strings.HasSuffix(entry.Name(), "_test.go") {
			continue
		}
		t.Fatalf("backend/internal/application/crm/dashboard/%s exists; CRM Dashboard product service must live in the external CRM dialect module", entry.Name())
	}
}

func TestSharedAnalyticsDoesNotOwnSalesforceDashboardWireDTOs(t *testing.T) {
	root := repoRoot(t)
	path := filepath.Join(root, "shared/pkg/models/analytics.go")
	body := readFile(t, path)
	for _, token := range []string{
		"DashboardDefinition",
		"ComponentDefinition",
		"DashboardResult",
		"dashboardMetadata",
		"componentData",
		"generatedAt",
		"DashboardType",
		"RunningUserId",
	} {
		if strings.Contains(body, token) {
			t.Fatalf("%s contains %q; Salesforce Dashboard DTO/product fields belong in the CRM dialect, not shared L0 models", toRepoRelative(t, root, path), token)
		}
	}
}
