//nolint:gosec
package main

import (
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"

	"github.com/Wikid82/charon/backend/internal/patchreport"
)

func TestMainProcessHelper(t *testing.T) {
	t.Helper()
	if os.Getenv("GO_WANT_HELPER_PROCESS") != "1" {
		return
	}

	separatorIndex := -1
	for index, arg := range os.Args {
		if arg == "--" {
			separatorIndex = index
			break
		}
	}
	if separatorIndex == -1 {
		os.Exit(2)
	}

	os.Args = append([]string{os.Args[0]}, os.Args[separatorIndex+1:]...)
	flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
	main()
	os.Exit(0)
}

func TestMain_SuccessWritesReports(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "reports", "local-patch.json")
	mdOut := filepath.Join(repoRoot, "reports", "local-patch.md")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-backend-coverage", "backend/coverage.txt",
		"-frontend-coverage", "frontend/coverage/lcov.info",
		"-json-out", jsonOut,
		"-md-out", mdOut,
	)

	if result.exitCode != 0 {
		t.Fatalf("expected success exit code 0, got %d, stderr=%s", result.exitCode, result.stderr)
	}

	if _, err := os.Stat(jsonOut); err != nil {
		t.Fatalf("expected json report to exist: %v", err)
	}
	if _, err := os.Stat(mdOut); err != nil {
		t.Fatalf("expected markdown report to exist: %v", err)
	}

	// #nosec G304 -- Test reads artifact path created by this test.
	reportBytes, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json report: %v", err)
	}

	var report reportJSON
	if err := json.Unmarshal(reportBytes, &report); err != nil {
		t.Fatalf("unmarshal report: %v", err)
	}
	if report.Mode != "warn" {
		t.Fatalf("unexpected mode: %s", report.Mode)
	}
	if report.Artifacts.JSON == "" || report.Artifacts.Markdown == "" {
		t.Fatalf("expected artifacts to be populated: %+v", report.Artifacts)
	}
	if !strings.Contains(result.stdout, "Local patch report generated") {
		t.Fatalf("expected success output, got: %s", result.stdout)
	}
}

