package extension

import (
	"context"
	"testing"
	"time"

	"github.com/stretchr/testify/require"
)

func TestWriteInvocationAuditPersistsOnlySecretFreeFields(t *testing.T) {
	ctx := context.Background()
	db := startRollbackDB(t, ctx)
	now := time.Date(2026, 8, 11, 6, 0, 0, 123000000, time.UTC)
	fixture := seedExtensionStoreFixture(t, db, "audit", now)
	seedExtensionStoreAgent(t, db, fixture.WorkspaceID, fixture.UserID, "agt_audit", now)
	store := New(db)
	digest := "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
	requestHash := "sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"

	require.NoError(t, store.WriteInvocationAudit(ctx, InvocationAudit{
		ID: "extaudit_1", WorkspaceID: fixture.WorkspaceID, AgentID: "agt_audit",
		ServiceInstallationExtensionID: "svcinstext_github",
		ExtensionName:                  "github-main",
		Domain:                         "github",
		Action:                         "create-issue",
		DefinitionVersion:              1, DefinitionDigest: digest, CatalogVersion: 7,
		RequestHash: requestHash, ExecutionStatusClass: "2xx",
		ResultClassification: "success", Latency: 1250 * time.Millisecond,
		RequestBytes: 123, ResponseBytes: 456, OccurredAt: now,
	}))

	var selectionID, extensionName, domain, action, storedDigest, storedHash, statusClass, result string
	var definitionVersion, catalogVersion, latencyMS, requestBytes, responseBytes int64
	var occurredAt time.Time
	require.NoError(t, db.QueryRow(ctx, `
SELECT service_installation_extension_id, extension_name, domain, action,
       definition_version,
       definition_digest, catalog_version, request_hash,
       execution_status_class, result_classification, latency_ms,
       request_bytes, response_bytes, occurred_at
FROM extension_invocation_audits
WHERE id = $1`, "extaudit_1").Scan(
		&selectionID, &extensionName, &domain, &action, &definitionVersion,
		&storedDigest, &catalogVersion, &storedHash,
		&statusClass, &result, &latencyMS,
		&requestBytes, &responseBytes, &occurredAt,
	))
	require.Equal(t, "svcinstext_github", selectionID)
	require.Equal(t, "github-main", extensionName)
	require.Equal(t, "github", domain)
	require.Equal(t, "create-issue", action)
	require.Equal(t, int64(1), definitionVersion)
	require.Equal(t, digest, storedDigest)
	require.Equal(t, int64(7), catalogVersion)
	require.Equal(t, requestHash, storedHash)
	require.Equal(t, "2xx", statusClass)
	require.Equal(t, "success", result)
	require.Equal(t, int64(1250), latencyMS)
	require.Equal(t, int64(123), requestBytes)
	require.Equal(t, int64(456), responseBytes)
	require.WithinDuration(t, now, occurredAt, time.Microsecond)
}

func TestInvocationAuditTypeAndSchemaHaveNoSecretBearingFields(t *testing.T) {
	ctx := context.Background()
	db := startRollbackDB(t, ctx)
	rows, err := db.Query(ctx, `
SELECT column_name
FROM information_schema.columns
WHERE table_schema = DATABASE()
  AND table_name = 'extension_invocation_audits'
ORDER BY ordinal_position`)
	require.NoError(t, err)
	defer rows.Close()
	var columns []string
	for rows.Next() {
		var column string
		require.NoError(t, rows.Scan(&column))
		columns = append(columns, column)
	}
	require.NoError(t, rows.Err())
	require.NotContains(t, columns, "url")
	require.NotContains(t, columns, "query")
	require.NotContains(t, columns, "headers")
	require.NotContains(t, columns, "request_body")
	require.NotContains(t, columns, "response_body")
	require.NotContains(t, columns, "credentials")
	require.NotContains(t, columns, "connection_id")
	require.NotContains(t, columns, "grant_id")
}

func TestWriteInvocationAuditReplayPreservesFirstFact(t *testing.T) {
	ctx := context.Background()
	db := startRollbackDB(t, ctx)
	now := time.Date(2026, 8, 16, 2, 40, 0, 0, time.UTC)
	fixture := seedExtensionStoreFixture(t, db, "audit_replay", now)
	seedExtensionStoreAgent(
		t,
		db,
		fixture.WorkspaceID,
		fixture.UserID,
		"agt_audit_replay",
		now,
	)
	store := New(db)
	base := InvocationAudit{
		ID:                             "extaudit_receipt_stable",
		WorkspaceID:                    fixture.WorkspaceID,
		AgentID:                        "agt_audit_replay",
		ServiceInstallationExtensionID: "svcinstext_github",
		ExtensionName:                  "github-main",
		Domain:                         "mail",
		Action:                         "send-draft",
		DefinitionVersion:              1,
		DefinitionDigest: "sha256:" +
			"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
		CatalogVersion:       7,
		RequestHash:          "sha256:" + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
		ExecutionStatusClass: "accepted",
		ResultClassification: "smtp_accepted",
		Latency:              time.Second,
		RequestBytes:         11,
		ResponseBytes:        12,
		OccurredAt:           now,
	}
	require.NoError(t, store.WriteInvocationAuditOnce(ctx, base))

	replay := base
	replay.ExecutionStatusClass = "unknown"
	replay.ResultClassification = "smtp_unknown"
	replay.Latency = 0
	replay.RequestBytes = 0
	replay.ResponseBytes = 0
	replay.OccurredAt = now.Add(time.Minute)
	require.NoError(t, store.WriteInvocationAuditOnce(ctx, replay))

	var count int
	var status, result string
	var occurredAt time.Time
	require.NoError(t, db.QueryRow(ctx, `
SELECT COUNT(*), MIN(execution_status_class),
       MIN(result_classification), MIN(occurred_at)
FROM extension_invocation_audits
WHERE id = $1`, base.ID).Scan(
		&count,
		&status,
		&result,
		&occurredAt,
	))
	require.Equal(t, 1, count)
	require.Equal(t, "accepted", status)
	require.Equal(t, "smtp_accepted", result)
	require.WithinDuration(t, now, occurredAt, time.Microsecond)
}
