from __future__ import annotations

import json
from datetime import datetime
from pathlib import Path
from typing import Any

from leshy.core.models import TestCaseResult, TestSuiteConfig, TestSuiteResult
from leshy.core.registry import logger_registry
from leshy.loggers.base import Logger

_DEFAULT_DIR = Path("leshy") / "runs"


@logger_registry.register("json_file")
class JsonFileLogger(Logger):
    """Write TestSuiteResult as structured JSON, saving incrementally."""

    name = "json_file"

    def __init__(self, **kwargs: Any) -> None:
        super().__init__(**kwargs)
        self._output_dir = Path(
            kwargs.get("output", str(_DEFAULT_DIR))
        ).parent if kwargs.get("output") else _DEFAULT_DIR
        self._explicit_path: str | None = kwargs.get("output")
        self._path: Path | None = None
        self._partial: dict[str, Any] = {}

    async def on_suite_start(self, config: TestSuiteConfig) -> None:
        if self._explicit_path:
            self._path = Path(self._explicit_path)
        else:
            ts = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
            self._path = self._output_dir / f"run_{ts}.json"
        self._path.parent.mkdir(parents=True, exist_ok=True)

        self._partial = {
            "suite_name": config.name,
            "started_at": datetime.utcnow().isoformat(),
            "status": "running",
            "case_results": [],
        }
        self._write()

    async def on_case_complete(self, result: TestCaseResult) -> None:
        self._partial["case_results"].append(
            result.model_dump(mode="json")
        )
        self._write()

    async def on_suite_complete(self, result: TestSuiteResult) -> None:
        data = result.model_dump(mode="json")
        data["status"] = "complete"
        self._partial = data
        self._write()

    def _write(self) -> None:
        if self._path:
            self._path.write_text(
                json.dumps(self._partial, indent=2, default=str)
            )