func TestMain_FailsWhenBackendCoverageIsMissing(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.Remove(filepath.Join(repoRoot, "backend", "coverage.txt")); err != nil {
		t.Fatalf("remove backend coverage: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)

	if result.exitCode == 0 {
		t.Fatalf("expected non-zero exit code for missing backend coverage")
	}
	if !strings.Contains(result.stderr, "missing backend coverage file") {
		t.Fatalf("expected missing backend coverage error, stderr=%s", result.stderr)
	}
}

func TestMain_FailsWhenGitBaselineIsInvalid(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "this-is-not-a-valid-revision",
	)

	if result.exitCode == 0 {
		t.Fatalf("expected non-zero exit code for invalid baseline")
	}
	if !strings.Contains(result.stderr, "error generating git diff") {
		t.Fatalf("expected git diff error, stderr=%s", result.stderr)
	}
}

func TestMain_FailsWhenBackendCoverageParseErrors(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	backendCoverage := filepath.Join(repoRoot, "backend", "coverage.txt")

	tooLongLine := strings.Repeat("a", 3*1024*1024)
	if err := os.WriteFile(backendCoverage, []byte("mode: atomic\n"+tooLongLine+"\n"), 0o600); err != nil {
		t.Fatalf("write backend coverage: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)

	if result.exitCode == 0 {
		t.Fatalf("expected non-zero exit code for backend parse error")
	}
	if !strings.Contains(result.stderr, "error parsing backend coverage") {
		t.Fatalf("expected backend parse error, stderr=%s", result.stderr)
	}
}

func TestMain_FailsWhenFrontendCoverageParseErrors(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	frontendCoverage := filepath.Join(repoRoot, "frontend", "coverage", "lcov.info")

	tooLongLine := strings.Repeat("b", 3*1024*1024)
	if err := os.WriteFile(frontendCoverage, []byte("TN:\nSF:frontend/src/file.ts\nDA:1,1\n"+tooLongLine+"\n"), 0o600); err != nil {
		t.Fatalf("write frontend coverage: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)

	if result.exitCode == 0 {
		t.Fatalf("expected non-zero exit code for frontend parse error")
	}
	if !strings.Contains(result.stderr, "error parsing frontend coverage") {
		t.Fatalf("expected frontend parse error, stderr=%s", result.stderr)
	}
}

func TestMain_FailsWhenJSONOutputCannotBeWritten(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonDir := filepath.Join(repoRoot, "locked-json-dir")
	if err := os.MkdirAll(jsonDir, 0o750); err != nil {
		t.Fatalf("create json dir: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonDir,
	)

	if result.exitCode == 0 {
		t.Fatalf("expected non-zero exit code when json output path is a directory")
	}
	if !strings.Contains(result.stderr, "error writing json report") {
		t.Fatalf("expected json write error, stderr=%s", result.stderr)
	}
}

func TestResolvePathAndRelOrAbs(t *testing.T) {
	repoRoot := t.TempDir()
	absolute := filepath.Join(repoRoot, "absolute.txt")
	if got := resolvePath(repoRoot, absolute); got != absolute {
		t.Fatalf("expected absolute path unchanged, got %s", got)
	}

	relative := "nested/file.txt"
	expected := filepath.Join(repoRoot, relative)
	if got := resolvePath(repoRoot, relative); got != expected {
		t.Fatalf("expected joined path %s, got %s", expected, got)
	}

	if got := relOrAbs(repoRoot, expected); got != "nested/file.txt" {
		t.Fatalf("expected repo-relative path, got %s", got)
	}
}

func TestAssertFileExists(t *testing.T) {
	tempDir := t.TempDir()
	filePath := filepath.Join(tempDir, "ok.txt")
	if err := os.WriteFile(filePath, []byte("ok"), 0o600); err != nil {
		t.Fatalf("write file: %v", err)
	}

	if err := assertFileExists(filePath, "test file"); err != nil {
		t.Fatalf("expected existing file to pass: %v", err)
	}

	err := assertFileExists(filepath.Join(tempDir, "missing.txt"), "missing file")
	if err == nil || !strings.Contains(err.Error(), "missing missing file") {
		t.Fatalf("expected missing file error, got: %v", err)
	}

	err = assertFileExists(tempDir, "directory input")
	if err == nil || !strings.Contains(err.Error(), "found directory") {
		t.Fatalf("expected directory error, got: %v", err)
	}
}

func TestGitDiffAndWriters(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	diffContent, err := gitDiff(repoRoot, "HEAD...HEAD")
	if err != nil {
		t.Fatalf("gitDiff should succeed for HEAD...HEAD: %v", err)
	}
	if diffContent != "" {
		t.Fatalf("expected empty diff for HEAD...HEAD, got: %q", diffContent)
	}

	_, err = gitDiff(repoRoot, "bad-baseline")
	if err == nil {
		t.Fatal("expected gitDiff failure for invalid baseline")
	}

	report := reportJSON{
		Baseline:    "origin/development...HEAD",
		GeneratedAt: "2026-02-17T00:00:00Z",
		Mode:        "warn",
		Thresholds:  thresholdJSON{Overall: 90, Backend: 85, Frontend: 85},
		ThresholdSources: thresholdSourcesJSON{
			Overall:  "default",
			Backend:  "default",
			Frontend: "default",
		},
		Overall:  patchreport.ScopeCoverage{ChangedLines: 10, CoveredLines: 5, PatchCoveragePct: 50, Status: "warn"},
		Backend:  patchreport.ScopeCoverage{ChangedLines: 6, CoveredLines: 2, PatchCoveragePct: 33.3, Status: "warn"},
		Frontend: patchreport.ScopeCoverage{ChangedLines: 4, CoveredLines: 3, PatchCoveragePct: 75, Status: "warn"},
		FilesNeedingCoverage: []patchreport.FileCoverageDetail{{
			Path:                      "backend/cmd/localpatchreport/main.go",
			PatchCoveragePct:          0,
			UncoveredChangedLines:     2,
			UncoveredChangedLineRange: []string{"10-11"},
		}},
		Warnings:  []string{"warning one"},
		Artifacts: artifactsJSON{Markdown: "test-results/report.md", JSON: "test-results/report.json"},
	}

	jsonPath := filepath.Join(t.TempDir(), "report.json")
	err = writeJSON(jsonPath, report)
	if err != nil {
		t.Fatalf("writeJSON should succeed: %v", err)
	}
	// #nosec G304 -- Test reads artifact path created by this test.
	jsonBytes, err := os.ReadFile(jsonPath)
	if err != nil {
		t.Fatalf("read json file: %v", err)
	}
	if !strings.Contains(string(jsonBytes), "\"baseline\": \"origin/development...HEAD\"") {
		t.Fatalf("unexpected json content: %s", string(jsonBytes))
	}

	markdownPath := filepath.Join(t.TempDir(), "report.md")
	err = writeMarkdown(markdownPath, report, "backend/coverage.txt", "frontend/coverage/lcov.info")
	if err != nil {
		t.Fatalf("writeMarkdown should succeed: %v", err)
	}
	// #nosec G304 -- Test reads artifact path created by this test.
	markdownBytes, err := os.ReadFile(markdownPath)
	if err != nil {
		t.Fatalf("read markdown file: %v", err)
	}
	markdown := string(markdownBytes)
	if !strings.Contains(markdown, "## Files Needing Coverage") {
		t.Fatalf("expected files section in markdown: %s", markdown)
	}
	if !strings.Contains(markdown, "## Warnings") {
		t.Fatalf("expected warnings section in markdown: %s", markdown)
	}

	scope := patchreport.ScopeCoverage{ChangedLines: 3, CoveredLines: 2, PatchCoveragePct: 66.7, Status: "warn"}
	row := scopeRow("Backend", scope)
	if !strings.Contains(row, "| Backend | 3 | 2 | 66.7 | warn |") {
		t.Fatalf("unexpected scope row: %s", row)
	}
}

func runMainSubprocess(t *testing.T, args ...string) subprocessResult {
	t.Helper()

	commandArgs := append([]string{"-test.run=TestMainProcessHelper", "--"}, args...)
	// #nosec G204 -- Test helper subprocess invocation with controlled arguments.
	cmd := exec.Command(os.Args[0], commandArgs...)
	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")

	stdout, err := cmd.Output()
	if err == nil {
		return subprocessResult{exitCode: 0, stdout: string(stdout), stderr: ""}
	}

	var exitError *exec.ExitError
	if errors.As(err, &exitError) {
		return subprocessResult{exitCode: exitError.ExitCode(), stdout: string(stdout), stderr: string(exitError.Stderr)}
	}

	t.Fatalf("unexpected subprocess failure: %v", err)
	return subprocessResult{}
}

type subprocessResult struct {
	exitCode int
	stdout   string
	stderr   string
}

func createGitRepoWithCoverageInputs(t *testing.T) string {
	t.Helper()

	repoRoot := t.TempDir()
	mustRunCommand(t, repoRoot, "git", "init")
	mustRunCommand(t, repoRoot, "git", "config", "user.email", "test@example.com")
	mustRunCommand(t, repoRoot, "git", "config", "user.name", "Test User")

	paths := []string{
		filepath.Join(repoRoot, "backend", "internal"),
		filepath.Join(repoRoot, "frontend", "src"),
		filepath.Join(repoRoot, "frontend", "coverage"),
		filepath.Join(repoRoot, "backend"),
	}
	for _, path := range paths {
		if err := os.MkdirAll(path, 0o750); err != nil {
			t.Fatalf("mkdir %s: %v", path, err)
		}
	}

	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "internal", "sample.go"), []byte("package internal\nvar Sample = 1\n"), 0o600); err != nil {
		t.Fatalf("write backend sample: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "frontend", "src", "sample.ts"), []byte("export const sample = 1;\n"), 0o600); err != nil {
		t.Fatalf("write frontend sample: %v", err)
	}

	backendCoverage := "mode: atomic\nbackend/internal/sample.go:1.1,2.20 1 1\n"
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte(backendCoverage), 0o600); err != nil {
		t.Fatalf("write backend coverage: %v", err)
	}

	frontendCoverage := "TN:\nSF:frontend/src/sample.ts\nDA:1,1\nend_of_record\n"
	if err := os.WriteFile(filepath.Join(repoRoot, "frontend", "coverage", "lcov.info"), []byte(frontendCoverage), 0o600); err != nil {
		t.Fatalf("write frontend coverage: %v", err)
	}

	mustRunCommand(t, repoRoot, "git", "add", ".")
	mustRunCommand(t, repoRoot, "git", "commit", "-m", "initial commit")

	return repoRoot
}

func mustRunCommand(t *testing.T, dir string, name string, args ...string) {
	t.Helper()
	// #nosec G204 -- Test helper executes deterministic local commands.
	cmd := exec.Command(name, args...)
	cmd.Dir = dir
	output, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("command %s %s failed: %v\n%s", name, strings.Join(args, " "), err, string(output))
	}
}

func TestWriteJSONReturnsErrorWhenPathIsDirectory(t *testing.T) {
	dir := t.TempDir()
	report := reportJSON{Baseline: "x", GeneratedAt: "y", Mode: "warn"}
	if err := writeJSON(dir, report); err == nil {
		t.Fatal("expected writeJSON to fail when target is a directory")
	}
}

func TestWriteMarkdownReturnsErrorWhenPathIsDirectory(t *testing.T) {
	dir := t.TempDir()
	report := reportJSON{
		Baseline:             "origin/development...HEAD",
		GeneratedAt:          "2026-02-17T00:00:00Z",
		Mode:                 "warn",
		Thresholds:           thresholdJSON{Overall: 90, Backend: 85, Frontend: 85},
		ThresholdSources:     thresholdSourcesJSON{Overall: "default", Backend: "default", Frontend: "default"},
		Overall:              patchreport.ScopeCoverage{Status: "pass"},
		Backend:              patchreport.ScopeCoverage{Status: "pass"},
		Frontend:             patchreport.ScopeCoverage{Status: "pass"},
		FilesNeedingCoverage: nil,
		Warnings:             nil,
		Artifacts:            artifactsJSON{Markdown: "a", JSON: "b"},
	}
	if err := writeMarkdown(dir, report, "backend/coverage.txt", "frontend/coverage/lcov.info"); err == nil {
		t.Fatal("expected writeMarkdown to fail when target is a directory")
	}
}

func TestMain_FailsWhenMarkdownDirectoryCreationFails(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	lockedParent := filepath.Join(repoRoot, "md-root")
	if err := os.WriteFile(lockedParent, []byte("file-not-dir"), 0o600); err != nil {
		t.Fatalf("write locked parent file: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-md-out", filepath.Join(lockedParent, "report.md"),
	)

	if result.exitCode == 0 {
		t.Fatalf("expected markdown directory creation failure")
	}
	if !strings.Contains(result.stderr, "error creating markdown output directory") {
		t.Fatalf("expected markdown mkdir error, stderr=%s", result.stderr)
	}
}

func TestMain_FailsWhenJSONDirectoryCreationFails(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	lockedParent := filepath.Join(repoRoot, "json-root")
	if err := os.WriteFile(lockedParent, []byte("file-not-dir"), 0o600); err != nil {
		t.Fatalf("write locked parent file: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", filepath.Join(lockedParent, "report.json"),
	)

	if result.exitCode == 0 {
		t.Fatalf("expected json directory creation failure")
	}
	if !strings.Contains(result.stderr, "error creating json output directory") {
		t.Fatalf("expected json mkdir error, stderr=%s", result.stderr)
	}
}

func TestMain_PrintsWarningsWhenThresholdsNotMet(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "internal", "sample.go"), []byte("package internal\nvar Sample = 2\n"), 0o600); err != nil {
		t.Fatalf("update backend sample: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "frontend", "src", "sample.ts"), []byte("export const sample = 2;\n"), 0o600); err != nil {
		t.Fatalf("update frontend sample: %v", err)
	}

	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte("mode: atomic\nbackend/internal/sample.go:1.1,2.20 1 0\n"), 0o600); err != nil {
		t.Fatalf("write backend uncovered coverage: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "frontend", "coverage", "lcov.info"), []byte("TN:\nSF:frontend/src/sample.ts\nDA:1,0\nend_of_record\n"), 0o600); err != nil {
		t.Fatalf("write frontend uncovered coverage: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD",
	)

	if result.exitCode != 0 {
		t.Fatalf("expected success with warnings, got exit=%d stderr=%s", result.exitCode, result.stderr)
	}
	if !strings.Contains(result.stdout, "WARN: Overall patch coverage") {
		t.Fatalf("expected WARN output, stdout=%s", result.stdout)
	}
}

func TestRelOrAbsConvertsSlashes(t *testing.T) {
	repoRoot := t.TempDir()
	targetPath := filepath.Join(repoRoot, "reports", "file.json")

	got := relOrAbs(repoRoot, targetPath)
	if got != "reports/file.json" {
		t.Fatalf("expected slash-normalized relative path, got %s", got)
	}
}

func TestHelperCommandFailureHasContext(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	_, err := gitDiff(repoRoot, "definitely-invalid")
	if err == nil {
		t.Fatal("expected gitDiff error")
	}
	if !strings.Contains(err.Error(), "git diff definitely-invalid failed") {
		t.Fatalf("expected contextual error message, got %v", err)
	}
}

func TestMain_FailsWhenMarkdownWriteFails(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	mdDir := filepath.Join(repoRoot, "md-as-dir")
	if err := os.MkdirAll(mdDir, 0o750); err != nil {
		t.Fatalf("create markdown dir: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-md-out", mdDir,
	)

	if result.exitCode == 0 {
		t.Fatalf("expected markdown write failure")
	}
	if !strings.Contains(result.stderr, "error writing markdown report") {
		t.Fatalf("expected markdown write error, stderr=%s", result.stderr)
	}
}

func TestMain_FailsWhenFrontendCoverageIsMissing(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.Remove(filepath.Join(repoRoot, "frontend", "coverage", "lcov.info")); err != nil {
		t.Fatalf("remove frontend coverage: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)

	if result.exitCode == 0 {
		t.Fatalf("expected non-zero exit code for missing frontend coverage")
	}
	if !strings.Contains(result.stderr, "missing frontend coverage file") {
		t.Fatalf("expected missing frontend coverage error, stderr=%s", result.stderr)
	}
}

func TestMain_FailsWhenRepoRootInvalid(t *testing.T) {
	nonexistentPath := filepath.Join(t.TempDir(), "missing", "repo")

	result := runMainSubprocess(t,
		"-repo-root", nonexistentPath,
		"-baseline", "HEAD...HEAD",
		"-backend-coverage", "backend/coverage.txt",
		"-frontend-coverage", "frontend/coverage/lcov.info",
	)

	if result.exitCode == 0 {
		t.Fatalf("expected non-zero exit code for invalid repo root")
	}
	if !strings.Contains(result.stderr, "missing backend coverage file") {
		t.Fatalf("expected backend missing error for invalid repo root, stderr=%s", result.stderr)
	}
}

func TestMain_WarnsForInvalidThresholdEnv(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	commandArgs := []string{"-test.run=TestMainProcessHelper", "--", "-repo-root", repoRoot, "-baseline", "HEAD...HEAD"}
	// #nosec G204 -- Test helper subprocess invocation with controlled arguments.
	cmd := exec.Command(os.Args[0], commandArgs...)
	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1", "CHARON_OVERALL_PATCH_COVERAGE_MIN=invalid")
	output, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("expected success with warning env, got err=%v output=%s", err, string(output))
	}

	if !strings.Contains(string(output), "WARN: Ignoring invalid CHARON_OVERALL_PATCH_COVERAGE_MIN") {
		t.Fatalf("expected invalid-threshold warning, output=%s", string(output))
	}
}

func TestWriteMarkdownIncludesArtifactsSection(t *testing.T) {
	report := reportJSON{
		Baseline:         "origin/development...HEAD",
		GeneratedAt:      "2026-02-17T00:00:00Z",
		Mode:             "warn",
		Thresholds:       thresholdJSON{Overall: 90, Backend: 85, Frontend: 85},
		ThresholdSources: thresholdSourcesJSON{Overall: "default", Backend: "default", Frontend: "default"},
		Overall:          patchreport.ScopeCoverage{ChangedLines: 1, CoveredLines: 1, PatchCoveragePct: 100, Status: "pass"},
		Backend:          patchreport.ScopeCoverage{ChangedLines: 1, CoveredLines: 1, PatchCoveragePct: 100, Status: "pass"},
		Frontend:         patchreport.ScopeCoverage{ChangedLines: 0, CoveredLines: 0, PatchCoveragePct: 100, Status: "pass"},
		Artifacts:        artifactsJSON{Markdown: "test-results/local-patch-report.md", JSON: "test-results/local-patch-report.json"},
	}

	path := filepath.Join(t.TempDir(), "report.md")
	if err := writeMarkdown(path, report, "backend/coverage.txt", "frontend/coverage/lcov.info"); err != nil {
		t.Fatalf("writeMarkdown: %v", err)
	}

	// #nosec G304 -- Test reads artifact path created by this test.
	body, err := os.ReadFile(path)
	if err != nil {
		t.Fatalf("read markdown: %v", err)
	}
	if !strings.Contains(string(body), "## Artifacts") {
		t.Fatalf("expected artifacts section, got: %s", string(body))
	}
}

func TestRunMainSubprocessReturnsExitCode(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "not-a-revision",
	)

	if result.exitCode == 0 {
		t.Fatalf("expected non-zero exit for invalid baseline")
	}
	if result.stderr == "" {
		t.Fatal("expected stderr to be captured")
	}
}

func TestMustRunCommandHelper(t *testing.T) {
	temp := t.TempDir()
	mustRunCommand(t, temp, "git", "init")

	// #nosec G204 -- Test setup command with fixed arguments.
	configEmail := exec.Command("git", "-C", temp, "config", "user.email", "test@example.com")
	if output, err := configEmail.CombinedOutput(); err != nil {
		t.Fatalf("configure email failed: %v output=%s", err, string(output))
	}
	// #nosec G204 -- Test setup command with fixed arguments.
	configName := exec.Command("git", "-C", temp, "config", "user.name", "Test User")
	if output, err := configName.CombinedOutput(); err != nil {
		t.Fatalf("configure name failed: %v output=%s", err, string(output))
	}

	if err := os.WriteFile(filepath.Join(temp, "README.md"), []byte("content\n"), 0o600); err != nil {
		t.Fatalf("write file: %v", err)
	}

	mustRunCommand(t, temp, "git", "add", ".")
	mustRunCommand(t, temp, "git", "commit", "-m", "test")
}

func TestSubprocessHelperFailsWithoutSeparator(t *testing.T) {
	// #nosec G204 -- Test helper subprocess invocation with fixed arguments.
	cmd := exec.Command(os.Args[0], "-test.run=TestMainProcessHelper")
	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
	_, err := cmd.CombinedOutput()
	if err == nil {
		t.Fatal("expected helper process to fail without separator")
	}
}

func TestScopeRowFormatting(t *testing.T) {
	row := scopeRow("Overall", patchreport.ScopeCoverage{ChangedLines: 10, CoveredLines: 8, PatchCoveragePct: 80.0, Status: "warn"})
	expected := "| Overall | 10 | 8 | 80.0 | warn |\n"
	if row != expected {
		t.Fatalf("unexpected row\nwant: %q\ngot:  %q", expected, row)
	}
}

func TestMainProcessHelperNoopWhenEnvUnset(t *testing.T) {
	if os.Getenv("GO_WANT_HELPER_PROCESS") != "" {
		t.Skip("helper env is set by parent process")
	}
}

func TestRelOrAbsWithNestedPath(t *testing.T) {
	repoRoot := t.TempDir()
	nested := filepath.Join(repoRoot, "a", "b", "c", "report.json")
	if got := relOrAbs(repoRoot, nested); got != "a/b/c/report.json" {
		t.Fatalf("unexpected relative path: %s", got)
	}
}

func TestResolvePathWithAbsoluteInput(t *testing.T) {
	repoRoot := t.TempDir()
	abs := filepath.Join(repoRoot, "direct.txt")
	if resolvePath(repoRoot, abs) != abs {
		t.Fatal("resolvePath should return absolute input unchanged")
	}
}

func TestResolvePathWithRelativeInput(t *testing.T) {
	repoRoot := t.TempDir()
	got := resolvePath(repoRoot, "test-results/out.json")
	expected := filepath.Join(repoRoot, "test-results", "out.json")
	if got != expected {
		t.Fatalf("unexpected resolved path: %s", got)
	}
}

func TestAssertFileExistsErrorMessageIncludesLabel(t *testing.T) {
	err := assertFileExists(filepath.Join(t.TempDir(), "missing"), "backend coverage file")
	if err == nil {
		t.Fatal("expected error for missing file")
	}
	if !strings.Contains(err.Error(), "backend coverage file") {
		t.Fatalf("expected label in error, got: %v", err)
	}
}

func TestWriteJSONContentIncludesTrailingNewline(t *testing.T) {
	path := filepath.Join(t.TempDir(), "out.json")
	report := reportJSON{Baseline: "origin/development...HEAD", GeneratedAt: "2026-02-17T00:00:00Z", Mode: "warn"}
	if err := writeJSON(path, report); err != nil {
		t.Fatalf("writeJSON: %v", err)
	}
	// #nosec G304 -- Test reads artifact path created by this test.
	body, err := os.ReadFile(path)
	if err != nil {
		t.Fatalf("read json: %v", err)
	}
	if len(body) == 0 || body[len(body)-1] != '\n' {
		t.Fatalf("expected trailing newline, got: %q", string(body))
	}
}

func TestMainProducesRelArtifactPaths(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := "test-results/custom/report.json"
	mdOut := "test-results/custom/report.md"

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: stderr=%s", result.stderr)
	}

	// #nosec G304 -- Test reads artifact path created by this test.
	content, err := os.ReadFile(filepath.Join(repoRoot, jsonOut))
	if err != nil {
		t.Fatalf("read json report: %v", err)
	}

	var report reportJSON
	if err := json.Unmarshal(content, &report); err != nil {
		t.Fatalf("unmarshal report: %v", err)
	}
	if report.Artifacts.JSON != "test-results/custom/report.json" {
		t.Fatalf("unexpected json artifact path: %s", report.Artifacts.JSON)
	}
	if report.Artifacts.Markdown != "test-results/custom/report.md" {
		t.Fatalf("unexpected markdown artifact path: %s", report.Artifacts.Markdown)
	}
}

func TestMainWithExplicitInputPaths(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-backend-coverage", filepath.Join(repoRoot, "backend", "coverage.txt"),
		"-frontend-coverage", filepath.Join(repoRoot, "frontend", "coverage", "lcov.info"),
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success with explicit paths: stderr=%s", result.stderr)
	}
}

func TestMainOutputIncludesArtifactPaths(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := "test-results/a.json"
	mdOut := "test-results/a.md"

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: stderr=%s", result.stderr)
	}
	if !strings.Contains(result.stdout, "JSON: test-results/a.json") {
		t.Fatalf("expected JSON output path in stdout: %s", result.stdout)
	}
	if !strings.Contains(result.stdout, "Markdown: test-results/a.md") {
		t.Fatalf("expected markdown output path in stdout: %s", result.stdout)
	}
}

func TestMainWithFileNeedingCoverageIncludesMarkdownTable(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)

	backendSource := filepath.Join(repoRoot, "backend", "internal", "sample.go")
	if err := os.WriteFile(backendSource, []byte("package internal\nvar Sample = 3\n"), 0o600); err != nil {
		t.Fatalf("update backend source: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte("mode: atomic\nbackend/internal/sample.go:1.1,2.20 1 0\n"), 0o600); err != nil {
		t.Fatalf("write backend coverage: %v", err)
	}

	mdOut := filepath.Join(repoRoot, "test-results", "patch.md")
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD",
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: stderr=%s", result.stderr)
	}

	// #nosec G304 -- Test reads artifact path created by this test.
	body, err := os.ReadFile(mdOut)
	if err != nil {
		t.Fatalf("read markdown report: %v", err)
	}
	if !strings.Contains(string(body), "| Path | Patch Coverage (%) | Uncovered Changed Lines | Uncovered Changed Line Ranges |") {
		t.Fatalf("expected files table in markdown, got: %s", string(body))
	}
}

func TestMainStderrForMissingFrontendCoverage(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.Remove(filepath.Join(repoRoot, "frontend", "coverage", "lcov.info")); err != nil {
		t.Fatalf("remove lcov: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected failure for missing lcov")
	}
	if !strings.Contains(result.stderr, "missing frontend coverage file") {
		t.Fatalf("unexpected stderr: %s", result.stderr)
	}
}

func TestWriteMarkdownWithoutWarningsOrFiles(t *testing.T) {
	report := reportJSON{
		Baseline:         "origin/development...HEAD",
		GeneratedAt:      "2026-02-17T00:00:00Z",
		Mode:             "warn",
		Thresholds:       thresholdJSON{Overall: 90, Backend: 85, Frontend: 85},
		ThresholdSources: thresholdSourcesJSON{Overall: "default", Backend: "default", Frontend: "default"},
		Overall:          patchreport.ScopeCoverage{ChangedLines: 0, CoveredLines: 0, PatchCoveragePct: 100, Status: "pass"},
		Backend:          patchreport.ScopeCoverage{ChangedLines: 0, CoveredLines: 0, PatchCoveragePct: 100, Status: "pass"},
		Frontend:         patchreport.ScopeCoverage{ChangedLines: 0, CoveredLines: 0, PatchCoveragePct: 100, Status: "pass"},
		Artifacts:        artifactsJSON{Markdown: "test-results/out.md", JSON: "test-results/out.json"},
	}

	path := filepath.Join(t.TempDir(), "report.md")
	if err := writeMarkdown(path, report, "backend/coverage.txt", "frontend/coverage/lcov.info"); err != nil {
		t.Fatalf("writeMarkdown failed: %v", err)
	}

	// #nosec G304 -- Test reads artifact path created by this test.
	body, err := os.ReadFile(path)
	if err != nil {
		t.Fatalf("read markdown: %v", err)
	}
	text := string(body)
	if strings.Contains(text, "## Warnings") {
		t.Fatalf("did not expect warnings section: %s", text)
	}
	if strings.Contains(text, "## Files Needing Coverage") {
		t.Fatalf("did not expect files section: %s", text)
	}
}

func TestMainProducesExpectedJSONSchemaFields(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "test-results", "schema.json")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: stderr=%s", result.stderr)
	}

	// #nosec G304 -- Test reads artifact path created by this test.
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json: %v", err)
	}

	var raw map[string]any
	if err := json.Unmarshal(body, &raw); err != nil {
		t.Fatalf("unmarshal raw json: %v", err)
	}
	required := []string{"baseline", "generated_at", "mode", "thresholds", "threshold_sources", "overall", "backend", "frontend", "artifacts"}
	for _, key := range required {
		if _, ok := raw[key]; !ok {
			t.Fatalf("missing required key %q in report json", key)
		}
	}
}

