from __future__ import annotations

from datetime import datetime
from pathlib import Path

from tests.pipeline_setup_v2.core.artifacts import ArtifactWriter
from tests.pipeline_setup_v2.core.case_loader import CaseDirectoryLoader
from tests.pipeline_setup_v2.core.models import V2CaseResult
from tests.pipeline_setup_v2.core.session_provider import RagSessionProvider
from tests.pipeline_setup_v2.core.validators import CaseValidator


class V2Runner:
    def __init__(self, cases_dir: Path, results_dir: Path, run_name: str) -> None:
        self._cases_dir = cases_dir
        self._validator = CaseValidator()
        self._sessions = RagSessionProvider()
        self._runtime = None
        self._code_qa = None
        self._writer = ArtifactWriter(results_dir, run_name=run_name, started_at=datetime.now())

    @property
    def run_dir(self) -> Path:
        return self._writer.run_dir

    def run(self) -> tuple[list[V2CaseResult], Path]:
        results: list[V2CaseResult] = []
        for case in CaseDirectoryLoader().load(self._cases_dir):
            rag_session_id = self._sessions.resolve(case.input)
            payload = self._execute(case, rag_session_id)
            mismatches = self._validator.validate(case, payload.actual, payload.details)
            result = V2CaseResult(
                case=case,
                actual=payload.actual,
                details=payload.details,
                passed=not mismatches,
                mismatches=mismatches,
            )
            self._writer.write_case(result)
            results.append(result)
        return results, self._writer.write_summary(results)

    def _execute(self, case, rag_session_id):
        if case.runner == "runtime":
            return self._runtime_adapter().execute(case, rag_session_id)
        if case.runner == "code_qa_eval":
            return self._code_qa_adapter().execute(case, rag_session_id)
        raise ValueError(f"Unsupported runner: {case.runner}")

    def _runtime_adapter(self):
        if self._runtime is None:
            from tests.pipeline_setup_v2.runtime.runtime_adapter import RuntimeAdapter

            self._runtime = RuntimeAdapter()
        return self._runtime

    def _code_qa_adapter(self):
        if self._code_qa is None:
            from tests.pipeline_setup_v2.runtime.code_qa_eval_adapter import CodeQaEvalAdapter

            self._code_qa = CodeQaEvalAdapter()
        return self._code_qa
