"""
Physical Inventory Domain Entities.
"""
from dataclasses import dataclass
from datetime import date, datetime
from enum import Enum
from typing import Optional
from uuid import UUID

from shared.base_classes.entity import TenantEntity


class InventoryType(str, Enum):
    FULL = "FULL"
    PARTIAL = "PARTIAL"
    CYCLE_COUNT = "CYCLE_COUNT"


class PhysicalInventoryStatus(str, Enum):
    DRAFT = "DRAFT"
    IN_PROGRESS = "IN_PROGRESS"
    COUNTING = "COUNTING"
    COMPLETED = "COMPLETED"
    CANCELLED = "CANCELLED"


class InventoryLineStatus(str, Enum):
    PENDING = "PENDING"
    COUNTED = "COUNTED"
    VARIANCE_APPROVED = "VARIANCE_APPROVED"
    ADJUSTED = "ADJUSTED"


@dataclass
class PhysicalInventory(TenantEntity):
    """سند شمارش فیزیکی — Aggregate Root."""

    inventory_number: str = ""
    inventory_date: Optional[date] = None
    inventory_type: InventoryType = InventoryType.FULL

    warehouse_id: Optional[UUID] = None
    location_id: Optional[UUID] = None
    item_group_id: Optional[UUID] = None
    abc_class_filter: str = ""

    inventory_status: PhysicalInventoryStatus = PhysicalInventoryStatus.DRAFT
    is_blind_count: bool = False
    is_stock_frozen: bool = False

    required_count_times: int = 1
    variance_threshold_percent: float = 5.0

    scheduled_start_date: Optional[date] = None
    actual_start_date: Optional[date] = None
    completed_date: Optional[date] = None

    responsible_user_id: Optional[UUID] = None
    approved_by: Optional[UUID] = None
    approved_date: Optional[date] = None

    company_id: Optional[UUID] = None
    remarks: str = ""

    def start(self):
        self.inventory_status = PhysicalInventoryStatus.IN_PROGRESS
        self.actual_start_date = date.today()
        self.mark_updated()

    def complete(self):
        self.inventory_status = PhysicalInventoryStatus.COMPLETED
        self.completed_date = date.today()
        self.mark_updated()


@dataclass
class PhysicalInventoryLine(TenantEntity):
    """اقلام شمارش."""

    physical_inventory_id: Optional[UUID] = None
    line_number: int = 0

    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

    book_quantity: float = 0.0
    uom_id: Optional[UUID] = None

    # Counts
    first_count_quantity: Optional[float] = None
    first_count_by: Optional[UUID] = None
    first_count_date: Optional[datetime] = None

    second_count_quantity: Optional[float] = None
    second_count_by: Optional[UUID] = None
    second_count_date: Optional[datetime] = None

    third_count_quantity: Optional[float] = None
    third_count_by: Optional[UUID] = None
    third_count_date: Optional[datetime] = None

    # Final
    final_count_quantity: Optional[float] = None
    variance_quantity: float = 0.0
    variance_percent: float = 0.0
    variance_value: float = 0.0

    line_status: InventoryLineStatus = InventoryLineStatus.PENDING
    variance_reason_code: str = ""
    variance_remarks: str = ""
    approved_by: Optional[UUID] = None
    approved_date: Optional[date] = None

    adjustment_sle_id: Optional[UUID] = None


@dataclass
class CycleCountSchedule(TenantEntity):
    """برنامه شمارش چرخشی."""

    schedule_name: str = ""
    warehouse_id: Optional[UUID] = None
    count_frequency_days: int = 30

    item_group_id: Optional[UUID] = None
    abc_class: str = ""
    high_value_items_only: bool = False

    next_count_date: Optional[date] = None
    last_count_date: Optional[date] = None

    is_active: bool = True