func TestMainReturnsNonZeroWhenBackendCoveragePathIsDirectory(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.Remove(filepath.Join(repoRoot, "backend", "coverage.txt")); err != nil {
		t.Fatalf("remove backend coverage: %v", err)
	}
	if err := os.MkdirAll(filepath.Join(repoRoot, "backend", "coverage.txt"), 0o750); err != nil {
		t.Fatalf("create backend coverage dir: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected failure when backend coverage path is dir")
	}
	if !strings.Contains(result.stderr, "expected backend coverage file to be a file") {
		t.Fatalf("unexpected stderr: %s", result.stderr)
	}
}

func TestMainReturnsNonZeroWhenFrontendCoveragePathIsDirectory(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	lcovPath := filepath.Join(repoRoot, "frontend", "coverage", "lcov.info")
	if err := os.Remove(lcovPath); err != nil {
		t.Fatalf("remove lcov path: %v", err)
	}
	if err := os.MkdirAll(lcovPath, 0o750); err != nil {
		t.Fatalf("create lcov dir: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected failure when frontend coverage path is dir")
	}
	if !strings.Contains(result.stderr, "expected frontend coverage file to be a file") {
		t.Fatalf("unexpected stderr: %s", result.stderr)
	}
}

func TestMainHandlesAbsoluteOutputPaths(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(t.TempDir(), "absolute", "report.json")
	mdOut := filepath.Join(t.TempDir(), "absolute", "report.md")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success with absolute outputs: stderr=%s", result.stderr)
	}
	if _, err := os.Stat(jsonOut); err != nil {
		t.Fatalf("expected absolute json file to exist: %v", err)
	}
	if _, err := os.Stat(mdOut); err != nil {
		t.Fatalf("expected absolute markdown file to exist: %v", err)
	}
}

