"""Generic YAML linter — 8 rules for YAML quality."""

from __future__ import annotations

import re

from ..models import Finding, LintRule, Severity

RULES: dict[str, LintRule] = {
    "YML001": LintRule("YML001", "Quality", Severity.MEDIUM, "Inconsistent indentation", "Mixed indentation (tabs vs spaces or inconsistent levels)", "Use consistent 2-space indentation"),
    "YML002": LintRule("YML002", "Quality", Severity.LOW, "Trailing whitespace", "Line has trailing whitespace", "Remove trailing spaces"),
    "YML003": LintRule("YML003", "Quality", Severity.LOW, "Very long line", "Line exceeds 200 characters", "Break long lines using YAML multiline syntax"),
    "YML004": LintRule("YML004", "Quality", Severity.INFO, "No document start marker", "File doesn't start with ---", "Add --- at the beginning of YAML documents"),
    "YML005": LintRule("YML005", "Security", Severity.HIGH, "Hardcoded credentials", "Potential password/token/secret in YAML values", "Use environment variables or secret management"),
    "YML006": LintRule("YML006", "Quality", Severity.MEDIUM, "Duplicate keys", "Same key appears multiple times in a mapping", "Remove duplicate keys"),
    "YML007": LintRule("YML007", "Quality", Severity.LOW, "Empty value", "Key has an empty value (null)", "Provide a value or use explicit null"),
    "YML008": LintRule("YML008", "Quality", Severity.INFO, "File too large", "YAML file exceeds 1000 lines", "Consider splitting into multiple files"),
}

_SECRET_RE = re.compile(
    r"(password|secret|token|api_key|private_key|access_key|credential|auth_token)"
    r"\s*[:=]\s*['\"]?[^\s'\"]{8,}",
    re.IGNORECASE,
)


def lint_yaml(content: str, file_path: str = "") -> list[Finding]:
    """Lint raw YAML content for quality issues."""
    findings: list[Finding] = []
    lines = content.split("\n")

    # YML004: No document start
    stripped_lines = [ln for ln in lines if ln.strip()]
    if stripped_lines and stripped_lines[0].strip() != "---":
        findings.append(Finding(rule=RULES["YML004"], line=1, message="No document start marker (---)"))

    # YML008: File too large
    if len(lines) > 1000:
        findings.append(Finding(rule=RULES["YML008"], line=0, message=f"File has {len(lines)} lines — consider splitting"))

    has_tabs = False
    indent_sizes = set()

    for i, line in enumerate(lines, 1):
        # YML002: Trailing whitespace
        if line != line.rstrip():
            findings.append(Finding(rule=RULES["YML002"], line=i, message="Trailing whitespace"))

        # YML003: Very long line
        if len(line) > 200:
            findings.append(Finding(rule=RULES["YML003"], line=i, message=f"Line is {len(line)} characters"))

        # Tab detection
        if "\t" in line and not line.strip().startswith("#"):
            has_tabs = True

        # Indentation tracking
        if line and not line.strip().startswith("#"):
            stripped = line.lstrip()
            if stripped:
                indent = len(line) - len(stripped)
                if indent > 0:
                    indent_sizes.add(indent)

        # YML005: Hardcoded credentials
        if _SECRET_RE.search(line) and not line.strip().startswith("#"):
            findings.append(Finding(rule=RULES["YML005"], line=i, message="Potential hardcoded credential"))

    # YML001: Inconsistent indentation
    if has_tabs:
        findings.append(Finding(rule=RULES["YML001"], line=0, message="Tabs used for indentation — use spaces"))

    # YML006: Duplicate keys (simple line-level detection)
    seen_keys: dict[str, int] = {}
    dup_re = re.compile(r"^(\s*)([a-zA-Z_][a-zA-Z0-9_-]*)\s*:")
    for i, line in enumerate(lines, 1):
        if line.strip().startswith("#") or not line.strip():
            continue
        m = dup_re.match(line)
        if m:
            indent_level = len(m.group(1))
            key = f"{indent_level}:{m.group(2)}"
            if key in seen_keys:
                findings.append(Finding(
                    rule=RULES["YML006"],
                    line=i,
                    message=f"Duplicate key '{m.group(2)}' (first at line {seen_keys[key]})",
                ))
            else:
                seen_keys[key] = i

    # Limit trailing whitespace findings to max 5
    trail_findings = [f for f in findings if f.rule.rule_id == "YML002"]
    if len(trail_findings) > 5:
        findings = [f for f in findings if f.rule.rule_id != "YML002"]
        findings.extend(trail_findings[:5])
        findings.append(Finding(
            rule=RULES["YML002"],
            line=0,
            message=f"... and {len(trail_findings) - 5} more trailing whitespace issues",
        ))

    return findings
