//go:build integration

package cmd

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"testing"
	"time"

	"github.com/tidbcloud/controlplane9/internal/cluster"
)

func TestIntegration_StatusProjectsO11YProofLayers(t *testing.T) {
	repo := t.TempDir()
	stateDir := filepath.Join(repo, ".cp9", "o11y-status-proof")
	state := cluster.NewState("o11y-status-proof", "session-id")
	state.Persona = "dev-full"
	evidenceDir := filepath.Join(stateDir, "tilt", "reports", "evidence")
	writeStatusO11YTestJSON(t, filepath.Join(evidenceDir, "o11y-platform-readiness.json"), `{
  "status":"passed",
  "cluster_status":"ACTIVE",
	"cluster_id":"cluster-id",
	"active_clusters_before_gateway":1,
	"cleanup_pending":true,
  "vmcluster":"operational",
  "vm_account_id":"vm-account",
  "vm_project_id":"vm-project",
  "dns_name":"o11y.internal",
  "endpoint_service_name":"com.amazonaws.vpce.us-west-2.vpce-svc-example"
}`)
	writeStatusO11YTestJSON(t, filepath.Join(evidenceDir, "o11y-gateway-readiness.json"), `{
  "status":"passed",
  "global_api_status":200,
  "metrics_write_status":204,
  "metrics_query_status":200,
  "metrics_marker":"cp9_o11y_gateway_ready",
  "private_write_public_alb_status":404,
  "private_write_public_nlb_status":404,
  "active_clusters_after_delete":0
}`)
	writeStatusO11YProductSummary(t, repo, "starter-openapi", "run-1", "o11y-status-proof", state.CreatedAt, "starter", "passed")
	writeStatusO11YTestJSON(t, filepath.Join(repo, "artifacts", "dedicated-openapi", "wrong-session", "summary.json"), `{
	  "cp9Session":"o11y-status-proof",
	  "cp9CreatedAt":"2020-01-01T00:00:00Z",
  "group":"Dedicated OpenAPI",
  "o11y":{"product":"dedicated","status":"passed"}
}`)

	result := cluster.BuildStatus(state)
	result.Layers = statusLayersFromState(context.Background(), stateDir, state, result)

	o11y := result.Layers.O11Y
	if o11y == nil {
		t.Fatal("layers.o11y is nil")
	}
	if got, want := o11y.Status, "partial"; got != want {
		t.Fatalf("layers.o11y.status = %q, want %q", got, want)
	}
	if got := o11y.Platform.Status; got != "passed" {
		t.Fatalf("platform status = %q, want passed", got)
	}
	if got := o11y.RoutingMapping["shared"].Status; got != "passed" {
		t.Fatalf("routing/mapping status = %q, want passed", got)
	}
	if got := o11y.MetricsWriteQuery["shared"].Status; got != "passed" {
		t.Fatalf("shared metrics status = %q, want passed", got)
	}
	if got := o11y.PublicWriteNegative.Status; got != "passed" {
		t.Fatalf("public-write negative status = %q, want passed", got)
	}
	if got := o11y.ACS["starter"].Status; got != "passed" {
		t.Fatalf("Starter ACS status = %q, want passed", got)
	}
	if got := o11y.RoutingMapping["starter"].Status; got != "passed" {
		t.Fatalf("Starter routing/mapping status = %q, want passed", got)
	}
	if got := o11y.AgentCR["starter"].Status; got != "passed" {
		t.Fatalf("Starter Agent CR status = %q, want passed", got)
	}
	if got := o11y.AgentWorkload["starter"].Status; got != "passed" {
		t.Fatalf("Starter workload status = %q, want passed", got)
	}
	if got := o11y.MetricsWriteQuery["starter"].Status; got != "passed" {
		t.Fatalf("Starter metrics status = %q, want passed", got)
	}
	if got := o11y.NamespaceNegative["starter"].Status; got != "passed" {
		t.Fatalf("Starter namespace negative status = %q, want passed", got)
	}
	if got := o11y.Idempotency["starter"].Status; got != "passed" {
		t.Fatalf("Starter idempotency status = %q, want passed", got)
	}
	if got := o11y.InterruptedRecovery["starter"].Status; got != "passed" {
		t.Fatalf("Starter interrupted recovery status = %q, want passed", got)
	}
	if got := o11y.Cleanup["starter"].Status; got != "passed" {
		t.Fatalf("Starter cleanup status = %q, want passed", got)
	}
	if _, ok := o11y.ACS["dedicated"]; ok {
		t.Fatal("wrong-session Dedicated evidence was projected")
	}
	if got, want := o11y.LogsBackend, "not_deployed"; got != want {
		t.Fatalf("logs backend = %q, want %q", got, want)
	}

	text := result.FormatText()
	for _, want := range []string{
		"O11Y:     partial",
		"platform=passed",
		"routing_mapping=shared:passed,starter:passed",
		"acs=starter:passed",
		"agent_cr=starter:passed",
		"agent_workload=starter:passed",
		"metrics_write_query=shared:passed,starter:passed",
		"namespace_negative=starter:passed",
		"public_write_negative=passed",
		"interrupted_recovery=starter:passed",
		"idempotency=starter:passed",
		"cleanup=shared:passed,starter:passed",
		"logs_backend=not_deployed",
		"alerts=not_deployed",
		"dr_house=not_deployed",
	} {
		if !strings.Contains(text, want) {
			t.Fatalf("status text missing %q:\n%s", want, text)
		}
	}

	writeStatusO11YProductSummary(t, repo, "premium-openapi", "run-2", "o11y-status-proof", state.CreatedAt, "premium", "passed")
	writeStatusO11YProductSummary(t, repo, "premium-openapi", "run-3", "o11y-status-proof", state.CreatedAt, "essential_v2", "passed")
	writeStatusO11YProductSummary(t, repo, "dedicated-openapi", "run-2", "o11y-status-proof", state.CreatedAt, "dedicated", "passed")
	result.Layers = statusLayersFromState(context.Background(), stateDir, state, result)
	if got := result.Layers.O11Y.Status; got != "passed" {
		t.Fatalf("complete layers.o11y.status = %q, want passed", got)
	}
	if got := result.Layers.O11Y.AgentCR["essential_v2"].Status; got != "passed" {
		t.Fatalf("Essential V2 Agent CR status = %q, want passed", got)
	}
	writeStatusO11YProductSummary(t, repo, "starter-openapi", "run-8", "o11y-status-proof", state.CreatedAt, "starter", "failed")
	result.Layers = statusLayersFromState(context.Background(), stateDir, state, result)
	if got := result.Layers.O11Y.ACS["starter"].Status; got != "passed" {
		t.Fatalf("Starter ACS status after cleanup failure = %q, want passed", got)
	}
	if got := result.Layers.O11Y.Cleanup["starter"].Status; got != "failed" {
		t.Fatalf("Starter cleanup status = %q, want failed", got)
	}

	malformedPath := filepath.Join(repo, "artifacts", "starter-openapi", "run-9", "summary.json")
	writeStatusO11YTestJSON(t, malformedPath, `{
	  "cp9Session":"o11y-status-proof",
	  "cp9CreatedAt":`+fmt.Sprintf("%q", state.CreatedAt.Format(time.RFC3339Nano))+`,
	  "o11y":{"product":"starter","status":"passed","acs":"broken"}
	}`)
	future := time.Now().Add(time.Second)
	if err := os.Chtimes(malformedPath, future, future); err != nil {
		t.Fatal(err)
	}
	result.Layers = statusLayersFromState(context.Background(), stateDir, state, result)
	if got := result.Layers.O11Y.ACS["starter"].Status; got != "invalid" {
		t.Fatalf("newest malformed Starter ACS status = %q, want invalid", got)
	}
}