func TestMainWithNoChangedLinesStillPasses(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success when no lines changed, stderr=%s", result.stderr)
	}
}

func TestMain_UsageOfBaselineFlagAffectsGitDiff(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "internal", "sample.go"), []byte("package internal\nvar Sample = 5\n"), 0o600); err != nil {
		t.Fatalf("update backend source: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD",
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success for baseline HEAD, stderr=%s", result.stderr)
	}
}

func TestMainOutputsWarnLinesWhenAnyScopeWarns(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "internal", "sample.go"), []byte("package internal\nvar Sample = 7\n"), 0o600); err != nil {
		t.Fatalf("update backend file: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte("mode: atomic\nbackend/internal/sample.go:1.1,2.20 1 0\n"), 0o600); err != nil {
		t.Fatalf("write backend coverage: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD",
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success with warnings: stderr=%s", result.stderr)
	}
	if !strings.Contains(result.stdout, "WARN:") {
		t.Fatalf("expected warning lines in stdout: %s", result.stdout)
	}
}

func TestMainProcessHelperWithMalformedArgsExitsNonZero(t *testing.T) {
	// #nosec G204 -- Test helper subprocess invocation with fixed arguments.
	cmd := exec.Command(os.Args[0], "-test.run=TestMainProcessHelper", "--", "-repo-root")
	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
	_, err := cmd.CombinedOutput()
	if err == nil {
		t.Fatal("expected helper process to fail for malformed args")
	}
}

func TestWriteMarkdownContainsSummaryTable(t *testing.T) {
	report := reportJSON{
		Baseline:         "origin/development...HEAD",
		GeneratedAt:      "2026-02-17T00:00:00Z",
		Mode:             "warn",
		Thresholds:       thresholdJSON{Overall: 90, Backend: 85, Frontend: 85},
		ThresholdSources: thresholdSourcesJSON{Overall: "default", Backend: "default", Frontend: "default"},
		Overall:          patchreport.ScopeCoverage{ChangedLines: 5, CoveredLines: 2, PatchCoveragePct: 40.0, Status: "warn"},
		Backend:          patchreport.ScopeCoverage{ChangedLines: 3, CoveredLines: 1, PatchCoveragePct: 33.3, Status: "warn"},
		Frontend:         patchreport.ScopeCoverage{ChangedLines: 2, CoveredLines: 1, PatchCoveragePct: 50.0, Status: "warn"},
		Artifacts:        artifactsJSON{Markdown: "test-results/report.md", JSON: "test-results/report.json"},
	}

	path := filepath.Join(t.TempDir(), "summary.md")
	if err := writeMarkdown(path, report, "backend/coverage.txt", "frontend/coverage/lcov.info"); err != nil {
		t.Fatalf("write markdown: %v", err)
	}
	body, err := os.ReadFile(path)
	if err != nil {
		t.Fatalf("read markdown: %v", err)
	}
	if !strings.Contains(string(body), "| Scope | Changed Lines | Covered Lines | Patch Coverage (%) | Status |") {
		t.Fatalf("expected summary table in markdown: %s", string(body))
	}
}

func TestMainWithRepoRootDotFromSubprocess(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	commandArgs := []string{"-test.run=TestMainProcessHelper", "--", "-repo-root", ".", "-baseline", "HEAD...HEAD"}
	// #nosec G204 -- Test helper subprocess invocation with controlled arguments.
	cmd := exec.Command(os.Args[0], commandArgs...)
	cmd.Dir = repoRoot
	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1")
	output, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("expected success with repo-root dot: %v\n%s", err, string(output))
	}
}

