"""Unit tests for HistoryReader."""

import json
from pathlib import Path

import pytest

from tools.history.reader import AuditSummary, HistoryReader


@pytest.fixture
def temp_history_dir(tmp_path: Path) -> Path:
    """Create a temporary history directory."""
    return tmp_path / ".optix" / "history"


@pytest.fixture
def sample_audit_data() -> dict:
    """Sample audit.json data."""
    return {
        "version": "1.0",
        "timestamp": "2026-01-29T14:30:45",
        "lens": "security",
        "continuation_id": "test-abc-123",
        "project": {
            "name": "my-project",
            "root_path": "/path/to/project",
        },
        "summary": {
            "total_findings": 5,
            "by_severity": {"critical": 0, "high": 2, "medium": 2, "low": 1, "info": 0},
            "files_examined": 42,
            "steps_completed": 6,
            "duration_seconds": 120,
        },
        "findings": [
            {
                "id": "OPX-A1B2C3D4",
                "severity": "high",
                "category": "SQL Injection",
                "description": "Unsafe query",
                "affected_files": ["src/db.py"],
                "remediation": "Use parameterized queries",
            }
        ],
        "step_history": [],
        "files_checked": ["src/db.py", "src/api.py"],
        "confidence": "high",
    }


def create_audit_dir(history_dir: Path, dir_name: str, audit_data: dict) -> Path:
    """Helper to create an audit directory with data."""
    audit_dir = history_dir / dir_name
    audit_dir.mkdir(parents=True, exist_ok=True)
    audit_file = audit_dir / "audit.json"
    with open(audit_file, "w", encoding="utf-8") as f:
        json.dump(audit_data, f)
    return audit_dir


class TestHistoryReaderInit:
    def test_init_sets_base_dir(self, temp_history_dir: Path):
        reader = HistoryReader(temp_history_dir)
        assert reader.base_dir == temp_history_dir


class TestListAudits:
    def test_returns_empty_when_dir_not_exists(self, temp_history_dir: Path):
        reader = HistoryReader(temp_history_dir)
        result = reader.list_audits()
        assert result == []

    def test_returns_empty_when_no_audits(self, temp_history_dir: Path):
        temp_history_dir.mkdir(parents=True, exist_ok=True)
        reader = HistoryReader(temp_history_dir)
        result = reader.list_audits()
        assert result == []

    def test_returns_audit_summaries(
        self, temp_history_dir: Path, sample_audit_data: dict
    ):
        create_audit_dir(
            temp_history_dir, "2026-01-29_14-30-45_security", sample_audit_data
        )
        reader = HistoryReader(temp_history_dir)
        result = reader.list_audits()

        assert len(result) == 1
        assert isinstance(result[0], AuditSummary)
        assert result[0].dir_name == "2026-01-29_14-30-45_security"
        assert result[0].lens == "security"
        assert result[0].total_findings == 5

    def test_sorted_by_timestamp_descending(
        self, temp_history_dir: Path, sample_audit_data: dict
    ):
        older_data = sample_audit_data.copy()
        older_data["timestamp"] = "2026-01-28T10:00:00"

        newer_data = sample_audit_data.copy()
        newer_data["timestamp"] = "2026-01-30T16:00:00"

        create_audit_dir(temp_history_dir, "older_audit_security", older_data)
        create_audit_dir(temp_history_dir, "newer_audit_security", newer_data)

        reader = HistoryReader(temp_history_dir)
        result = reader.list_audits()

        assert len(result) == 2
        assert result[0].dir_name == "newer_audit_security"
        assert result[1].dir_name == "older_audit_security"

    def test_skips_dirs_without_audit_json(
        self, temp_history_dir: Path, sample_audit_data: dict
    ):
        temp_history_dir.mkdir(parents=True, exist_ok=True)
        (temp_history_dir / "empty_dir").mkdir()
        create_audit_dir(
            temp_history_dir, "2026-01-29_14-30-45_security", sample_audit_data
        )

        reader = HistoryReader(temp_history_dir)
        result = reader.list_audits()

        assert len(result) == 1

    def test_skips_invalid_json(self, temp_history_dir: Path, sample_audit_data: dict):
        audit_dir = temp_history_dir / "invalid_json"
        audit_dir.mkdir(parents=True, exist_ok=True)
        (audit_dir / "audit.json").write_text("not valid json")

        create_audit_dir(
            temp_history_dir, "2026-01-29_14-30-45_security", sample_audit_data
        )

        reader = HistoryReader(temp_history_dir)
        result = reader.list_audits()

        assert len(result) == 1


class TestGetAudit:
    def test_returns_audit_data(self, temp_history_dir: Path, sample_audit_data: dict):
        create_audit_dir(
            temp_history_dir, "2026-01-29_14-30-45_security", sample_audit_data
        )
        reader = HistoryReader(temp_history_dir)

        result = reader.get_audit("2026-01-29_14-30-45_security")

        assert result is not None
        assert result["lens"] == "security"
        assert result["continuation_id"] == "test-abc-123"
        assert result["dir_name"] == "2026-01-29_14-30-45_security"

    def test_returns_none_when_not_found(self, temp_history_dir: Path):
        temp_history_dir.mkdir(parents=True, exist_ok=True)
        reader = HistoryReader(temp_history_dir)

        result = reader.get_audit("nonexistent")

        assert result is None

    def test_rejects_path_traversal_dotdot(self, temp_history_dir: Path):
        reader = HistoryReader(temp_history_dir)
        result = reader.get_audit("../etc/passwd")
        assert result is None

    def test_rejects_path_traversal_slash(self, temp_history_dir: Path):
        reader = HistoryReader(temp_history_dir)
        result = reader.get_audit("foo/bar")
        assert result is None

    def test_rejects_path_traversal_backslash(self, temp_history_dir: Path):
        reader = HistoryReader(temp_history_dir)
        result = reader.get_audit("foo\\bar")
        assert result is None


class TestAuditSummary:
    def test_to_dict(self):
        summary = AuditSummary(
            dir_name="2026-01-29_14-30-45_security",
            timestamp="2026-01-29T14:30:45",
            lens="security",
            continuation_id="test-123",
            project_name="my-project",
            total_findings=5,
            by_severity={"critical": 0, "high": 2, "medium": 2, "low": 1, "info": 0},
            files_examined=42,
            steps_completed=6,
        )

        result = summary.to_dict()

        assert result["dir_name"] == "2026-01-29_14-30-45_security"
        assert result["lens"] == "security"
        assert result["total_findings"] == 5
        assert result["by_severity"]["high"] == 2
