"""Signed internal client for the AroFlo UI worker."""

from __future__ import annotations

import json
import os
import time
import uuid

import requests
from bridge_platform.secrets.secrets_manager import SecretsManager

from .worker_security import sign_worker_request


class WorkerError(RuntimeError):
    def __init__(self, code: str, *, retryable: bool = False):
        self.code, self.retryable = code, retryable
        super().__init__(code)


class AroFloWorkerClient:
    def __init__(self, base_url: str | None = None, secret: str | None = None,
                 session: requests.Session | None = None):
        self.base_url = (
            base_url
            or os.getenv("AROFLO_UI_WORKER_URL")
            or "http://127.0.0.1:5010"
        ).rstrip("/")
        self.secret = secret or ""
        self.session = session or requests.Session()

    def call(self, method: str, path: str, *, tenant_id: str, bot_id: str,
             payload: dict | None = None, timeout: int = 15) -> dict:
        method = method.upper()
        secret = self.secret or SecretsManager().get_secret(
            tenant_id=tenant_id,
            app_id="aroflo_connector_app",
            secret_name="ui_worker_shared_secret",
        ) or ""
        if not secret:
            raise WorkerError("worker_not_configured")
        data = dict(payload or {})
        data.update({"tenant_id": tenant_id, "bot_id": bot_id})
        if method == "GET":
            body, params = b"", data
        else:
            body = json.dumps(data, separators=(",", ":"), sort_keys=True).encode()
            params = None
        timestamp, nonce = str(int(time.time())), uuid.uuid4().hex
        headers = {
            "X-AroFlo-Timestamp": timestamp,
            "X-AroFlo-Nonce": nonce,
            "X-AroFlo-Signature": sign_worker_request(
                secret, method, path, body, timestamp, nonce,
            ),
            "Content-Type": "application/json",
            "Accept": "application/json",
        }
        try:
            response = self.session.request(method, self.base_url + path, params=params,
                                            data=body or None, headers=headers, timeout=timeout)
        except requests.RequestException as exc:
            raise WorkerError("worker_unavailable", retryable=True) from exc
        try:
            result = response.json()
        except ValueError as exc:
            raise WorkerError("worker_invalid_response", retryable=True) from exc
        if response.status_code == 409 and result.get("status") == "busy":
            raise WorkerError("bot_busy", retryable=True)
        if response.status_code >= 400:
            code = str(result.get("code") or "worker_request_failed")
            raise WorkerError(code, retryable=response.status_code >= 500)
        return result
