from datetime import date
from decimal import Decimal

from fastapi import Query
from pydantic import BaseModel, UUID4, root_validator
from pydantic.dataclasses import dataclass

from intranet.trip.src import enums
from intranet.trip.src.api.schemas.person import PersonDetailsPublic
from intranet.trip.src.models import TransactionActions


class TransactionBase(BaseModel):
    type: enums.TransactionType
    general_service_id: str = None
    service_type: enums.TransactionServiceType
    execution_date: date
    price: Decimal
    is_penalty: bool


class TransactionCreate(TransactionBase):
    trip_id: int
    service_id: int = None
    company_id: int
    person_id: int
    status: enums.TransactionStatus
    invoice_date: date = None
    fee: Decimal


class TransactionPartialUpdate(TransactionBase):
    person_id: int = None
    service_id: int = None
    type: enums.TransactionType = None
    service_type: enums.TransactionServiceType = None
    execution_date: date = None
    invoice_date: date = None
    price: Decimal = None
    is_penalty: bool = None
    fee: Decimal = None


class TransactionLite(TransactionBase):
    """Транзакция для списковой ручки с ограниченным доступом"""
    trip_id: int
    transaction_id: UUID4
    company_id: int
    person: PersonDetailsPublic
    status: enums.TransactionStatus
    actions: TransactionActions = None
    fee: str
    full_price: str
    is_offline: bool

    # TODO: BTRIP-3006 грануляция доступов
    editable_fields: set[str]

    @root_validator(pre=True)
    def set_is_offline(cls, values):
        values['is_offline'] = values.get('author_id') is not None
        return values


class Transaction(TransactionLite):
    service_id: int = None
    invoice_date: date = None


class TransactionId(BaseModel):
    transaction_id: UUID4


@dataclass
class TransactionFilter:
    """Фильтр транзакций в списковой ручке"""
    limit: int = Query(None)
    offset: int = Query(None)
    company_id: int = Query(None)
    query: str = Query(None)
    trip_id: int = Query(None)
    person_id: int = Query(None)
    service_id: int = Query(None)
    service_type: enums.TransactionServiceType = Query(None)
    status: enums.TransactionStatus = Query(None)
    execution_date__lte: date = Query(None)
    execution_date__gte: date = Query(None)
    invoice_date__lte: date = Query(None)
    invoice_date__gte: date = Query(None)


class Balance(BaseModel):
    company_id: int
    amount: str
    last_deposit_date: date
    status: enums.BalanceStatus


class Expenses(BaseModel):
    company_id: int
    amount: str
    from_date: date
    to_date: date
