import requests
import dataclasses
from typing import *

@dataclasses.dataclass()
class ClientConfig:
    base_url: Optional[str] = None
    username: Optional[str] = None
    password: Optional[str] = None

@dataclasses.dataclass()
class Vector3:
    x: float
    y: float
    z: float

@dataclasses.dataclass()
class ResultData:
    data: Optional[Any] = None
    error: Optional[str] = None

@dataclasses.dataclass()
class PathFindingResult:
    path: Optional[List[Vector3]] = None
    error: Optional[str] = None

class VoxelClient:
    def __init__(self, config: ClientConfig):
        self.config = config

    def _get_default_config(self)-> Dict[str, Any]:
        return {
            "username": self.config.username,
            "password": self.config.password,
        }

    def _do_request(self, sub_url: str, params: Dict[str, Any]) -> ResultData:
        try:
            data = {
                "config": self._get_default_config(),
                "data": params
            }
            url = f"{self.config.base_url}{sub_url}"
            response = requests.post(url, json=data)
            response.raise_for_status()
            return ResultData(
                data=response.json(),
                error=None
            )
        except requests.exceptions.RequestException as e:
            return ResultData(
                data=None,
                error=f"请求失败: {str(e)}"
            )
        
    def find_path(self, level_name: str, start: Vector3, end: Vector3) -> PathFindingResult:
        sub_url = "/path_finding/"
        params = {
            "level_name": level_name,
            "start": start,
            "end": end
        }
        result = self._do_request(sub_url, params)
        if result.error is not None:
            return PathFindingResult(
                path=None,
                error=result.error
            )
        return PathFindingResult(
            path=result.data["path"],
            error=None
        )
