"""
Reservation & Allocation Domain Entities.
"""
from dataclasses import dataclass
from datetime import date
from enum import Enum
from typing import Optional
from uuid import UUID

from shared.base_classes.entity import TenantEntity


class ReservationStatus(str, Enum):
    ACTIVE = "ACTIVE"
    PARTIALLY_ALLOCATED = "PARTIALLY_ALLOCATED"
    FULLY_ALLOCATED = "FULLY_ALLOCATED"
    EXPIRED = "EXPIRED"
    CANCELLED = "CANCELLED"


class AllocationStatus(str, Enum):
    ALLOCATED = "ALLOCATED"
    PARTIALLY_PICKED = "PARTIALLY_PICKED"
    FULLY_PICKED = "FULLY_PICKED"
    CANCELLED = "CANCELLED"


@dataclass
class StockReservation(TenantEntity):
    """رزرو موجودی."""

    reservation_number: str = ""
    reservation_date: Optional[date] = None

    item_id: Optional[UUID] = None
    warehouse_id: Optional[UUID] = None
    location_id: Optional[UUID] = None
    batch_id: Optional[UUID] = None
    serial_number_id: Optional[UUID] = None

    reserved_quantity: float = 0.0
    allocated_quantity: float = 0.0
    uom_id: Optional[UUID] = None

    source_document_type: str = ""
    source_document_id: Optional[UUID] = None
    source_document_line_id: Optional[UUID] = None

    priority_level: int = 5
    expiry_date: Optional[date] = None
    reservation_status: ReservationStatus = ReservationStatus.ACTIVE

    required_by_date: Optional[date] = None
    requested_by_user_id: Optional[UUID] = None
    remarks: str = ""

    company_id: Optional[UUID] = None
    cancelled_at: Optional[date] = None
    cancelled_by: Optional[UUID] = None

    def cancel(self, user_id: Optional[UUID] = None):
        self.reservation_status = ReservationStatus.CANCELLED
        self.cancelled_at = date.today()
        self.cancelled_by = user_id
        self.mark_updated(user_id)


@dataclass
class StockAllocation(TenantEntity):
    """تخصیص موجودی."""

    allocation_number: str = ""
    allocation_date: Optional[date] = None
    reservation_id: Optional[UUID] = None

    item_id: Optional[UUID] = None
    warehouse_id: Optional[UUID] = None
    location_id: Optional[UUID] = None
    batch_id: Optional[UUID] = None
    serial_number_id: Optional[UUID] = None

    allocated_quantity: float = 0.0
    picked_quantity: float = 0.0
    uom_id: Optional[UUID] = None

    source_document_type: str = ""
    source_document_id: Optional[UUID] = None
    source_document_line_id: Optional[UUID] = None

    allocation_status: AllocationStatus = AllocationStatus.ALLOCATED
    picking_user_id: Optional[UUID] = None

    company_id: Optional[UUID] = None
