"""Verify API client."""

from __future__ import annotations

import time
from datetime import datetime
from pathlib import Path
from typing import TYPE_CHECKING, IO

from .report import VerifyReport
from .types import Verdict, VerifyConfig

if TYPE_CHECKING:
    from botmanifold.client import BotManifoldClient


class VerifyClient:
    """Client for policy verification.

    This is the primary API surface for BotManifold. Use it to verify
    that your robot policies are safe before deployment.

    Example:
        >>> client = BotManifoldClient(api_key="...")
        >>> report = client.verify.run("my_policy.zip", scenario="messy_room")
        >>> print(f"Verdict: {report.verdict}")
    """

    def __init__(self, parent: "BotManifoldClient") -> None:
        self._parent = parent

    def run(
        self,
        policy: str | Path | IO[bytes],
        scenario: str,
        *,
        num_episodes: int = 5,
        timeout: int = 300,
        wait: bool = True,
    ) -> VerifyReport:
        """Verify a policy and return the result.

        Args:
            policy: Path to policy zip file, or file-like object.
            scenario: Scenario ID to verify against.
            num_episodes: Number of episodes to run (default: 5).
            timeout: Maximum time to wait in seconds (default: 300).
            wait: If True, wait for result. If False, return immediately.

        Returns:
            VerifyReport with verdict and details.
        """
        config = VerifyConfig(
            scenario=scenario,
            num_episodes=num_episodes,
            timeout=timeout,
        )
        job = self.submit(policy, config)

        if wait:
            return self.wait(job.job_id, timeout=timeout)
        return job

    def submit(
        self,
        policy: str | Path | IO[bytes],
        config: VerifyConfig,
    ) -> VerifyReport:
        """Submit a policy for verification (non-blocking).

        Args:
            policy: Path to policy zip file, or file-like object.
            config: Verification configuration.

        Returns:
            VerifyReport with job_id and PENDING status.
        """
        if isinstance(policy, (str, Path)):
            path = Path(policy)
            if not path.exists():
                raise FileNotFoundError(f"Policy file not found: {path}")
            with open(path, "rb") as f:
                return self._submit_file(f, path.name, config)
        else:
            return self._submit_file(policy, "policy.zip", config)

    def _submit_file(
        self,
        file: IO[bytes],
        filename: str,
        config: VerifyConfig,
    ) -> VerifyReport:
        """Submit a file for verification."""
        files = {"file": (filename, file, "application/zip")}
        data = self._parent._request(
            "POST",
            "/verify",
            files=files,
            data=config.to_dict(),
        )

        return VerifyReport(
            job_id=data["job_id"],
            verdict=Verdict.PENDING,
            score=0.0,
            scenario=config.scenario,
            episodes=config.num_episodes,
            created_at=datetime.now(),
        )

    def status(self, job_id: str) -> VerifyReport:
        """Check the status of a verification job.

        Args:
            job_id: The job ID from submit().

        Returns:
            VerifyReport with current status.
        """
        data = self._parent._request("GET", f"/verify/{job_id}")

        completed_at = None
        if data.get("completed_at"):
            completed_at = datetime.fromisoformat(
                data["completed_at"].replace("Z", "+00:00")
            )

        return VerifyReport(
            job_id=data["job_id"],
            verdict=Verdict(data["verdict"]),
            score=data.get("score", 0.0),
            scenario=data["scenario"],
            episodes=data.get("episodes", 5),
            video_url=data.get("video_url"),
            report_url=data.get("report_url"),
            created_at=datetime.fromisoformat(
                data["created_at"].replace("Z", "+00:00")
            ) if data.get("created_at") else None,
            completed_at=completed_at,
            details=data.get("details", {}),
        )

    def wait(
        self,
        job_id: str,
        timeout: int = 300,
        poll_interval: int = 5,
    ) -> VerifyReport:
        """Wait for a verification job to complete.

        Args:
            job_id: The job ID to wait for.
            timeout: Maximum time to wait in seconds.
            poll_interval: Time between status checks.

        Returns:
            VerifyReport with final result.
        """
        start_time = time.time()
        while time.time() - start_time < timeout:
            report = self.status(job_id)
            if report.is_complete:
                return report
            time.sleep(poll_interval)

        raise TimeoutError(
            f"Verification job {job_id} did not complete within {timeout}s"
        )
