from __future__ import annotations

from pathlib import Path
from threading import Lock

from app.modules.api.domain.events.client_event import ClientEventRecord
from app.modules.api.domain.models.agent_request import AgentRequest
from app.modules.api.domain.models.agent_session import AgentSession
from app.modules.api.infrastructure.logging.trace_file_path_builder import TraceFilePathBuilder
from app.modules.api.infrastructure.logging.trace_markdown_writer import TraceMarkdownWriter


class RequestTraceLogger:
    def __init__(self, root: Path) -> None:
        self._paths = TraceFilePathBuilder(root)
        self._writer = TraceMarkdownWriter()
        self._files: dict[str, Path] = {}
        self._lock = Lock()

    def start_request(self, request: AgentRequest, session: AgentSession) -> None:
        path = self._paths.build(request.request_id)
        self._writer.initialize(
            path,
            [
                f"# Request Trace: {request.request_id}",
                "",
                f"- session_id: {session.session_id}",
                f"- active_rag_session_id: {session.active_rag_session_id or '—'}",
                f"- process_version: {request.process_version}",
                f"- created_at: {request.created_at.isoformat()}",
                "",
                "## User Message",
                request.message,
            ],
        )
        with self._lock:
            self._files[request.request_id] = path

    def log_step(self, request_id: str, step: str, status: str, details: dict | None = None) -> None:
        self._append(request_id, f"Step {step}", {"status": status, "details": details or {}})

    def log_module(self, request_id: str, module: str, title: str, payload: dict | None = None) -> None:
        body = {"event": title}
        body.update(payload or {})
        self._append(request_id, module, body)

    def log_event(self, event: ClientEventRecord) -> None:
        self._append(
            event.request_id,
            "client_event",
            {
                "event": event.type.value,
                "source": event.source,
                "text": event.text,
                "payload": event.payload,
                "created_at": event.created_at.isoformat(),
            },
        )

    def complete_request(self, request: AgentRequest) -> None:
        self._append(
            request.request_id,
            "result",
            {
                "status": request.status.value,
                "answer": request.answer,
                "completed_at": request.completed_at.isoformat() if request.completed_at else None,
            },
        )

    def fail_request(self, request: AgentRequest) -> None:
        self._append(
            request.request_id,
            "result",
            {
                "status": request.status.value,
                "error": request.error.model_dump(mode="json") if request.error else None,
                "completed_at": request.completed_at.isoformat() if request.completed_at else None,
            },
        )

    def _append(self, request_id: str, title: str, payload: dict) -> None:
        with self._lock:
            path = self._files.get(request_id)
        if path is None:
            return
        self._writer.append_section(path, title, payload)
