# #region TestRunToDict [C:3] [TYPE Module] [SEMANTICS test,validation,run,dict,duration]
# @BRIEF Verify ValidationTaskService._run_to_dict computes duration_ms correctly,
#   including timezone-naive datetime handling and edge cases.
# @RELATION BINDS_TO -> [ValidationTaskService]
# @TEST_EDGE: no_finished_at -> duration_ms is None
# @TEST_EDGE: no_started_at -> duration_ms is None
# @TEST_EDGE: naive_datetime -> Handled correctly (treated as UTC)
# @TEST_EDGE: aware_datetime -> Handled correctly
# @TEST_INVARIANT: duration_ms_computed -> VERIFIED_BY: test_duration_ms_with_aware_datetimes, test_duration_ms_with_naive_datetimes

import sys
from datetime import UTC, datetime, timezone, timedelta
from pathlib import Path
from unittest.mock import MagicMock

import pytest

sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))


class MockRun:
    """Minimal mock matching ValidationRun ORM attributes."""
    def __init__(self, **kwargs):
        self.id = kwargs.get("id", "run-1")
        self.policy_id = kwargs.get("policy_id", "policy-1")
        self.task_id = kwargs.get("task_id", "task-1")
        self.status = kwargs.get("status", "completed")
        self.trigger = kwargs.get("trigger", "manual")
        self.started_at = kwargs.get("started_at")
        self.finished_at = kwargs.get("finished_at")
        self.dashboard_count = kwargs.get("dashboard_count", 3)
        self.pass_count = kwargs.get("pass_count", 2)
        self.warn_count = kwargs.get("warn_count", 1)
        self.fail_count = kwargs.get("fail_count", 0)
        self.unknown_count = kwargs.get("unknown_count", 0)
        self.created_at = kwargs.get("created_at", datetime(2025, 1, 15, tzinfo=UTC))


# #region TestRunToDictDuration [C:2] [TYPE Class]
# @BRIEF Verify _run_to_dict duration_ms computation.
class TestRunToDictDuration:
    """Verify _run_to_dict duration_ms field."""

    # #region setup [C:1] [TYPE Function]
    @pytest.fixture(autouse=True)
    def setup_service(self):
        from src.services.validation_service import ValidationTaskService
        self.mock_db = MagicMock()
        self.service = ValidationTaskService(db=self.mock_db)
        self.run_to_dict = self.service._run_to_dict
    # #endregion setup

    # #region test_duration_ms_with_aware_datetimes [C:2] [TYPE Function]
    # @BRIEF UTC-aware started_at/finished_at → correct duration_ms.
    def test_duration_ms_with_aware_datetimes(self):
        started = datetime(2025, 1, 15, 10, 0, 0, tzinfo=UTC)
        finished = datetime(2025, 1, 15, 10, 0, 5, tzinfo=UTC)  # 5 seconds
        run = MockRun(started_at=started, finished_at=finished)

        result = self.run_to_dict(run)

        assert result["duration_ms"] == 5000
    # #endregion test_duration_ms_with_aware_datetimes

    # #region test_duration_ms_with_naive_datetimes [C:2] [TYPE Function]
    # @BRIEF Naive (no timezone) datetimes → treated as UTC, correct duration.
    def test_duration_ms_with_naive_datetimes(self):
        started = datetime(2025, 1, 15, 10, 0, 0)  # naive
        finished = datetime(2025, 1, 15, 10, 2, 30)  # naive, 2.5 minutes
        run = MockRun(started_at=started, finished_at=finished)

        result = self.run_to_dict(run)

        assert result["duration_ms"] == 150000  # 2.5 * 60 * 1000
    # #endregion test_duration_ms_with_naive_datetimes

    # #region test_duration_ms_no_finished_at [C:2] [TYPE Function]
    # @BRIEF When finished_at is None, duration_ms is None.
    def test_duration_ms_no_finished_at(self):
        started = datetime(2025, 1, 15, 10, 0, 0, tzinfo=UTC)
        run = MockRun(started_at=started, finished_at=None)

        result = self.run_to_dict(run)

        assert result["duration_ms"] is None
    # #endregion test_duration_ms_no_finished_at

    # #region test_duration_ms_no_started_at [C:2] [TYPE Function]
    # @BRIEF When started_at is None, duration_ms is None.
    def test_duration_ms_no_started_at(self):
        finished = datetime(2025, 1, 15, 10, 0, 0, tzinfo=UTC)
        run = MockRun(started_at=None, finished_at=finished)

        result = self.run_to_dict(run)

        assert result["duration_ms"] is None
    # #endregion test_duration_ms_no_started_at

    # #region test_duration_ms_both_none [C:2] [TYPE Function]
    # @BRIEF When both are None, duration_ms is None.
    def test_duration_ms_both_none(self):
        run = MockRun(started_at=None, finished_at=None)

        result = self.run_to_dict(run)

        assert result["duration_ms"] is None
    # #endregion test_duration_ms_both_none

    # #region test_duration_ms_mixed_aware_naive [C:2] [TYPE Function]
    # @BRIEF One aware, one naive → still computes correctly (both treated as UTC).
    def test_duration_ms_mixed_aware_naive(self):
        started = datetime(2025, 1, 15, 10, 0, 0)  # naive
        finished = datetime(2025, 1, 15, 10, 0, 10, tzinfo=UTC)  # aware
        run = MockRun(started_at=started, finished_at=finished)

        result = self.run_to_dict(run)

        assert result["duration_ms"] == 10000
    # #endregion test_duration_ms_mixed_aware_naive

    # #region test_other_fields_present [C:2] [TYPE Function]
    # @BRIEF _run_to_dict returns all expected fields.
    def test_other_fields_present(self):
        run = MockRun()
        result = self.run_to_dict(run)

        assert result["id"] == "run-1"
        assert result["policy_id"] == "policy-1"
        assert result["task_id"] == "task-1"
        assert result["status"] == "completed"
        assert result["trigger"] == "manual"
        assert result["dashboard_count"] == 3
        assert result["pass_count"] == 2
        assert result["warn_count"] == 1
        assert result["fail_count"] == 0
        assert result["unknown_count"] == 0
    # #endregion test_other_fields_present

    # #region test_isoformat_on_dates [C:2] [TYPE Function]
    # @BRIEF started_at/finished_at are ISO-formatted strings in output.
    def test_isoformat_on_dates(self):
        started = datetime(2025, 1, 15, 10, 0, 0, tzinfo=UTC)
        run = MockRun(started_at=started, finished_at=started)

        result = self.run_to_dict(run)

        assert isinstance(result["started_at"], str)
        assert isinstance(result["finished_at"], str)
        assert "2025-01-15" in result["started_at"]
    # #endregion test_isoformat_on_dates
# #endregion TestRunToDictDuration


# #endregion TestRunToDict
