# -*- coding: utf-8 -*-
from __future__ import annotations

import time
import uuid
from typing import Any


PROTOCOL_SCHEMA = "BaoCardCut.resolve.backend.v1"
SUPPORTED_COMMANDS = frozenset(
    {
        "ping",
        "get_context",
        "export_selected_cards",
        "get_selected_audio",
        "insert_audio",
        "insert_text_plus",
    }
)
DEFAULT_TIMEOUT_SECONDS = 10.0
RETRY_INTERVAL_SECONDS = 1.0
MAX_RETRIES = 2
RESULT_CACHE_LIMIT = 64


class ResolveBackendProtocolError(ValueError):
    pass


def _validate_request_id(value: Any) -> str:
    request_id = str(value or "").strip()
    if not request_id or len(request_id) > 128:
        raise ResolveBackendProtocolError("request_id 缺失或長度不正確。")
    if not all(character.isalnum() or character in "-_." for character in request_id):
        raise ResolveBackendProtocolError("request_id 含有不允許的字元。")
    return request_id


def build_request(
    command: str,
    params: dict[str, Any] | None = None,
    *,
    request_id: str | None = None,
) -> dict[str, Any]:
    command_name = str(command or "").strip()
    if command_name not in SUPPORTED_COMMANDS:
        raise ResolveBackendProtocolError(f"不支援的 backend 命令：{command_name}")
    normalized_request_id = _validate_request_id(request_id or uuid.uuid4().hex)
    if params is not None and not isinstance(params, dict):
        raise ResolveBackendProtocolError("params 必須是 JSON object。")
    return {
        "schema": PROTOCOL_SCHEMA,
        "request_id": normalized_request_id,
        "command": command_name,
        "params": dict(params or {}),
        "created_at": time.time(),
    }


def validate_request(payload: Any) -> dict[str, Any]:
    if not isinstance(payload, dict):
        raise ResolveBackendProtocolError("Backend request 必須是 JSON object。")
    if str(payload.get("schema") or "") != PROTOCOL_SCHEMA:
        raise ResolveBackendProtocolError("Backend request schema 不相容。")
    return build_request(
        str(payload.get("command") or ""),
        payload.get("params"),
        request_id=_validate_request_id(payload.get("request_id")),
    ) | {"created_at": float(payload.get("created_at") or time.time())}


def build_success_result(request: dict[str, Any], **payload: Any) -> dict[str, Any]:
    normalized = validate_request(request)
    return {
        "schema": PROTOCOL_SCHEMA,
        "request_id": normalized["request_id"],
        "command": normalized["command"],
        "ok": True,
        "handled_at": time.time(),
        **payload,
    }


def build_error_result(
    *,
    request_id: str,
    command: str,
    error: str,
    error_code: str,
    traceback_text: str = "",
) -> dict[str, Any]:
    return {
        "schema": PROTOCOL_SCHEMA,
        "request_id": str(request_id or ""),
        "command": str(command or ""),
        "ok": False,
        "error_code": str(error_code or "backend_command_failed"),
        "error": str(error or "Backend command failed."),
        "traceback": str(traceback_text or ""),
        "handled_at": time.time(),
    }


def validate_result(
    payload: Any,
    *,
    request_id: str,
    command: str,
) -> dict[str, Any]:
    if not isinstance(payload, dict):
        raise ResolveBackendProtocolError("Backend result 必須是 JSON object。")
    if str(payload.get("schema") or "") != PROTOCOL_SCHEMA:
        raise ResolveBackendProtocolError("Backend result schema 不相容。")
    if str(payload.get("request_id") or "") != str(request_id):
        raise ResolveBackendProtocolError("Backend result request_id 不相符。")
    if str(payload.get("command") or "") != str(command):
        raise ResolveBackendProtocolError("Backend result command 不相符。")
    if not isinstance(payload.get("ok"), bool):
        raise ResolveBackendProtocolError("Backend result 缺少布林 ok 狀態。")
    return dict(payload)
