from typing import List
from uuid import UUID

import inject
from sqlalchemy.sql.expression import desc
from sqlmodel import Session, between, select

from src.core.events import EventDescription
from src.core.helpers.exceptions import DataValidationError, NotAuthorizedError, NotFoundError
from src.core.models import (
    Client,
    Context,
    CreateBalance,
    CreateOrder,
    Item,
    Order,
    OrderDetail,
    QueryOrder,
    UpdateOrder,
    UpdateOrderStatus,
)
from src.core.services import Streamer

from . import balance


def get_all(session: Session, query_schema: QueryOrder, context: Context) -> List[Order]:
    args = []

    if query_schema.status is not None:
        args.append(Order.status == query_schema.status)

    if not context.user_is_super_user:
        args.append(Order.owner_id == context.user_id)

    if query_schema.start_date is not None and query_schema.end_date is not None:
        args.append(between(Order.date, query_schema.start_date, query_schema.end_date))

    return session.exec(select(Order).where(*args).order_by(desc(Order.date))).all()


def get_by_id(session: Session, order_id: UUID, context: Context) -> Order:
    order = session.exec(select(Order).where(Order.id == order_id)).first()

    if not order:
        raise NotFoundError("Não foi possível localizar a venda com ID: %s" % order_id)

    if not context.user_is_super_user and order.owner_id != context.user_id:
        raise NotAuthorizedError(f"Você não possui permissão para consultar a Venda {order_id}")

    return order


@inject.params(streamer=Streamer)
def register_sale(session: Session, schema: CreateOrder, context: Context, streamer: Streamer) -> Order:
    if not session.exec(select(Client).where(Client.id == schema.client_id)).first():
        raise NotFoundError(f"Não foi possível localizar o cliente com ID: {schema.client_id}")

    checked_ids = []

    for detail in schema.items:
        if detail.item_id in checked_ids:
            continue

        checked_ids.append(detail.item_id)
        item = session.exec(