func TestIntegration_StatusFailsClosedOnMalformedO11YSummary(t *testing.T) {
	repo := t.TempDir()
	stateDir := filepath.Join(repo, ".cp9", "o11y-status-proof")
	state := cluster.NewState("o11y-status-proof", "session-id")
	state.Persona = "dev-full"
	writeStatusO11YProductSummary(t, repo, "starter-openapi", "run-1", state.SessionName, state.CreatedAt, "starter", "passed")

	result := cluster.BuildStatus(state)
	result.Layers = statusLayersFromState(context.Background(), stateDir, state, result)
	if got := result.Layers.O11Y.ACS["starter"].Status; got != "passed" {
		t.Fatalf("Starter ACS status = %q, want passed", got)
	}

	malformedPath := filepath.Join(repo, "artifacts", "starter-openapi", "run-2", "summary.json")
	writeStatusO11YTestJSON(t, malformedPath, `{`)
	future := time.Now().Add(time.Second)
	if err := os.Chtimes(malformedPath, future, future); err != nil {
		t.Fatal(err)
	}
	result.Layers = statusLayersFromState(context.Background(), stateDir, state, result)
	if got := result.Layers.O11Y.Status; got != "failed" {
		t.Fatalf("status with newest malformed summary = %q, want failed", got)
	}
}

func writeStatusO11YProductSummary(t *testing.T, repo, artifact, run, session string, createdAt time.Time, product, cleanupStatus string) {
	t.Helper()
	runDir := filepath.Join(repo, "artifacts", artifact, run)
	writeStatusO11YTestJSON(t, filepath.Join(runDir, "o11y-readback.json"), `{"status":"passed"}`)
	writeStatusO11YTestJSON(t, filepath.Join(runDir, "summary.json"), fmt.Sprintf(`{
  "cp9Session":%q,
	"cp9CreatedAt":%q,
  "o11y":{
    "product":%q,
	"status":%q,
	"routingMapping":{"status":"passed","evidencePath":"o11y-readback.json"},
	"acs":{"status":"passed","evidencePath":"o11y-readback.json"},
	"agentCR":{"status":"passed","evidencePath":"o11y-readback.json"},
	"agentWorkload":{"status":"passed","evidencePath":"o11y-readback.json"},
	"metricsWriteQuery":{"status":"passed","evidencePath":"o11y-readback.json"},
	"namespaceNegative":{"status":"passed","evidencePath":"o11y-readback.json"},
	"interruptedRecovery":{"status":"passed","evidencePath":"o11y-readback.json"},
	"idempotency":{"status":"passed","evidencePath":"o11y-readback.json"},
	"cleanup":{
	  "status":%q,
	  "evidencePath":"o11y-readback.json",
	  %s
	},
    "logsBackend":"not_deployed",
    "alerts":"not_deployed",
    "drHouse":"not_deployed"
  }
}`, session, createdAt.Format(time.RFC3339Nano), product, cleanupStatus, cleanupStatus, statusO11YCleanupTestJSON(product)))
}

func statusO11YCleanupTestJSON(product string) string {
	if product == "starter" {
		return `"agentCRsAfterDelete":2,"agentWorkloadsAfterDelete":25,"mappingsAfterDelete":1`
	}
	return `"agentCRsAfterDelete":0,"agentWorkloadsAfterDelete":0,"mappingsAfterDelete":0`
}

func writeStatusO11YTestJSON(t *testing.T, path, data string) {
	t.Helper()
	if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(path, []byte(data), 0o600); err != nil {
		t.Fatal(err)
	}
}
