# Doesn't work with admin part of library
import httpx
from typing import List, Optional
from .schemes import MessageResponse, User, Message, UserData


class Client:
    token: str
    base_url: str
    headers: dict

    def __init__(self, token: str, base_url: str) -> None:
        self.token = token
        self.base_url = base_url if base_url.endswith("/") else base_url + "/"

        self.headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.token}",
        }

        self.check_connection()

    def check_connection(self):
        with httpx.Client(headers=self.headers) as client:
            try:
                r = client.get(self.base_url)
                if r.status_code == 403:
                    raise Exception("Connection error, check your token")
                r.raise_for_status()
            except httpx.HTTPError:
                raise Exception("Connection error, check your base url")

    async def send_message(self, user_id: str, message: str) -> MessageResponse:
        async with httpx.AsyncClient(headers=self.headers, timeout=120) as client:
            r = await client.post(
                f"{self.base_url}request",
                json={"user_id": user_id, "request": message},
            )

            r.raise_for_status()
            return MessageResponse(**r.json())

    async def get_history(self, user_id: str) -> List[Message]:
        async with httpx.AsyncClient(headers=self.headers) as client:
            r = await client.get(f"{self.base_url}history", params={"id": user_id})

            r.raise_for_status()
            return [Message(**m) for m in r.json()]

    async def clear_history(self, user_id: str) -> None:
        async with httpx.AsyncClient(headers=self.headers) as client:
            r = await client.delete(f"{self.base_url}history", params={"id": user_id})
            r.raise_for_status()

    async def get_user(self, user_id: str) -> Optional[User]:
        async with httpx.AsyncClient(headers=self.headers) as client:
            r = await client.get(f"{self.base_url}user", params={"id": user_id})

            if r.status_code == 404:
                return None

            r.raise_for_status()
            rj = r.json()
            return User(**rj) if rj else None

    async def create_user(self, user_id: str) -> Optional[User]:
        async with httpx.AsyncClient(headers=self.headers) as client:
            r = await client.post(f"{self.base_url}user", params={"id": user_id})

            r.raise_for_status()
            rj = r.json()
            return User(**rj) if rj else None

    async def delete_user(self, user_id: str) -> Optional[User]:
        async with httpx.AsyncClient(headers=self.headers) as client:
            r = await client.delete(f"{self.base_url}user", params={"id": user_id})

            r.raise_for_status()
            rj = r.json()
            return User(**rj) if rj else None

    async def update_user(
        self, user_id: str, new_user_id: str = None, content: dict = None
    ) -> Optional[User]:
        async with httpx.AsyncClient(headers=self.headers) as client:
            r = await client.put(
                f"{self.base_url}user",
                params={"id": user_id},
                json={
                    "id": new_user_id,
                    "content": content,
                },
            )

            r.raise_for_status()
            rj = r.json()
            return User(**rj) if rj else None