func TestMain_InvalidBackendCoverageFlagPath(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-backend-coverage", "backend/does-not-exist.txt",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected failure for invalid backend coverage flag path")
	}
}

func TestMain_InvalidFrontendCoverageFlagPath(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-frontend-coverage", "frontend/coverage/missing.info",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected failure for invalid frontend coverage flag path")
	}
}

func TestGitDiffReturnsContextualErrorOutput(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	_, err := gitDiff(repoRoot, "refs/heads/does-not-exist")
	if err == nil {
		t.Fatal("expected gitDiff to fail")
	}
	if !strings.Contains(err.Error(), "refs/heads/does-not-exist") {
		t.Fatalf("expected baseline in error: %v", err)
	}
}

func TestMain_EmitsWarningsInSortedOrderWithEnvWarning(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	// #nosec G204 -- Test helper subprocess invocation with controlled arguments.
	// #nosec G204 -- Test helper subprocess invocation with controlled arguments.
	cmd := exec.Command(os.Args[0], "-test.run=TestMainProcessHelper", "--", "-repo-root", repoRoot, "-baseline", "HEAD...HEAD")
	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1", "CHARON_FRONTEND_PATCH_COVERAGE_MIN=bad")
	output, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("expected success with env warning: %v\n%s", err, string(output))
	}
	if !strings.Contains(string(output), "WARN: Ignoring invalid CHARON_FRONTEND_PATCH_COVERAGE_MIN") {
		t.Fatalf("expected frontend env warning: %s", string(output))
	}
}

