"""Sales services."""

from __future__ import annotations

from dataclasses import dataclass, field

from ..common.value_objects import Money
from .entities import SalesOrder
from .exceptions import InvalidSalesOrderError
from .policies import DefaultSalesOrderTransitionPolicy, SalesOrderTransitionPolicy


@dataclass(frozen=True)
class SalesPricingService:
    def calculate_subtotal(self, order: SalesOrder) -> Money:
        return order.amount_untaxed

    def calculate_discount(self, order: SalesOrder) -> Money:
        return order.amount_discount

    def calculate_total(self, order: SalesOrder) -> Money:
        return order.amount_total


@dataclass
class SalesWorkflowService:
    transition_policy: SalesOrderTransitionPolicy = field(default_factory=DefaultSalesOrderTransitionPolicy)
    pricing_service: SalesPricingService = field(default_factory=SalesPricingService)

    def send(self, order: SalesOrder) -> SalesOrder:
        self._validate_order(order)
        order.send(policy=self.transition_policy)
        return order

    def confirm(self, order: SalesOrder) -> SalesOrder:
        self._validate_order(order)
        order.confirm(policy=self.transition_policy)
        return order

    def complete(self, order: SalesOrder) -> SalesOrder:
        self._validate_order(order)
        order.mark_done(policy=self.transition_policy)
        return order

    def cancel(self, order: SalesOrder) -> SalesOrder:
        self._validate_order(order)
        order.cancel(policy=self.transition_policy)
        return order

    def amounts(self, order: SalesOrder) -> dict[str, object]:
        self._validate_order(order)
        return {
            "subtotal": self.pricing_service.calculate_subtotal(order),
            "discount": self.pricing_service.calculate_discount(order),
            "total": self.pricing_service.calculate_total(order),
            "state": order.state,
        }

    def _validate_order(self, order: SalesOrder) -> None:
        if not isinstance(order, SalesOrder):
            raise InvalidSalesOrderError("order must be a SalesOrder instance")
