"""Tests for yaml-doctor models."""

import pytest

from yaml_doctor.models import (
    FileType,
    Finding,
    Grade,
    LintResult,
    LintRule,
    ScanResult,
    Severity,
    grade_from_score,
)


class TestSeverity:
    def test_values(self):
        assert Severity.CRITICAL.value == "critical"
        assert Severity.HIGH.value == "high"
        assert Severity.MEDIUM.value == "medium"
        assert Severity.LOW.value == "low"
        assert Severity.INFO.value == "info"


class TestFileType:
    def test_values(self):
        assert FileType.KUBERNETES.value == "Kubernetes"
        assert FileType.HELM.value == "Helm"
        assert FileType.DOCKER_COMPOSE.value == "Docker Compose"
        assert FileType.GITHUB_ACTIONS.value == "GitHub Actions"
        assert FileType.GITLAB_CI.value == "GitLab CI"
        assert FileType.GENERIC_YAML.value == "YAML"
        assert FileType.UNKNOWN.value == "Unknown"


class TestGrade:
    def test_values(self):
        assert Grade.A_PLUS.value == "A+"
        assert Grade.A.value == "A"
        assert Grade.F.value == "F"


class TestGradeFromScore:
    @pytest.mark.parametrize("score,expected", [
        (100, Grade.A_PLUS),
        (95, Grade.A_PLUS),
        (94, Grade.A),
        (85, Grade.A),
        (84, Grade.B),
        (75, Grade.B),
        (74, Grade.C),
        (65, Grade.C),
        (64, Grade.D),
        (50, Grade.D),
        (49, Grade.F),
        (0, Grade.F),
    ])
    def test_grading(self, score, expected):
        assert grade_from_score(score) == expected


class TestLintRule:
    def test_create(self):
        r = LintRule("TEST001", "Cat", Severity.HIGH, "Title", "Desc", "Fix it")
        assert r.rule_id == "TEST001"
        assert r.category == "Cat"
        assert r.severity == Severity.HIGH
        assert r.title == "Title"
        assert r.description == "Desc"
        assert r.fix == "Fix it"


class TestFinding:
    def test_create(self):
        r = LintRule("T001", "Cat", Severity.LOW, "T", "D", "F")
        f = Finding(rule=r, line=10, message="Issue found")
        assert f.rule == r
        assert f.line == 10
        assert f.message == "Issue found"
        assert f.path == ""
        assert f.fix_suggestion == ""


class TestLintResult:
    def test_defaults(self):
        lr = LintResult(file_path="test.yaml")
        assert lr.valid_yaml is True
        assert lr.score == 100
        assert lr.grade == Grade.A_PLUS
        assert lr.findings == []
        assert lr.documents == 0

    def test_severity_counts(self):
        lr = LintResult(file_path="test.yaml")
        lr.findings = [
            Finding(rule=LintRule("A", "C", Severity.CRITICAL, "", "", ""), line=1, message=""),
            Finding(rule=LintRule("B", "C", Severity.CRITICAL, "", "", ""), line=2, message=""),
            Finding(rule=LintRule("C", "C", Severity.HIGH, "", "", ""), line=3, message=""),
            Finding(rule=LintRule("D", "C", Severity.MEDIUM, "", "", ""), line=4, message=""),
            Finding(rule=LintRule("E", "C", Severity.LOW, "", "", ""), line=5, message=""),
            Finding(rule=LintRule("F", "C", Severity.INFO, "", "", ""), line=6, message=""),
        ]
        assert lr.critical_count == 2
        assert lr.high_count == 1
        assert lr.medium_count == 1
        assert lr.low_count == 1
        assert lr.info_count == 1
        assert lr.total_issues == 5  # excludes INFO
        assert lr.passed is False  # has critical

    def test_passed(self):
        lr = LintResult(file_path="test.yaml")
        lr.findings = [
            Finding(rule=LintRule("A", "C", Severity.LOW, "", "", ""), line=1, message=""),
        ]
        assert lr.passed is True


class TestScanResult:
    def test_defaults(self):
        sr = ScanResult()
        assert sr.total_files == 0
        assert sr.files == []
        assert sr.passed_files == 0
        assert sr.failed_files == 0
        assert sr.critical_total == 0

    def test_with_files(self):
        lr1 = LintResult(file_path="a.yaml")
        lr1.findings = [
            Finding(rule=LintRule("A", "C", Severity.CRITICAL, "", "", ""), line=1, message=""),
        ]
        lr2 = LintResult(file_path="b.yaml")
        sr = ScanResult(files=[lr1, lr2], total_files=2)
        assert sr.passed_files == 1
        assert sr.failed_files == 1
        assert sr.critical_total == 1