func TestMain_FrontendParseErrorWithMissingSFDataStillSucceeds(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.WriteFile(filepath.Join(repoRoot, "frontend", "coverage", "lcov.info"), []byte("TN:\nDA:1,1\nend_of_record\n"), 0o600); err != nil {
		t.Fatalf("write lcov: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success with lcov missing SF sections, stderr=%s", result.stderr)
	}
}

func TestMain_BackendCoverageWithInvalidRowsStillSucceeds(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte("mode: atomic\nthis is not valid coverage row\nbackend/internal/sample.go:1.1,2.20 1 1\n"), 0o600); err != nil {
		t.Fatalf("write coverage: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success with ignored invalid rows, stderr=%s", result.stderr)
	}
}

func TestMainOutputMentionsModeWarn(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	if !strings.Contains(result.stdout, "mode=warn") {
		t.Fatalf("expected mode in stdout: %s", result.stdout)
	}
}

func TestMain_GeneratesMarkdownAtConfiguredRelativePath(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	mdOut := "custom/out/report.md"

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	if _, err := os.Stat(filepath.Join(repoRoot, mdOut)); err != nil {
		t.Fatalf("expected markdown output to exist: %v", err)
	}
}

func TestMain_GeneratesJSONAtConfiguredRelativePath(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := "custom/out/report.json"

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	if _, err := os.Stat(filepath.Join(repoRoot, jsonOut)); err != nil {
		t.Fatalf("expected json output to exist: %v", err)
	}
}

