# This file is generated by prismarine. Do not modify it.

from prismarine.runtime.dynamo_crud import (
    _query,
    _get_item,
    _update,
    _put_item,
    _delete,
    _scan,
    _save,
    Model,
    without,
    DbNotFound
)

from typing import TypedDict, List, Literal, NotRequired  # noqa
from types import EllipsisType

from prismarine.runtime.dynamo_default import get_dynamo_access
from myobject.models import Item

dynamo = get_dynamo_access()


class ItemModel(Model):
    table_name = 'MyDatabaseItem'
    PK = 'Foo'
    SK = 'Bar'

    class UpdateDTO(TypedDict, total=False):
        Foo: str
        Bar: str
        Baz: NotRequired[str]

    @staticmethod
    def list(*, foo: str, **kwargs) -> List[Item]:
        return _query(dynamo, ItemModel.table_name, {ItemModel.PK: foo}, **kwargs)

    @staticmethod
    def get(
        *, bar: str, foo: str, default: Item | EllipsisType = ..., **kwargs
    ) -> Item:
        item = _get_item(
            dynamo,
            ItemModel.table_name,
            {ItemModel.PK: foo, ItemModel.SK: bar},
            default,
            **kwargs
        )
        if not item:
            raise DbNotFound(
                f'Item was not found in {ItemModel.table_name} with params foo={foo}, bar={bar}'
            )
        return item

    @staticmethod
    def put(item: Item, **kwargs) -> Item:
        _put_item(dynamo, ItemModel.table_name, item, **kwargs)
        return item

    @staticmethod
    def update(
        item: UpdateDTO, *, foo: str, bar: str, default: Item | EllipsisType = ...
    ) -> Item:
        initial = ItemModel.get(bar=bar, foo=foo, default=default)
        _update(
            dynamo,
            ItemModel.table_name,
            {ItemModel.PK: foo, ItemModel.SK: bar},
            without(item, [ItemModel.PK, ItemModel.SK])
        )
        return {**initial, **item}

    @staticmethod
    def save(updated: Item, *, original: Item | None = None) -> Item:
        _save(
            dynamo,
            ItemModel.table_name,
            kv={
                ItemModel.PK: updated[ItemModel.PK],
                ItemModel.SK: updated[ItemModel.SK]
            },
            updated=updated,
            original=original
        )
        return updated

    @staticmethod
    def delete(*, bar: str, foo: str, **kwargs):
        _delete(
            dynamo,
            ItemModel.table_name,
            {ItemModel.PK: foo, ItemModel.SK: bar},
            **kwargs
        )

    @staticmethod
    def scan(**kwargs) -> List[Item]:
        return _scan(dynamo, ItemModel.table_name, **kwargs)
