"""
SCM Use Cases — Purchase Requisition Operations.

عملیات مدیریت درخواست خرید.
"""
from dataclasses import dataclass
from datetime import date
from decimal import Decimal
from uuid import uuid4

from ..dtos.scm_dtos import CreatePRDTO, PRResponseDTO
from ...domain.entities.purchase_requisition import (
    PurchaseRequisition,
    PurchaseRequisitionLine,
    PRStatus,
    PRPriority,
)
from ...domain.repositories.interfaces import IPurchaseRequisitionRepository
from ...domain.exceptions import PRNotFoundError


@dataclass
class CreatePRUseCase:
    """Use Case — ایجاد درخواست خرید."""
    pr_repo: IPurchaseRequisitionRepository

    def execute(self, dto: CreatePRDTO, tenant_id=None) -> PRResponseDTO:
        lines = []
        for idx, line_dto in enumerate(dto.lines, start=1):
            line = PurchaseRequisitionLine(
                id=uuid4(),
                tenant_id=tenant_id,
                line_number=idx,
                item_id=line_dto.item_id,
                item_code=line_dto.item_code,
                item_name=line_dto.item_name,
                description=line_dto.description,
                quantity=Decimal(line_dto.quantity),
                uom_id=line_dto.uom_id,
                uom_code=line_dto.uom_code,
                estimated_unit_price=Decimal(line_dto.estimated_unit_price),
                required_date=line_dto.required_date,
                warehouse_id=line_dto.warehouse_id,
                warehouse_name=line_dto.warehouse_name,
                preferred_vendor_id=line_dto.preferred_vendor_id,
                notes=line_dto.notes,
            )
            line.calculate_total()
            lines.append(line)

        pr = PurchaseRequisition(
            id=uuid4(),
            tenant_id=tenant_id,
            pr_number=dto.pr_number,
            title=dto.title,
            description=dto.description,
            status=PRStatus.DRAFT,
            priority=PRPriority(dto.priority) if dto.priority else PRPriority.NORMAL,
            requester_id=dto.requester_id,
            requester_name=dto.requester_name,
            department=dto.department,
            request_date=date.today(),
            required_date=dto.required_date,
            currency_code=dto.currency_code,
            notes=dto.notes,
            lines=lines,
        )
        pr.calculate_totals()
        pr.validate()

        saved = self.pr_repo.save(pr)

        return PRResponseDTO(
            id=saved.id,
            pr_number=saved.pr_number,
            title=saved.title,
            status=saved.status.value if saved.status else "",
            priority=saved.priority.value if saved.priority else "",
            requester_name=saved.requester_name,
            department=saved.department,
            request_date=saved.request_date,
            required_date=saved.required_date,
            total_estimated_amount=str(saved.total_estimated_amount),
            currency_code=saved.currency_code,
            created_at=saved.created_at,
        )


@dataclass
class SubmitPRUseCase:
    """Use Case — ارسال درخواست خرید برای تأیید."""
    pr_repo: IPurchaseRequisitionRepository

    def execute(self, pr_id) -> PRResponseDTO:
        pr = self.pr_repo.get_by_id(pr_id)
        if not pr:
            raise PRNotFoundError(str(pr_id))

        pr.submit()
        saved = self.pr_repo.save(pr)

        return PRResponseDTO(
            id=saved.id,
            pr_number=saved.pr_number,
            title=saved.title,
            status=saved.status.value if saved.status else "",
            priority=saved.priority.value if saved.priority else "",
            requester_name=saved.requester_name,
        )


@dataclass
class ApprovePRUseCase:
    """Use Case — تأیید درخواست خرید."""
    pr_repo: IPurchaseRequisitionRepository

    def execute(self, pr_id, approved_by) -> PRResponseDTO:
        pr = self.pr_repo.get_by_id(pr_id)
        if not pr:
            raise PRNotFoundError(str(pr_id))

        pr.approve(approved_by)
        saved = self.pr_repo.save(pr)

        return PRResponseDTO(
            id=saved.id,
            pr_number=saved.pr_number,
            title=saved.title,
            status=saved.status.value if saved.status else "",
        )


@dataclass
class RejectPRUseCase:
    """Use Case — رد درخواست خرید."""
    pr_repo: IPurchaseRequisitionRepository

    def execute(self, pr_id, reason: str = "") -> PRResponseDTO:
        pr = self.pr_repo.get_by_id(pr_id)
        if not pr:
            raise PRNotFoundError(str(pr_id))

        pr.reject(reason)
        saved = self.pr_repo.save(pr)

        return PRResponseDTO(
            id=saved.id,
            pr_number=saved.pr_number,
            title=saved.title,
            status=saved.status.value if saved.status else "",
        )


@dataclass
class CancelPRUseCase:
    """Use Case — لغو درخواست خرید."""
    pr_repo: IPurchaseRequisitionRepository

    def execute(self, pr_id) -> PRResponseDTO:
        pr = self.pr_repo.get_by_id(pr_id)
        if not pr:
            raise PRNotFoundError(str(pr_id))

        pr.cancel()
        saved = self.pr_repo.save(pr)

        return PRResponseDTO(
            id=saved.id,
            pr_number=saved.pr_number,
            title=saved.title,
            status=saved.status.value if saved.status else "",
        )
