from typing import Any, Dict, Optional, Tuple

from schedint.daemon.client import (
    DaemonResponse,
    cancel_request,
    get_cadence_multiplier,
    list_requests,
    set_cadence_multiplier,
    submit_request,
)


class SchedintClient:
    """
    Public client API for interacting with schedintd.
    """

    def __init__(self, socket_path: str, timeout_s: float = 5.0):
        self.socket_path = socket_path
        self.timeout_s = timeout_s

    def cadence_multiplier(self) -> float:
        resp = get_cadence_multiplier(
            self.socket_path,
            timeout_s=self.timeout_s,
        )
        if not resp.ok:
            raise RuntimeError(resp.error)

        return float(resp.raw["cadence_multiplier"])

    def set_cadence_multiplier(self, value: float) -> float:
        resp = set_cadence_multiplier(
            self.socket_path,
            value=value,
            timeout_s=self.timeout_s,
        )
        if not resp.ok:
            raise RuntimeError(resp.error)
        return float(resp.raw["cadence_multiplier"])

    def list(
        self,
        *,
        request_id: Optional[str] = None,
        source: Optional[str] = None,
        submitted_by: Optional[str] = None,
        active: Optional[bool] = None,
        expired: Optional[bool] = None,
        between: Optional[Tuple[str, str]] = None,
    ) -> DaemonResponse:
        return list_requests(
            self.socket_path,
            request_id=request_id,
            source=source,
            submitted_by=submitted_by,
            active=active,
            expired=expired,
            between=between,
            timeout_s=self.timeout_s,
        )

    def submit(
        self,
        *,
        source: str,
        overrides: Dict[str, Dict[str, Any]],
        reason: Optional[str] = None,
    ) -> DaemonResponse:
        return submit_request(
            self.socket_path,
            source=source,
            overrides=overrides,
            reason=reason,
            timeout_s=self.timeout_s,
        )

    def cancel(self, *, request_id_prefix: str) -> DaemonResponse:
        return cancel_request(
            self.socket_path,
            request_id_prefix=request_id_prefix,
            timeout_s=self.timeout_s,
        )
