package pressure

import (
	"fmt"
	"slices"
	"strings"

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

const (
	LevelHigh     = "high"
	LevelModerate = "moderate"
	LevelUnknown  = "unknown"
)

// Report describes expected local pressure for a session without mutating the
// host. It combines the declared service graph with measured cp9 persona
// benchmarks when the persona is known.
type Report struct {
	Persona         string          `json:"persona"`
	Level           string          `json:"level"`
	Summary         string          `json:"summary"`
	LocalBenchmark  *LocalBenchmark `json:"local_benchmark,omitempty"`
	Recommendations []string        `json:"recommendations,omitempty"`
}

type LocalBenchmark struct {
	Source              string  `json:"source"`
	PeakCPUPercent      float64 `json:"peak_cpu_percent"`
	PeakMemoryGiB       float64 `json:"peak_memory_gib"`
	SteadyCPUPercent    float64 `json:"steady_cpu_percent"`
	SteadyMemoryGiB     float64 `json:"steady_memory_gib"`
	SampleCount         int     `json:"sample_count"`
	MeasuredAtUTC       string  `json:"measured_at_utc"`
	MeasuredHostSummary string  `json:"measured_host_summary"`
}

type personaPressurePolicy struct {
	Level           string
	SummaryTemplate string
	Benchmark       LocalBenchmark
	Recommendations []string
}

var personaPressurePolicies = map[string]personaPressurePolicy{
	"dev-full": {
		Level:           LevelHigh,
		SummaryTemplate: "dev-full is high-pressure on local Docker/k3d: measured peak %.0f%% CPU / %.1fGiB and steady %.0f%% CPU / %.1fGiB",
		Benchmark: LocalBenchmark{
			Source:              "issue #275 local Docker/k3d dogfood measurement",
			PeakCPUPercent:      394.66,
			PeakMemoryGiB:       8.103,
			SteadyCPUPercent:    285.06,
			SteadyMemoryGiB:     7.422,
			SampleCount:         57,
			MeasuredAtUTC:       "2026-05-29",
			MeasuredHostSummary: "reference Apple Silicon Docker Desktop dogfood host",
		},
		Recommendations: []string{
			"Premium is full-mode only; use a larger Docker budget or remote/large-host runner for daily work",
			"prefer ec2-k3d or a large local Docker budget for full Premium dataplane dogfood",
			"when tuning, start with Crossplane/provider footprint and unbounded local services before shrinking dataplane behavior blindly",
		},
	},
}

// Build returns a local pressure report for the resolved v1alpha2 session.
func Build(session *config.SessionConfig) Report {
	if session == nil {
		return Report{
			Level:   LevelUnknown,
			Summary: "session config unavailable; local pressure cannot be estimated",
		}
	}

	report := Report{
		Persona: config.SessionPersona(session),
	}
	report.LocalBenchmark = benchmarkForPersona(report.Persona)
	report.Level, report.Summary = summarize(&report)
	report.Recommendations = recommendations(&report)
	return report
}

func benchmarkForPersona(persona string) *LocalBenchmark {
	policy, ok := pressurePolicyForPersona(persona)
	if !ok {
		return nil
	}
	benchmark := policy.Benchmark
	return &benchmark
}

func pressurePolicyForPersona(persona string) (personaPressurePolicy, bool) {
	policy, ok := personaPressurePolicies[strings.TrimSpace(persona)]
	return policy, ok
}

func summarize(report *Report) (level, summary string) {
	if report == nil {
		return LevelUnknown, "session config unavailable; local pressure cannot be estimated"
	}
	if report.LocalBenchmark == nil {
		return LevelUnknown, fmt.Sprintf(
			"no measured local pressure baseline for %q; record one before cp9 up",
			report.Persona,
		)
	}
	policy, ok := pressurePolicyForPersona(report.Persona)
	if !ok {
		return LevelUnknown, fmt.Sprintf("measured baseline exists for %q but no pressure policy is defined", report.Persona)
	}
	return policy.Level, fmt.Sprintf(
		policy.SummaryTemplate,
		report.LocalBenchmark.PeakCPUPercent,
		report.LocalBenchmark.PeakMemoryGiB,
		report.LocalBenchmark.SteadyCPUPercent,
		report.LocalBenchmark.SteadyMemoryGiB,
	)
}

func recommendations(report *Report) []string {
	if report == nil {
		return nil
	}
	policy, ok := pressurePolicyForPersona(report.Persona)
	if !ok {
		return []string{"run cp9 up dry-run on a known persona or record a new local benchmark before assuming laptop fit"}
	}
	return slices.Clone(policy.Recommendations)
}

// FormatDetails renders report details for command text output.
func FormatDetails(report *Report) string {
	if report == nil {
		return ""
	}
	var b strings.Builder
	if report.Summary != "" {
		fmt.Fprintf(&b, "%s\n", report.Summary)
	}
	if report.LocalBenchmark != nil {
		bench := report.LocalBenchmark
		fmt.Fprintf(&b,
			"measured: peak=%.0f%% CPU / %.1fGiB, steady=%.0f%% CPU / %.1fGiB, samples=%d, source=%s\n",
			bench.PeakCPUPercent,
			bench.PeakMemoryGiB,
			bench.SteadyCPUPercent,
			bench.SteadyMemoryGiB,
			bench.SampleCount,
			bench.Source,
		)
	}
	if len(report.Recommendations) > 0 {
		fmt.Fprintf(&b, "recommendations:\n")
		for _, recommendation := range report.Recommendations {
			fmt.Fprintf(&b, "  - %s\n", recommendation)
		}
	}
	return strings.TrimRight(b.String(), "\n")
}
