"""Tests for GitLab CI linter."""

from yaml_doctor.analyzers.gitlab_ci import lint_gitlab_ci


class TestGitLabCILinter:
    def _pipeline(self, **overrides):
        doc = {
            "image": "python:3.11",
            "stages": ["test", "deploy"],
            "test": {
                "stage": "test",
                "image": "python:3.11",
                "script": ["pytest"],
                "retry": 2,
                "timeout": "30m",
                "cache": {"key": "pip", "paths": [".cache/pip"]},
                "artifacts": {"reports": {"junit": "report.xml"}},
                "rules": [{"if": "$CI_PIPELINE_SOURCE == 'merge_request_event'"}],
                "description": "Run unit tests",
            },
        }
        if "no_stages" in overrides:
            del doc["stages"]
        if "job_overrides" in overrides:
            for k, v in overrides["job_overrides"].items():
                if v is None:
                    doc["test"].pop(k, None)
                else:
                    doc["test"][k] = v
        return doc

    def test_clean(self):
        doc = self._pipeline()
        findings = lint_gitlab_ci([doc])
        high_crit = [f for f in findings if f.rule.severity.value in ("critical", "high")]
        assert len(high_crit) == 0

    def test_gl001_secrets_in_script(self):
        doc = self._pipeline(job_overrides={"script": ['export API_KEY="sk-abc123"']})
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL001" for f in findings)

    def test_gl002_no_retry(self):
        doc = self._pipeline(job_overrides={"retry": None})
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL002" for f in findings)

    def test_gl003_no_cache(self):
        doc = self._pipeline(job_overrides={"cache": None})
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL003" for f in findings)

    def test_gl004_latest_image(self):
        doc = self._pipeline(job_overrides={"image": "python:latest"})
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL004" for f in findings)

    def test_gl005_no_timeout(self):
        doc = self._pipeline(job_overrides={"timeout": None})
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL005" for f in findings)

    def test_gl006_no_stages(self):
        doc = self._pipeline(no_stages=True)
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL006" for f in findings)

    def test_gl007_allow_failure_security(self):
        doc = self._pipeline()
        doc["security-scan"] = {
            "stage": "test",
            "script": ["scan"],
            "allow_failure": True,
        }
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL007" for f in findings)

    def test_gl008_no_artifacts(self):
        doc = self._pipeline(job_overrides={"artifacts": None})
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL008" for f in findings)

    def test_gl009_no_rules(self):
        doc = self._pipeline(job_overrides={"rules": None})
        findings = lint_gitlab_ci([doc])
        assert any(f.rule.rule_id == "GL009" for f in findings)

    def test_empty_docs(self):
        assert lint_gitlab_ci([]) == []
