"""
SCM Domain Entities — Purchase Requisition.

درخواست خرید و آیتم‌های آن.
"""
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 PRStatus(str, Enum):
    DRAFT = "DRAFT"
    PENDING_APPROVAL = "PENDING_APPROVAL"
    APPROVED = "APPROVED"
    REJECTED = "REJECTED"
    CONVERTED = "CONVERTED"
    PARTIALLY_CONVERTED = "PARTIALLY_CONVERTED"
    CANCELLED = "CANCELLED"


class PRPriority(str, Enum):
    LOW = "LOW"
    NORMAL = "NORMAL"
    HIGH = "HIGH"
    URGENT = "URGENT"


@dataclass
class PurchaseRequisitionLine(TenantEntity):
    """آیتم درخواست خرید."""
    requisition_id: Optional[UUID] = None
    line_number: int = 0
    item_id: Optional[UUID] = None
    item_code: str = ""
    item_name: str = ""
    description: str = ""
    quantity: Decimal = Decimal("0")
    uom_id: Optional[UUID] = None
    uom_code: str = ""
    estimated_unit_price: Decimal = Decimal("0")
    estimated_total_price: Decimal = Decimal("0")
    required_date: Optional[date] = None
    warehouse_id: Optional[UUID] = None
    warehouse_name: str = ""
    preferred_vendor_id: Optional[UUID] = None
    notes: str = ""
    is_converted: bool = False
    converted_po_id: Optional[UUID] = None

    def calculate_total(self):
        self.estimated_total_price = self.quantity * self.estimated_unit_price


@dataclass
class PurchaseRequisition(TenantEntity):
    """درخواست خرید — Aggregate Root."""
    pr_number: str = ""
    title: str = ""
    description: str = ""
    status: PRStatus = PRStatus.DRAFT
    priority: PRPriority = PRPriority.NORMAL

    # Requester
    requester_id: Optional[UUID] = None
    requester_name: str = ""
    department: str = ""

    # Dates
    request_date: Optional[date] = None
    required_date: Optional[date] = None

    # Totals
    total_estimated_amount: Decimal = Decimal("0")
    currency_code: str = "IRR"

    # Approval
    approved_by_id: Optional[UUID] = None
    approved_at: Optional[datetime] = None
    rejection_reason: str = ""

    # Lines
    lines: List[PurchaseRequisitionLine] = field(default_factory=list)

    notes: str = ""

    def calculate_totals(self):
        """محاسبه جمع کل."""
        self.total_estimated_amount = sum(
            line.estimated_total_price for line in self.lines
        )

    def submit(self):
        """ارسال برای تأیید."""
        if self.status != PRStatus.DRAFT:
            raise ValueError("Only DRAFT PRs can be submitted")
        if not self.lines:
            raise ValueError("PR must have at least one line")
        self.status = PRStatus.PENDING_APPROVAL

    def approve(self, approved_by: UUID):
        """تأیید درخواست."""
        if self.status != PRStatus.PENDING_APPROVAL:
            raise ValueError("Only PENDING_APPROVAL PRs can be approved")
        self.status = PRStatus.APPROVED
        self.approved_by_id = approved_by
        self.approved_at = datetime.utcnow()

    def reject(self, reason: str):
        """رد درخواست."""
        if self.status != PRStatus.PENDING_APPROVAL:
            raise ValueError("Only PENDING_APPROVAL PRs can be rejected")
        self.status = PRStatus.REJECTED
        self.rejection_reason = reason

    def cancel(self):
        """لغو درخواست."""
        if self.status in (PRStatus.CONVERTED, PRStatus.CANCELLED):
            raise ValueError("Cannot cancel this PR")
        self.status = PRStatus.CANCELLED

    def mark_converted(self):
        """تبدیل شده به PO."""
        all_converted = all(line.is_converted for line in self.lines)
        if all_converted:
            self.status = PRStatus.CONVERTED
        else:
            self.status = PRStatus.PARTIALLY_CONVERTED

    def validate(self):
        if not self.pr_number:
            raise ValueError("PR number is required")
        if not self.requester_id:
            raise ValueError("Requester is required")