func TestMainWarningsAppearWhenThresholdRaised(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	cmd := exec.Command(os.Args[0], "-test.run=TestMainProcessHelper", "--", "-repo-root", repoRoot, "-baseline", "HEAD...HEAD")
	cmd.Env = append(os.Environ(), "GO_WANT_HELPER_PROCESS=1", "CHARON_OVERALL_PATCH_COVERAGE_MIN=101")
	output, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("expected success with invalid threshold env: %v\n%s", err, string(output))
	}
	if !strings.Contains(string(output), "WARN: Ignoring invalid CHARON_OVERALL_PATCH_COVERAGE_MIN") {
		t.Fatalf("expected invalid threshold warning in output: %s", string(output))
	}
}

func TestMain_BaselineFlagRoundTripIntoJSON(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "test-results", "baseline.json")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json: %v", err)
	}

	var report reportJSON
	if err := json.Unmarshal(body, &report); err != nil {
		t.Fatalf("unmarshal json: %v", err)
	}
	if report.Baseline != "HEAD...HEAD" {
		t.Fatalf("expected baseline to match flag, got %s", report.Baseline)
	}
}

func TestMain_WithChangedFilesProducesFilesNeedingCoverageInJSON(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "internal", "sample.go"), []byte("package internal\nvar Sample = 42\n"), 0o600); err != nil {
		t.Fatalf("update backend file: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte("mode: atomic\nbackend/internal/sample.go:1.1,2.20 1 0\n"), 0o600); err != nil {
		t.Fatalf("write backend coverage: %v", err)
	}

	jsonOut := filepath.Join(repoRoot, "test-results", "coverage-gaps.json")
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}

	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json output: %v", err)
	}
	var report reportJSON
	if err := json.Unmarshal(body, &report); err != nil {
		t.Fatalf("unmarshal json: %v", err)
	}
	if len(report.FilesNeedingCoverage) == 0 {
		t.Fatalf("expected files_needing_coverage to be non-empty")
	}
}

func TestMain_FailsWhenMarkdownPathParentIsDirectoryFileConflict(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	conflict := filepath.Join(repoRoot, "conflict")
	if err := os.WriteFile(conflict, []byte("x"), 0o600); err != nil {
		t.Fatalf("write conflict file: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-md-out", filepath.Join(conflict, "nested", "report.md"),
	)
	if result.exitCode == 0 {
		t.Fatalf("expected failure due to markdown path parent conflict")
	}
}

func TestMain_FailsWhenJSONPathParentIsDirectoryFileConflict(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	conflict := filepath.Join(repoRoot, "json-conflict")
	if err := os.WriteFile(conflict, []byte("x"), 0o600); err != nil {
		t.Fatalf("write conflict file: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", filepath.Join(conflict, "nested", "report.json"),
	)
	if result.exitCode == 0 {
		t.Fatalf("expected failure due to json path parent conflict")
	}
}

func TestMain_ReportContainsThresholdSources(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "test-results", "threshold-sources.json")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json: %v", err)
	}
	if !strings.Contains(string(body), "\"threshold_sources\"") {
		t.Fatalf("expected threshold_sources in json: %s", string(body))
	}
}

func TestMain_ReportContainsCoverageScopes(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "test-results", "scopes.json")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json: %v", err)
	}
	for _, key := range []string{"\"overall\"", "\"backend\"", "\"frontend\""} {
		if !strings.Contains(string(body), key) {
			t.Fatalf("expected %s in json: %s", key, string(body))
		}
	}
}

func TestMain_ReportIncludesGeneratedAt(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "test-results", "generated-at.json")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json: %v", err)
	}
	if !strings.Contains(string(body), "\"generated_at\"") {
		t.Fatalf("expected generated_at in json: %s", string(body))
	}
}

func TestMain_ReportIncludesMode(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "test-results", "mode.json")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json: %v", err)
	}
	if !strings.Contains(string(body), "\"mode\": \"warn\"") {
		t.Fatalf("expected warn mode in json: %s", string(body))
	}
}

func TestMain_ReportIncludesArtifactsPaths(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "test-results", "artifacts.json")
	mdOut := filepath.Join(repoRoot, "test-results", "artifacts.md")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json: %v", err)
	}
	if !strings.Contains(string(body), "\"artifacts\"") {
		t.Fatalf("expected artifacts object in json: %s", string(body))
	}
}

