# app/exceptions/vendor.py
"""
Vendor management specific exceptions.
"""

from typing import Any

from .base import (
    AuthorizationException,
    BusinessLogicException,
    ConflictException,
    ResourceNotFoundException,
    ValidationException,
)


class VendorNotFoundException(ResourceNotFoundException):
    """Raised when a vendor is not found."""

    def __init__(self, vendor_identifier: str, identifier_type: str = "code"):
        if identifier_type.lower() == "id":
            message = f"Vendor with ID '{vendor_identifier}' not found"
        else:
            message = f"Vendor with code '{vendor_identifier}' not found"

        super().__init__(
            resource_type="Vendor",
            identifier=vendor_identifier,
            message=message,
            error_code="VENDOR_NOT_FOUND",
        )


class VendorAlreadyExistsException(ConflictException):
    """Raised when trying to create a vendor that already exists."""

    def __init__(self, vendor_code: str):
        super().__init__(
            message=f"Vendor with code '{vendor_code}' already exists",
            error_code="VENDOR_ALREADY_EXISTS",
            details={"vendor_code": vendor_code},
        )


class VendorNotActiveException(BusinessLogicException):
    """Raised when trying to perform operations on inactive vendor."""

    def __init__(self, vendor_code: str):
        super().__init__(
            message=f"Vendor '{vendor_code}' is not active",
            error_code="VENDOR_NOT_ACTIVE",
            details={"vendor_code": vendor_code},
        )


class VendorNotVerifiedException(BusinessLogicException):
    """Raised when trying to perform operations requiring verified vendor."""

    def __init__(self, vendor_code: str):
        super().__init__(
            message=f"Vendor '{vendor_code}' is not verified",
            error_code="VENDOR_NOT_VERIFIED",
            details={"vendor_code": vendor_code},
        )


class UnauthorizedVendorAccessException(AuthorizationException):
    """Raised when user tries to access vendor they don't own."""

    def __init__(self, vendor_code: str, user_id: int | None = None):
        details = {"vendor_code": vendor_code}
        if user_id:
            details["user_id"] = user_id

        super().__init__(
            message=f"Unauthorized access to vendor '{vendor_code}'",
            error_code="UNAUTHORIZED_VENDOR_ACCESS",
            details=details,
        )


class InvalidVendorDataException(ValidationException):
    """Raised when vendor data is invalid or incomplete."""

    def __init__(
        self,
        message: str = "Invalid vendor data",
        field: str | None = None,
        details: dict[str, Any] | None = None,
    ):
        super().__init__(
            message=message,
            field=field,
            details=details,
        )
        self.error_code = "INVALID_VENDOR_DATA"


class VendorValidationException(ValidationException):
    """Raised when vendor validation fails."""

    def __init__(
        self,
        message: str = "Vendor validation failed",
        field: str | None = None,
        validation_errors: dict[str, str] | None = None,
    ):
        details = {}
        if validation_errors:
            details["validation_errors"] = validation_errors

        super().__init__(
            message=message,
            field=field,
            details=details,
        )
        self.error_code = "VENDOR_VALIDATION_FAILED"


class IncompleteVendorDataException(ValidationException):
    """Raised when vendor data is missing required fields."""

    def __init__(
        self,
        vendor_code: str,
        missing_fields: list,
    ):
        super().__init__(
            message=f"Vendor '{vendor_code}' is missing required fields: {', '.join(missing_fields)}",
            details={
                "vendor_code": vendor_code,
                "missing_fields": missing_fields,
            },
        )
        self.error_code = "INCOMPLETE_VENDOR_DATA"


class MaxVendorsReachedException(BusinessLogicException):
    """Raised when user tries to create more vendors than allowed."""

    def __init__(self, max_vendors: int, user_id: int | None = None):
        details = {"max_vendors": max_vendors}
        if user_id:
            details["user_id"] = user_id

        super().__init__(
            message=f"Maximum number of vendors reached ({max_vendors})",
            error_code="MAX_VENDORS_REACHED",
            details=details,
        )


class VendorAccessDeniedException(AuthorizationException):
    """Raised when no vendor context is available for an authenticated endpoint."""

    def __init__(self, message: str = "No vendor context available"):
        super().__init__(
            message=message,
            error_code="VENDOR_ACCESS_DENIED",
        )


class VendorOwnerOnlyException(AuthorizationException):
    """Raised when operation requires vendor owner role."""

    def __init__(self, operation: str, vendor_code: str | None = None):
        details = {"operation": operation}
        if vendor_code:
            details["vendor_code"] = vendor_code

        super().__init__(
            message=f"Operation '{operation}' requires vendor owner role",
            error_code="VENDOR_OWNER_ONLY",
            details=details,
        )


class InsufficientVendorPermissionsException(AuthorizationException):
    """Raised when user lacks required vendor permission."""

    def __init__(self, required_permission: str, vendor_code: str | None = None):
        details = {"required_permission": required_permission}
        if vendor_code:
            details["vendor_code"] = vendor_code

        super().__init__(
            message=f"Permission required: {required_permission}",
            error_code="INSUFFICIENT_VENDOR_PERMISSIONS",
            details=details,
        )
