"""
SCM Domain Entities — Goods Receipt.

رسید کالا بر اساس سفارش خرید.
"""
from dataclasses import dataclass, field
from datetime import date, datetime
from decimal import Decimal
from enum import Enum
from typing import Optional, List
from uuid import UUID

from shared.base_classes.entity import TenantEntity


class GRStatus(str, Enum):
    DRAFT = "DRAFT"
    CONFIRMED = "CONFIRMED"
    CANCELLED = "CANCELLED"


@dataclass
class GoodsReceiptLine(TenantEntity):
    """آیتم رسید کالا."""
    receipt_id: Optional[UUID] = None
    line_number: int = 0
    po_line_id: Optional[UUID] = None
    item_id: Optional[UUID] = None
    item_code: str = ""
    item_name: str = ""
    ordered_quantity: Decimal = Decimal("0")
    received_quantity: Decimal = Decimal("0")
    accepted_quantity: Decimal = Decimal("0")
    rejected_quantity: Decimal = Decimal("0")
    uom_id: Optional[UUID] = None
    uom_code: str = ""
    unit_cost: Decimal = Decimal("0")
    line_total: Decimal = Decimal("0")
    warehouse_id: Optional[UUID] = None
    warehouse_name: str = ""
    storage_location_id: Optional[UUID] = None
    batch_number: str = ""
    serial_numbers: List[str] = field(default_factory=list)
    inspection_required: bool = False
    notes: str = ""

    def calculate_total(self):
        self.line_total = self.accepted_quantity * self.unit_cost


@dataclass
class GoodsReceipt(TenantEntity):
    """رسید کالا — Aggregate Root."""
    gr_number: str = ""
    status: GRStatus = GRStatus.DRAFT

    # Source
    po_id: Optional[UUID] = None
    po_number: str = ""
    vendor_id: Optional[UUID] = None
    vendor_name: str = ""

    # Receiver
    receiver_id: Optional[UUID] = None
    receiver_name: str = ""

    # Dates
    receipt_date: Optional[date] = None
    posting_date: Optional[date] = None

    # Totals
    total_amount: Decimal = Decimal("0")
    currency_code: str = "IRR"

    # Delivery
    delivery_note_number: str = ""
    transporter: str = ""

    notes: str = ""

    # Lines
    lines: List[GoodsReceiptLine] = field(default_factory=list)

    def calculate_totals(self):
        for line in self.lines:
            line.calculate_total()
        self.total_amount = sum(line.line_total for line in self.lines)

    def confirm(self):
        """تأیید رسید."""
        if self.status != GRStatus.DRAFT:
            raise ValueError("Only DRAFT receipts can be confirmed")
        if not self.lines:
            raise ValueError("Receipt must have at least one line")
        self.status = GRStatus.CONFIRMED

    def cancel(self):
        """لغو رسید."""
        if self.status == GRStatus.CANCELLED:
            raise ValueError("Already cancelled")
        self.status = GRStatus.CANCELLED

    def validate(self):
        if not self.gr_number:
            raise ValueError("GR number is required")
        if not self.po_id:
            raise ValueError("PO reference is required")
