import httpx
import msgspec.json

from csirtmu.self_service import models
from csirtmu.self_service.config import BackendConfig
from csirtmu.self_service.models import (
    NetboxIPSearchResult,
    NetboxPrefixSearchResult,
    NetboxTenantSearchResult,
    OutlineResult,
)
from csirtmu.self_service.structs import FormData


class SelfServiceClient:
    def __init__(self, config: BackendConfig) -> None:
        self.client = httpx.Client
        self.config = config

    def _add_step(self, data: bytes, url: str) -> None:
        with self.client() as client:
            client.post(url, json=data)

    def get_next_step(
        self, language: str, step_id: int
    ) -> list[models.TextStep | models.LinkStep | models.FormStep | models.NetboxSearchStep | models.OutlineSearchStep]:
        with self.client() as client:
            response = client.get(f"{self.config.next_step_url}/{step_id}?lang={language}")
            return msgspec.convert(
                response.json(),
                type=list[
                    models.TextStep
                    | models.LinkStep
                    | models.FormStep
                    | models.NetboxSearchStep
                    | models.OutlineSearchStep
                ],
            )

    def get_first_step(self, language: str) -> models.TextStep:
        with self.client() as client:
            response = client.get(f"{self.config.first_step_url}?lang={language}")
            return msgspec.convert(response.json(), type=models.TextStep)

    def get_user_tickets(self, user: str) -> list[dict[str, str]]:
        with self.client() as session:
            response = session.get(f"{self.config.get_tickets_url}", params={"user": user})
            return response.json()

    def submit_form(self, data: FormData, requestor: str, title: str) -> int:
        with self.client() as client:
            response = client.post(
                f"{self.config.submit_form_url}",
                content=msgspec.json.encode({"data": data, "requestor": requestor, "title": title}),
                timeout=30,
            )
            return msgspec.convert(response.json(), type=int)

    def search_netbox(
        self, query: str, path: str
    ) -> list[NetboxIPSearchResult | NetboxPrefixSearchResult | NetboxTenantSearchResult]:
        with self.client() as client:
            response = client.get(
                f"{self.config.netbox_search_url}/{path}",
                params={"query": query},
            )
            return msgspec.convert(
                response.json(),
                type=list[NetboxIPSearchResult | NetboxPrefixSearchResult | NetboxTenantSearchResult],
            )

    def search_outline(self, query: str) -> list[OutlineResult]:
        with self.client() as client:
            response = client.get(
                self.config.outline_search_url,
                params={"query": query},
            )
            return msgspec.convert(
                response.json(),
                type=list[OutlineResult],
            )
