"""
SCM Use Cases — Goods Receipt Operations.

عملیات مدیریت رسید کالا.
"""
from dataclasses import dataclass
from datetime import date
from decimal import Decimal
from uuid import uuid4

from ..dtos.scm_dtos import CreateGRDTO, GRResponseDTO
from ...domain.entities.goods_receipt import GoodsReceipt, GoodsReceiptLine, GRStatus
from ...domain.repositories.interfaces import IGoodsReceiptRepository, IPurchaseOrderRepository
from ...domain.exceptions import GRNotFoundError


@dataclass
class CreateGRUseCase:
    """Use Case — ایجاد رسید کالا."""
    gr_repo: IGoodsReceiptRepository
    po_repo: IPurchaseOrderRepository = None

    def execute(self, dto: CreateGRDTO, tenant_id=None) -> GRResponseDTO:
        lines = []
        for idx, line_dto in enumerate(dto.lines, start=1):
            line = GoodsReceiptLine(
                id=uuid4(),
                tenant_id=tenant_id,
                line_number=idx,
                po_line_id=line_dto.po_line_id,
                item_id=line_dto.item_id,
                item_code=line_dto.item_code,
                item_name=line_dto.item_name,
                received_quantity=Decimal(line_dto.received_quantity),
                accepted_quantity=Decimal(line_dto.accepted_quantity),
                rejected_quantity=Decimal(line_dto.rejected_quantity),
                uom_id=line_dto.uom_id,
                uom_code=line_dto.uom_code,
                unit_cost=Decimal(line_dto.unit_cost),
                warehouse_id=line_dto.warehouse_id,
                warehouse_name=line_dto.warehouse_name,
                storage_location_id=line_dto.storage_location_id,
                batch_number=line_dto.batch_number,
                serial_numbers=line_dto.serial_numbers,
                inspection_required=line_dto.inspection_required,
                notes=line_dto.notes,
            )
            lines.append(line)

        gr = GoodsReceipt(
            id=uuid4(),
            tenant_id=tenant_id,
            gr_number=dto.gr_number,
            status=GRStatus.DRAFT,
            po_id=dto.po_id,
            po_number=dto.po_number,
            vendor_id=dto.vendor_id,
            vendor_name=dto.vendor_name,
            receiver_id=dto.receiver_id,
            receiver_name=dto.receiver_name,
            receipt_date=dto.receipt_date or date.today(),
            delivery_note_number=dto.delivery_note_number,
            transporter=dto.transporter,
            currency_code=dto.currency_code,
            notes=dto.notes,
            lines=lines,
        )
        gr.calculate_totals()
        gr.validate()

        saved = self.gr_repo.save(gr)

        return GRResponseDTO(
            id=saved.id,
            gr_number=saved.gr_number,
            status=saved.status.value if saved.status else "",
            po_number=saved.po_number,
            vendor_name=saved.vendor_name,
            receiver_name=saved.receiver_name,
            receipt_date=saved.receipt_date,
            total_amount=str(saved.total_amount),
            created_at=saved.created_at,
        )


@dataclass
class ConfirmGRUseCase:
    """Use Case — تأیید رسید کالا و بروزرسانی PO."""
    gr_repo: IGoodsReceiptRepository
    po_repo: IPurchaseOrderRepository = None

    def execute(self, gr_id) -> GRResponseDTO:
        gr = self.gr_repo.get_by_id(gr_id)
        if not gr:
            raise GRNotFoundError(str(gr_id))

        gr.confirm()
        saved = self.gr_repo.save(gr)

        # Update PO receipt status
        if self.po_repo and saved.po_id:
            po = self.po_repo.get_by_id(saved.po_id)
            if po:
                for gr_line in saved.lines:
                    for po_line in po.lines:
                        if po_line.id == gr_line.po_line_id:
                            po_line.received_quantity += gr_line.accepted_quantity
                po.update_receipt_status()
                self.po_repo.save(po)

        return GRResponseDTO(
            id=saved.id,
            gr_number=saved.gr_number,
            status=saved.status.value if saved.status else "",
            po_number=saved.po_number,
            vendor_name=saved.vendor_name,
            receipt_date=saved.receipt_date,
            total_amount=str(saved.total_amount),
        )


@dataclass
class CancelGRUseCase:
    """Use Case — لغو رسید کالا."""
    gr_repo: IGoodsReceiptRepository

    def execute(self, gr_id) -> GRResponseDTO:
        gr = self.gr_repo.get_by_id(gr_id)
        if not gr:
            raise GRNotFoundError(str(gr_id))

        gr.cancel()
        saved = self.gr_repo.save(gr)

        return GRResponseDTO(
            id=saved.id,
            gr_number=saved.gr_number,
            status=saved.status.value if saved.status else "",
        )
