from typing import Dict, Optional

import httpx
from pydantic import BaseModel
from sqlmodel import Field, SQLModel

from learn_sql_model.config import config


class {{ modelname }}Base(SQLModel, table=False):
    # put model attributes here


class {{ modelname }}({{ modelname }}Base, table=True):
    id: int = Field(default=None, primary_key=True)


class {{ modelname }}Create({{ modelname }}Base):
    ...

    def post(self) -> {{ modelname }}:
        r = httpx.post(
            f"{config.api_client.url}/{{ modelname }}/",
            json=self.dict(),
        )
        if r.status_code != 200:
            raise RuntimeError(f"{r.status_code}:\n {r.text}")

        return {{ modelname }}.parse_obj(r.json())


class {{ modelname }}Read({{ modelname }}Base):
    id: int

    @classmethod
    def get(
        cls,
        id: int,
    ) -> {{ modelname }}:
        r = httpx.get(f"{config.api_client.url}/{{ modelname }}/{id}")
        if r.status_code != 200:
            raise RuntimeError(f"{r.status_code}:\n {r.text}")
        return {{ modelname }}Read.parse_obj(r.json())


class {{ modelname }}s(BaseModel):
    __root__: list[{{ modelname }}]

    @classmethod
    def list(
        self,
    ) -> {{ modelname }}:
        r = httpx.get(f"{config.api_client.url}/{{ modelname }}s/")
        if r.status_code != 200:
            raise RuntimeError(f"{r.status_code}:\n {r.text}")
        return {{ modelname }}s.parse_obj({"__root__": r.json()})


class {{ modelname }}Update(SQLModel):
    # id is required to update the {{ modelname }}
    id: int

    def update(self) -> {{ modelname }}:
        r = httpx.patch(
            f"{config.api_client.url}/{{ modelname }}/",
            json=self.dict(),
        )
        if r.status_code != 200:
            raise RuntimeError(f"{r.status_code}:\n {r.text}")


class {{ modelname }}Delete(BaseModel):
    id: int

    @classmethod
    def delete(self, id: int) -> Dict[str, bool]:
        r = httpx.delete(
            f"{config.api_client.url}/{{ modelname }}/{id}",
        )
        if r.status_code != 200:
            raise RuntimeError(f"{r.status_code}:\n {r.text}")
        return {"ok": True}

