"""
SCM Use Cases — Vendor Operations.

عملیات مدیریت تأمین‌کنندگان.
"""
from dataclasses import dataclass
from uuid import uuid4

from ..dtos.scm_dtos import (
    CreateVendorDTO,
    UpdateVendorDTO,
    VendorResponseDTO,
    CreateVendorCategoryDTO,
    VendorCategoryResponseDTO,
)
from ...domain.entities.vendor import Vendor, VendorCategory, VendorStatus, VendorType
from ...domain.repositories.interfaces import IVendorRepository, IVendorCategoryRepository
from ...domain.exceptions import DuplicateVendorCodeError, VendorNotFoundError


@dataclass
class CreateVendorUseCase:
    """
    Use Case — ایجاد تأمین‌کننده جدید.

    Flow:
    1. بررسی یکتایی کد
    2. ایجاد entity دامنه
    3. اعتبارسنجی
    4. ذخیره
    5. بازگشت DTO
    """
    vendor_repo: IVendorRepository

    def execute(self, dto: CreateVendorDTO, tenant_id=None) -> VendorResponseDTO:
        # 1. Uniqueness check
        existing = self.vendor_repo.find_by_code(dto.vendor_code)
        if existing:
            raise DuplicateVendorCodeError(dto.vendor_code)

        # 2. Create domain entity
        vendor = Vendor(
            id=uuid4(),
            tenant_id=tenant_id,
            vendor_code=dto.vendor_code,
            vendor_name=dto.vendor_name,
            vendor_name_en=dto.vendor_name_en,
            vendor_type=VendorType(dto.vendor_type) if dto.vendor_type else VendorType.COMPANY,
            category_id=dto.category_id,
            status=VendorStatus.PENDING_APPROVAL,
            national_id=dto.national_id,
            economic_code=dto.economic_code,
            registration_number=dto.registration_number,
            phone=dto.phone,
            fax=dto.fax,
            email=dto.email,
            website=dto.website,
            representative_employee_id=dto.representative_employee_id,
            payment_terms_days=dto.payment_terms_days,
            credit_limit=dto.credit_limit,
            currency_code=dto.currency_code,
            notes=dto.notes,
        )

        # 3. Validate
        vendor.validate()

        # 4. Persist
        saved = self.vendor_repo.save(vendor)

        # 5. Return DTO
        return VendorResponseDTO(
            id=saved.id,
            vendor_code=saved.vendor_code,
            vendor_name=saved.vendor_name,
            vendor_name_en=saved.vendor_name_en,
            vendor_type=saved.vendor_type.value if saved.vendor_type else "",
            category_id=saved.category_id,
            status=saved.status.value if saved.status else "",
            national_id=saved.national_id,
            economic_code=saved.economic_code,
            phone=saved.phone,
            email=saved.email,
            website=saved.website,
            payment_terms_days=saved.payment_terms_days,
            credit_limit=saved.credit_limit,
            is_active=saved.is_active,
            created_at=saved.created_at,
        )


@dataclass
class UpdateVendorUseCase:
    """Use Case — بروزرسانی تأمین‌کننده."""
    vendor_repo: IVendorRepository

    def execute(self, vendor_id, dto: UpdateVendorDTO) -> VendorResponseDTO:
        vendor = self.vendor_repo.get_by_id(vendor_id)
        if not vendor:
            raise VendorNotFoundError(str(vendor_id))

        # Update fields
        if dto.vendor_name is not None:
            vendor.vendor_name = dto.vendor_name
        if dto.vendor_name_en is not None:
            vendor.vendor_name_en = dto.vendor_name_en
        if dto.vendor_type is not None:
            vendor.vendor_type = VendorType(dto.vendor_type)
        if dto.category_id is not None:
            vendor.category_id = dto.category_id
        if dto.phone is not None:
            vendor.phone = dto.phone
        if dto.fax is not None:
            vendor.fax = dto.fax
        if dto.email is not None:
            vendor.email = dto.email
        if dto.website is not None:
            vendor.website = dto.website
        if dto.representative_employee_id is not None:
            vendor.representative_employee_id = dto.representative_employee_id
        if dto.payment_terms_days is not None:
            vendor.payment_terms_days = dto.payment_terms_days
        if dto.credit_limit is not None:
            vendor.credit_limit = dto.credit_limit
        if dto.notes is not None:
            vendor.notes = dto.notes

        saved = self.vendor_repo.save(vendor)

        return VendorResponseDTO(
            id=saved.id,
            vendor_code=saved.vendor_code,
            vendor_name=saved.vendor_name,
            vendor_name_en=saved.vendor_name_en,
            vendor_type=saved.vendor_type.value if saved.vendor_type else "",
            category_id=saved.category_id,
            status=saved.status.value if saved.status else "",
            national_id=saved.national_id,
            economic_code=saved.economic_code,
            phone=saved.phone,
            email=saved.email,
            website=saved.website,
            payment_terms_days=saved.payment_terms_days,
            credit_limit=saved.credit_limit,
            is_active=saved.is_active,
            created_at=saved.created_at,
        )


@dataclass
class ActivateVendorUseCase:
    """Use Case — فعال‌سازی تأمین‌کننده."""
    vendor_repo: IVendorRepository

    def execute(self, vendor_id) -> VendorResponseDTO:
        vendor = self.vendor_repo.get_by_id(vendor_id)
        if not vendor:
            raise VendorNotFoundError(str(vendor_id))

        vendor.activate()
        saved = self.vendor_repo.save(vendor)

        return VendorResponseDTO(
            id=saved.id,
            vendor_code=saved.vendor_code,
            vendor_name=saved.vendor_name,
            vendor_name_en=saved.vendor_name_en,
            vendor_type=saved.vendor_type.value if saved.vendor_type else "",
            status=saved.status.value if saved.status else "",
            is_active=saved.is_active,
        )


@dataclass
class BlockVendorUseCase:
    """Use Case — مسدود کردن تأمین‌کننده."""
    vendor_repo: IVendorRepository

    def execute(self, vendor_id, reason: str = "") -> VendorResponseDTO:
        vendor = self.vendor_repo.get_by_id(vendor_id)
        if not vendor:
            raise VendorNotFoundError(str(vendor_id))

        vendor.block(reason)
        saved = self.vendor_repo.save(vendor)

        return VendorResponseDTO(
            id=saved.id,
            vendor_code=saved.vendor_code,
            vendor_name=saved.vendor_name,
            vendor_name_en=saved.vendor_name_en,
            vendor_type=saved.vendor_type.value if saved.vendor_type else "",
            status=saved.status.value if saved.status else "",
            is_active=saved.is_active,
        )


@dataclass
class CreateVendorCategoryUseCase:
    """Use Case — ایجاد دسته‌بندی تأمین‌کننده."""
    category_repo: IVendorCategoryRepository

    def execute(self, dto: CreateVendorCategoryDTO, tenant_id=None) -> VendorCategoryResponseDTO:
        category = VendorCategory(
            id=uuid4(),
            tenant_id=tenant_id,
            category_code=dto.category_code,
            category_name=dto.category_name,
            parent_category_id=dto.parent_category_id,
            description=dto.description,
            level=0,
        )

        if dto.parent_category_id:
            parent = self.category_repo.get_by_id(dto.parent_category_id)
            if parent:
                category.level = parent.level + 1

        saved = self.category_repo.save(category)

        return VendorCategoryResponseDTO(
            id=saved.id,
            category_code=saved.category_code,
            category_name=saved.category_name,
            parent_category_id=saved.parent_category_id,
            level=saved.level,
            is_active=saved.is_active,
        )