func TestMain_FailsWhenGitRepoNotInitialized(t *testing.T) {
	repoRoot := t.TempDir()
	if err := os.MkdirAll(filepath.Join(repoRoot, "backend"), 0o750); err != nil {
		t.Fatalf("mkdir backend: %v", err)
	}
	if err := os.MkdirAll(filepath.Join(repoRoot, "frontend", "coverage"), 0o750); err != nil {
		t.Fatalf("mkdir frontend: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte("mode: atomic\nbackend/internal/sample.go:1.1,1.2 1 1\n"), 0o600); err != nil {
		t.Fatalf("write backend coverage: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "frontend", "coverage", "lcov.info"), []byte("TN:\nSF:frontend/src/sample.ts\nDA:1,1\nend_of_record\n"), 0o600); err != nil {
		t.Fatalf("write frontend lcov: %v", err)
	}

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected failure when repo is not initialized")
	}
	if !strings.Contains(result.stderr, "error generating git diff") {
		t.Fatalf("expected git diff error, got: %s", result.stderr)
	}
}

func TestMain_WritesWarningsToJSONWhenPresent(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "internal", "sample.go"), []byte("package internal\nvar Sample = 8\n"), 0o600); err != nil {
		t.Fatalf("update backend source: %v", err)
	}
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte("mode: atomic\nbackend/internal/sample.go:1.1,2.20 1 0\n"), 0o600); err != nil {
		t.Fatalf("write backend coverage: %v", err)
	}

	jsonOut := filepath.Join(repoRoot, "test-results", "warnings.json")
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD",
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success with warnings: %s", result.stderr)
	}
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read warnings json: %v", err)
	}
	if !strings.Contains(string(body), "\"warnings\"") {
		t.Fatalf("expected warnings array in json: %s", string(body))
	}
}

func TestMain_CreatesOutputDirectoriesRecursively(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "nested", "json", "report.json")
	mdOut := filepath.Join(repoRoot, "nested", "md", "report.md")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-json-out", jsonOut,
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	if _, err := os.Stat(jsonOut); err != nil {
		t.Fatalf("expected json output to exist: %v", err)
	}
	if _, err := os.Stat(mdOut); err != nil {
		t.Fatalf("expected markdown output to exist: %v", err)
	}
}

func TestMain_ReportMarkdownIncludesInputs(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	mdOut := filepath.Join(repoRoot, "test-results", "inputs.md")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(mdOut)
	if err != nil {
		t.Fatalf("read markdown: %v", err)
	}
	if !strings.Contains(string(body), "- Backend coverage:") || !strings.Contains(string(body), "- Frontend coverage:") {
		t.Fatalf("expected inputs section in markdown: %s", string(body))
	}
}

func TestMain_ReportMarkdownIncludesThresholdTable(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	mdOut := filepath.Join(repoRoot, "test-results", "thresholds.md")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(mdOut)
	if err != nil {
		t.Fatalf("read markdown: %v", err)
	}
	if !strings.Contains(string(body), "## Resolved Thresholds") {
		t.Fatalf("expected thresholds section in markdown: %s", string(body))
	}
}

func TestMain_ReportMarkdownIncludesCoverageSummary(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	mdOut := filepath.Join(repoRoot, "test-results", "summary.md")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(mdOut)
	if err != nil {
		t.Fatalf("read markdown: %v", err)
	}
	if !strings.Contains(string(body), "## Coverage Summary") {
		t.Fatalf("expected coverage summary section in markdown: %s", string(body))
	}
}

func TestMain_ReportMarkdownIncludesArtifactsSection(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	mdOut := filepath.Join(repoRoot, "test-results", "artifacts.md")

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-md-out", mdOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(mdOut)
	if err != nil {
		t.Fatalf("read markdown: %v", err)
	}
	if !strings.Contains(string(body), "## Artifacts") {
		t.Fatalf("expected artifacts section in markdown: %s", string(body))
	}
}

func TestMain_RepoRootAbsoluteAndRelativeCoveragePaths(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	absoluteBackend := filepath.Join(repoRoot, "backend", "coverage.txt")
	relativeFrontend := "frontend/coverage/lcov.info"

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
		"-backend-coverage", absoluteBackend,
		"-frontend-coverage", relativeFrontend,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success with mixed path styles: %s", result.stderr)
	}
}

func TestMain_StderrContainsContextOnGitFailure(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "not-a-baseline",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected git failure")
	}
	if !strings.Contains(result.stderr, "error generating git diff") {
		t.Fatalf("expected context in stderr, got: %s", result.stderr)
	}
}

func TestMain_StderrContainsContextOnBackendParseFailure(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.WriteFile(filepath.Join(repoRoot, "backend", "coverage.txt"), []byte(strings.Repeat("x", 3*1024*1024)), 0o600); err != nil {
		t.Fatalf("write large backend coverage: %v", err)
	}
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected backend parse failure")
	}
	if !strings.Contains(result.stderr, "error parsing backend coverage") {
		t.Fatalf("expected backend parse context, got: %s", result.stderr)
	}
}

func TestMain_StderrContainsContextOnFrontendParseFailure(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	if err := os.WriteFile(filepath.Join(repoRoot, "frontend", "coverage", "lcov.info"), []byte(strings.Repeat("y", 3*1024*1024)), 0o600); err != nil {
		t.Fatalf("write large frontend coverage: %v", err)
	}
	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", "HEAD...HEAD",
	)
	if result.exitCode == 0 {
		t.Fatalf("expected frontend parse failure")
	}
	if !strings.Contains(result.stderr, "error parsing frontend coverage") {
		t.Fatalf("expected frontend parse context, got: %s", result.stderr)
	}
}

func TestMain_UsesConfiguredBaselineInOutput(t *testing.T) {
	repoRoot := createGitRepoWithCoverageInputs(t)
	jsonOut := filepath.Join(repoRoot, "test-results", "baseline-output.json")
	baseline := "HEAD...HEAD"

	result := runMainSubprocess(t,
		"-repo-root", repoRoot,
		"-baseline", baseline,
		"-json-out", jsonOut,
	)
	if result.exitCode != 0 {
		t.Fatalf("expected success: %s", result.stderr)
	}
	body, err := os.ReadFile(jsonOut)
	if err != nil {
		t.Fatalf("read json output: %v", err)
	}
	if !strings.Contains(string(body), fmt.Sprintf("\"baseline\": %q", baseline)) {
		t.Fatalf("expected baseline in output json, got: %s", string(body))
	}
}
