"""Verifier for sec-001: Detect Hardcoded Credentials."""

import json
from pathlib import Path

import pytest


@pytest.fixture
def workspace(request):
    """Resolve the workspace path from the --workspace CLI flag."""
    return Path(request.config.getoption("--workspace"))


@pytest.fixture
def findings(workspace):
    """Load and return the findings JSON."""
    path = workspace / "findings.json"
    assert path.exists(), "findings.json not found in workspace"
    data = json.loads(path.read_text())
    assert isinstance(data, list), "findings.json must contain a JSON array"
    return data


EXPECTED_FINDINGS = [
    {"file": "config.py", "line": 10, "type": "password"},
    {"file": "api_client.py", "line": 14, "type": "api_key"},
    {"file": "api_client.py", "line": 39, "type": "token"},
    {"file": "auth_service.py", "line": 16, "type": "password"},
    {"file": "auth_service.py", "line": 55, "type": "api_key"},
]


def test_findings_file_exists(workspace):
    """findings.json must exist in the workspace."""
    assert (workspace / "findings.json").exists()


def test_findings_is_valid_json_array(findings):
    """findings.json must be a non-empty JSON array."""
    assert len(findings) > 0, "findings.json must not be empty"


def test_all_five_findings_present(findings):
    """All 5 credential leaks must be detected."""
    assert len(findings) >= 5, f"Expected at least 5 findings, got {len(findings)}"


def test_correct_files_identified(findings):
    """Findings must reference the correct source files."""
    found_files = {f["file"] for f in findings}
    expected_files = {"config.py", "api_client.py", "auth_service.py"}
    for ef in expected_files:
        assert ef in found_files, f"Expected findings in {ef}"


def test_correct_line_numbers(findings):
    """Each finding must have the correct line number (within tolerance of 2)."""
    for expected in EXPECTED_FINDINGS:
        matches = [
            f for f in findings
            if f["file"] == expected["file"]
            and abs(f["line"] - expected["line"]) <= 2
        ]
        assert len(matches) >= 1, (
            f"No finding near line {expected['line']} in {expected['file']}"
        )


def test_correct_types_identified(findings):
    """Finding types must be one of password, api_key, token."""
    valid_types = {"password", "api_key", "token"}
    for f in findings:
        assert f.get("type") in valid_types, (
            f"Invalid type '{f.get('type')}' — expected one of {valid_types}"
        )


def test_severity_present(findings):
    """Each finding must include a severity field."""
    for f in findings:
        assert "severity" in f, "Each finding must have a severity field"
        assert f["severity"] in {"high", "medium", "low"}, (
            f"Invalid severity '{f['severity']}'"
        )


def test_config_password_found(findings):
    """DB_PASSWORD in config.py must be detected."""
    matches = [
        f for f in findings
        if f["file"] == "config.py" and f["type"] == "password"
    ]
    assert len(matches) >= 1, "DB_PASSWORD in config.py not detected"


def test_api_client_key_found(findings):
    """API_KEY in api_client.py must be detected."""
    matches = [
        f for f in findings
        if f["file"] == "api_client.py" and f["type"] == "api_key"
    ]
    assert len(matches) >= 1, "API_KEY in api_client.py not detected"


def test_weather_token_found(findings):
    """weather_token in api_client.py must be detected."""
    matches = [
        f for f in findings
        if f["file"] == "api_client.py" and f["type"] == "token"
    ]
    assert len(matches) >= 1, "weather_token in api_client.py not detected"
