"""
SCM Domain Entities — Purchase Return.

برگشت از خرید.
"""
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 ReturnStatus(str, Enum):
    DRAFT = "DRAFT"
    PENDING_APPROVAL = "PENDING_APPROVAL"
    APPROVED = "APPROVED"
    SENT = "SENT"
    COMPLETED = "COMPLETED"
    CANCELLED = "CANCELLED"


class ReturnReason(str, Enum):
    DEFECTIVE = "DEFECTIVE"
    WRONG_ITEM = "WRONG_ITEM"
    EXCESS_QUANTITY = "EXCESS_QUANTITY"
    QUALITY_ISSUE = "QUALITY_ISSUE"
    DAMAGED = "DAMAGED"
    OTHER = "OTHER"


@dataclass
class PurchaseReturnLine(TenantEntity):
    """آیتم برگشت از خرید."""
    return_id: Optional[UUID] = None
    line_number: int = 0
    gr_line_id: Optional[UUID] = None
    po_line_id: Optional[UUID] = None
    item_id: Optional[UUID] = None
    item_code: str = ""
    item_name: str = ""
    return_quantity: Decimal = Decimal("0")
    uom_id: Optional[UUID] = None
    uom_code: str = ""
    unit_cost: Decimal = Decimal("0")
    line_total: Decimal = Decimal("0")
    reason: ReturnReason = ReturnReason.OTHER
    reason_detail: str = ""
    warehouse_id: Optional[UUID] = None
    batch_number: str = ""
    serial_numbers: List[str] = field(default_factory=list)
    notes: str = ""

    def calculate_total(self):
        self.line_total = self.return_quantity * self.unit_cost


@dataclass
class PurchaseReturn(TenantEntity):
    """برگشت از خرید — Aggregate Root."""
    return_number: str = ""
    status: ReturnStatus = ReturnStatus.DRAFT

    # Source
    po_id: Optional[UUID] = None
    po_number: str = ""
    gr_id: Optional[UUID] = None
    gr_number: str = ""
    vendor_id: Optional[UUID] = None
    vendor_name: str = ""

    # Requester
    requester_id: Optional[UUID] = None
    requester_name: str = ""

    # Dates
    return_date: Optional[date] = None

    # Totals
    total_amount: Decimal = Decimal("0")
    currency_code: str = "IRR"

    # Approval
    approved_by_id: Optional[UUID] = None
    approved_at: Optional[datetime] = None

    notes: str = ""
    lines: List[PurchaseReturnLine] = 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 submit(self):
        if self.status != ReturnStatus.DRAFT:
            raise ValueError("Only DRAFT returns can be submitted")
        if not self.lines:
            raise ValueError("Return must have at least one line")
        self.status = ReturnStatus.PENDING_APPROVAL

    def approve(self, approved_by: UUID):
        if self.status != ReturnStatus.PENDING_APPROVAL:
            raise ValueError("Only PENDING_APPROVAL returns can be approved")
        self.status = ReturnStatus.APPROVED
        self.approved_by_id = approved_by
        self.approved_at = datetime.utcnow()

    def complete(self):
        if self.status not in (ReturnStatus.APPROVED, ReturnStatus.SENT):
            raise ValueError("Cannot complete this return")
        self.status = ReturnStatus.COMPLETED

    def cancel(self):
        if self.status in (ReturnStatus.COMPLETED, ReturnStatus.CANCELLED):
            raise ValueError("Cannot cancel this return")
        self.status = ReturnStatus.CANCELLED

    def validate(self):
        if not self.return_number:
            raise ValueError("Return number is required")
        if not self.vendor_id:
            raise ValueError("Vendor is required")
