"""Tests for CI/CD Configuration Generator."""

from __future__ import annotations

import pytest

from mcpaudit.ci_configs import (
    CIOptions,
    format_ci_config,
    generate_github_action,
    generate_gitlab_ci,
    generate_jenkins,
    generate_pre_commit,
)


# --- CIOptions ---

class TestCIOptions:
    def test_defaults(self):
        opts = CIOptions()
        assert opts.min_trust_score == 70
        assert opts.fail_on_severity == "high"
        assert opts.formats == ["text"]
        assert opts.targets == ["."]
        assert opts.python_version == "3.11"
        assert opts.mcpaudit_version == "latest"

    def test_custom_values(self):
        opts = CIOptions(
            min_trust_score=90,
            fail_on_severity="critical",
            formats=["sarif"],
            targets=["src/", "lib/"],
            python_version="3.12",
            mcpaudit_version="1.2.0",
        )
        assert opts.min_trust_score == 90
        assert opts.fail_on_severity == "critical"
        assert opts.targets == ["src/", "lib/"]


# --- GitHub Actions ---

class TestGitHubAction:
    def test_generates_yaml(self):
        output = generate_github_action()
        assert "name: MCP Security Audit" in output
        assert "actions/checkout@v4" in output
        assert "pip install mcpaudit" in output

    def test_includes_min_score(self):
        opts = CIOptions(min_trust_score=85)
        output = generate_github_action(opts)
        assert "--min-score 85" in output

    def test_includes_severity(self):
        opts = CIOptions(fail_on_severity="critical")
        output = generate_github_action(opts)
        assert "--severity critical" in output

    def test_includes_python_version(self):
        opts = CIOptions(python_version="3.12")
        output = generate_github_action(opts)
        assert "3.12" in output

    def test_includes_sarif_upload(self):
        output = generate_github_action()
        assert "sarif" in output.lower()
        assert "upload-sarif" in output.lower() or "codeql-action" in output.lower()

    def test_pinned_version(self):
        opts = CIOptions(mcpaudit_version="1.2.0")
        output = generate_github_action(opts)
        assert "mcpaudit==1.2.0" in output

    def test_latest_version(self):
        opts = CIOptions(mcpaudit_version="latest")
        output = generate_github_action(opts)
        assert "mcpaudit==" not in output

    def test_custom_targets(self):
        opts = CIOptions(targets=["src/", "lib/"])
        output = generate_github_action(opts)
        assert "src/ lib/" in output

    def test_extra_flags(self):
        opts = CIOptions(extra_flags=["--taxonomy", "--save-history"])
        output = generate_github_action(opts)
        assert "--taxonomy" in output
        assert "--save-history" in output


# --- GitLab CI ---

class TestGitLabCI:
    def test_generates_yaml(self):
        output = generate_gitlab_ci()
        assert "mcpaudit:" in output
        assert "stage: test" in output
        assert "pip install" in output

    def test_includes_min_score(self):
        opts = CIOptions(min_trust_score=80)
        output = generate_gitlab_ci(opts)
        assert "--min-score 80" in output

    def test_includes_severity(self):
        opts = CIOptions(fail_on_severity="medium")
        output = generate_gitlab_ci(opts)
        assert "--severity medium" in output

    def test_merge_request_trigger(self):
        output = generate_gitlab_ci()
        assert "merge_request_event" in output

    def test_artifacts_section(self):
        output = generate_gitlab_ci()
        assert "artifacts:" in output

    def test_pinned_version(self):
        opts = CIOptions(mcpaudit_version="1.2.0")
        output = generate_gitlab_ci(opts)
        assert "mcpaudit==1.2.0" in output

    def test_python_image(self):
        opts = CIOptions(python_version="3.12")
        output = generate_gitlab_ci(opts)
        assert "python:3.12-slim" in output


# --- Pre-commit ---

class TestPreCommit:
    def test_generates_yaml(self):
        output = generate_pre_commit()
        assert "repos:" in output
        assert "hooks:" in output
        assert "mcpaudit" in output

    def test_includes_min_score(self):
        opts = CIOptions(min_trust_score=90)
        output = generate_pre_commit(opts)
        assert "--min-score 90" in output

    def test_includes_severity(self):
        opts = CIOptions(fail_on_severity="critical")
        output = generate_pre_commit(opts)
        assert "--severity critical" in output

    def test_file_types(self):
        output = generate_pre_commit()
        assert "python" in output
        assert "ts" in output or "javascript" in output

    def test_pass_filenames(self):
        output = generate_pre_commit()
        assert "pass_filenames: true" in output

    def test_pinned_version(self):
        opts = CIOptions(mcpaudit_version="1.2.0")
        output = generate_pre_commit(opts)
        assert "v1.2.0" in output

    def test_latest_version(self):
        opts = CIOptions(mcpaudit_version="latest")
        output = generate_pre_commit(opts)
        assert "rev: latest" in output


# --- Jenkins ---

class TestJenkins:
    def test_generates_groovy(self):
        output = generate_jenkins()
        assert "stage(" in output
        assert "MCP Security Audit" in output
        assert "pip install mcpaudit" in output

    def test_includes_min_score(self):
        opts = CIOptions(min_trust_score=75)
        output = generate_jenkins(opts)
        assert "--min-score 75" in output

    def test_includes_severity(self):
        opts = CIOptions(fail_on_severity="high")
        output = generate_jenkins(opts)
        assert "--severity high" in output

    def test_includes_sarif(self):
        output = generate_jenkins()
        assert "sarif" in output

    def test_archive_artifacts(self):
        output = generate_jenkins()
        assert "archiveArtifacts" in output

    def test_pinned_version(self):
        opts = CIOptions(mcpaudit_version="1.2.0")
        output = generate_jenkins(opts)
        assert "mcpaudit==1.2.0" in output

    def test_post_always(self):
        output = generate_jenkins()
        assert "always" in output


# --- format_ci_config ---

class TestFormatCIConfig:
    def test_github(self):
        output = format_ci_config("github")
        assert "GitHub" in output or "github" in output.lower()
        assert "actions" in output.lower()

    def test_gitlab(self):
        output = format_ci_config("gitlab")
        assert "stage:" in output

    def test_pre_commit(self):
        output = format_ci_config("pre-commit")
        assert "repos:" in output

    def test_jenkins(self):
        output = format_ci_config("jenkins")
        assert "stage(" in output

    def test_invalid_platform(self):
        with pytest.raises(ValueError, match="Unknown platform"):
            format_ci_config("circleci")

    def test_with_options(self):
        opts = CIOptions(min_trust_score=95)
        output = format_ci_config("github", opts)
        assert "--min-score 95" in output
