package store

import (
	"context"
	"errors"
	"os"
	"strings"
	"testing"
	"time"
)

func TestModelIdentityRoutingAndDeleteProtection(t *testing.T) {
	databaseURL := strings.TrimSpace(os.Getenv("AI_GATEWAY_TEST_DATABASE_URL"))
	if databaseURL == "" {
		t.Skip("set AI_GATEWAY_TEST_DATABASE_URL to run model identity PostgreSQL integration tests")
	}

	ctx := context.Background()
	db, err := Connect(ctx, databaseURL)
	if err != nil {
		t.Fatalf("connect test database: %v", err)
	}
	defer db.Close()

	suffix := time.Now().UTC().Format("20060102150405.000000000")
	invocationName := "official-model-" + suffix
	legacyAlias := "Legacy Model " + suffix
	displayName := "Model Card " + suffix
	baseModel, err := db.CreateBaseModel(ctx, BaseModelInput{
		ProviderKey:       "openai",
		CanonicalModelKey: "openai:" + invocationName,
		InvocationName:    invocationName,
		ProviderModelName: "provider/" + invocationName,
		ModelType:         StringList{"text_generate"},
		DisplayName:       displayName,
		LegacyAliases:     StringList{legacyAlias},
		Status:            "active",
	})
	if err != nil {
		t.Fatalf("create base model: %v", err)
	}
	defer func() {
		_, _ = db.pool.Exec(ctx, `DELETE FROM platform_models WHERE base_model_id = $1::uuid`, baseModel.ID)
		_, _ = db.pool.Exec(ctx, `DELETE FROM base_model_catalog WHERE id = $1::uuid`, baseModel.ID)
	}()

	var platformID string
	if err := db.pool.QueryRow(ctx, `
SELECT id::text
FROM integration_platforms
WHERE status = 'enabled' AND deleted_at IS NULL
ORDER BY created_at ASC
LIMIT 1`).Scan(&platformID); err != nil {
		t.Fatalf("find enabled platform: %v", err)
	}
	var platformModelID string
	if err := db.pool.QueryRow(ctx, `
INSERT INTO platform_models (
  platform_id, base_model_id, model_name, provider_model_name, model_alias,
  model_type, display_name, enabled
)
VALUES ($1::uuid, $2::uuid, $3, $4, $3, '["text_generate"]'::jsonb, $5, true)
RETURNING id::text`, platformID, baseModel.ID, invocationName, "provider/"+invocationName, displayName).Scan(&platformModelID); err != nil {
		t.Fatalf("bind platform model: %v", err)
	}

	if err := db.DeleteBaseModel(ctx, baseModel.ID); !errors.Is(err, ErrBaseModelInUse) {
		t.Fatalf("bound base model deletion should be protected: %v", err)
	}

	officialCandidates, err := db.ListModelCandidates(ctx, invocationName, "text_generate", nil)
	if err != nil || len(officialCandidates) != 1 || officialCandidates[0].PlatformModelID != platformModelID {
		t.Fatalf("official invocation should resolve the bound source: candidates=%+v err=%v", officialCandidates, err)
	}
	legacyCandidates, err := db.ListModelCandidates(ctx, legacyAlias, "text_generate", nil)
	if err != nil || len(legacyCandidates) != 1 || !legacyCandidates[0].LegacyAliasUsed {
		t.Fatalf("registered legacy alias should resolve and be marked: candidates=%+v err=%v", legacyCandidates, err)
	}
	if _, err := db.ListModelCandidates(ctx, displayName, "text_generate", nil); !errors.Is(err, ErrNoModelCandidate) {
		t.Fatalf("display name must not become an invocation alias: %v", err)
	}

	var legacyHits int64
	if err := db.pool.QueryRow(ctx, `
SELECT hit_count
FROM model_alias_usage_metrics
WHERE alias = $1 AND canonical_model_key = $2 AND model_type = 'text_generate'`, legacyAlias, baseModel.CanonicalModelKey).Scan(&legacyHits); err != nil {
		t.Fatalf("read legacy alias metric: %v", err)
	}
	if legacyHits != 1 {
		t.Fatalf("expected one legacy alias hit, got %d", legacyHits)
	}

	deprecatedInvocation := "deprecated-model-" + suffix
	deprecatedBase, err := db.CreateBaseModel(ctx, BaseModelInput{
		ProviderKey:       "openai",
		CanonicalModelKey: "openai:" + deprecatedInvocation,
		InvocationName:    deprecatedInvocation,
		ProviderModelName: deprecatedInvocation,
		ModelType:         StringList{"text_generate"},
		DisplayName:       "Deprecated Model",
		Status:            "deprecated",
	})
	if err != nil {
		t.Fatalf("create deprecated base model: %v", err)
	}
	defer func() {
		_, _ = db.pool.Exec(ctx, `DELETE FROM base_model_catalog WHERE id = $1::uuid`, deprecatedBase.ID)
	}()
	if _, err := db.CreatePlatformModel(ctx, CreatePlatformModelInput{
		PlatformID:        platformID,
		BaseModelID:       deprecatedBase.ID,
		ModelName:         deprecatedInvocation,
		ProviderModelName: deprecatedInvocation,
		ModelType:         StringList{"text_generate"},
	}); !errors.Is(err, ErrInvalidPlatformModelConfiguration) {
		t.Fatalf("deprecated base model must reject new bindings: %v", err)
	}
}
