# app/exceptions/admin.py
"""
Admin operations specific exceptions.
"""

from typing import Any

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


class UserNotFoundException(ResourceNotFoundException):
    """Raised when user is not found in admin operations."""

    def __init__(self, user_identifier: str, identifier_type: str = "ID"):
        if identifier_type.lower() == "username":
            message = f"User with username '{user_identifier}' not found"
        elif identifier_type.lower() == "email":
            message = f"User with email '{user_identifier}' not found"
        else:
            message = f"User with ID '{user_identifier}' not found"

        super().__init__(
            resource_type="User",
            identifier=user_identifier,
            message=message,
            error_code="USER_NOT_FOUND",
        )


class UserStatusChangeException(BusinessLogicException):
    """Raised when user status cannot be changed."""

    def __init__(
        self,
        user_id: int,
        current_status: str,
        attempted_action: str,
        reason: str | None = None,
    ):
        message = f"Cannot {attempted_action} user {user_id} (current status: {current_status})"
        if reason:
            message += f": {reason}"

        super().__init__(
            message=message,
            error_code="USER_STATUS_CHANGE_FAILED",
            details={
                "user_id": user_id,
                "current_status": current_status,
                "attempted_action": attempted_action,
                "reason": reason,
            },
        )


class ShopVerificationException(BusinessLogicException):
    """Raised when shop verification fails."""

    def __init__(
        self,
        shop_id: int,
        reason: str,
        current_verification_status: bool | None = None,
    ):
        details = {
            "shop_id": shop_id,
            "reason": reason,
        }

        if current_verification_status is not None:
            details["current_verification_status"] = current_verification_status

        super().__init__(
            message=f"Shop verification failed for shop {shop_id}: {reason}",
            error_code="SHOP_VERIFICATION_FAILED",
            details=details,
        )


class AdminOperationException(BusinessLogicException):
    """Raised when admin operation fails."""

    def __init__(
        self,
        operation: str,
        reason: str,
        target_type: str | None = None,
        target_id: str | None = None,
    ):
        message = f"Admin operation '{operation}' failed: {reason}"

        details = {
            "operation": operation,
            "reason": reason,
        }

        if target_type:
            details["target_type"] = target_type
        if target_id:
            details["target_id"] = target_id

        super().__init__(
            message=message,
            error_code="ADMIN_OPERATION_FAILED",
            details=details,
        )


class CannotModifyAdminException(AuthorizationException):
    """Raised when trying to modify another admin user."""

    def __init__(self, target_user_id: int, admin_user_id: int):
        super().__init__(
            message=f"Cannot modify admin user {target_user_id}",
            error_code="CANNOT_MODIFY_ADMIN",
            details={
                "target_user_id": target_user_id,
                "admin_user_id": admin_user_id,
            },
        )


class CannotModifySelfException(BusinessLogicException):
    """Raised when admin tries to modify their own status."""

    def __init__(self, user_id: int, operation: str):
        super().__init__(
            message=f"Cannot perform '{operation}' on your own account",
            error_code="CANNOT_MODIFY_SELF",
            details={
                "user_id": user_id,
                "operation": operation,
            },
        )


class InvalidAdminActionException(ValidationException):
    """Raised when admin action is invalid."""

    def __init__(
        self,
        action: str,
        reason: str,
        valid_actions: list | None = None,
    ):
        details = {
            "action": action,
            "reason": reason,
        }

        if valid_actions:
            details["valid_actions"] = valid_actions

        super().__init__(
            message=f"Invalid admin action '{action}': {reason}",
            details=details,
        )
        self.error_code = "INVALID_ADMIN_ACTION"


class BulkOperationException(BusinessLogicException):
    """Raised when bulk admin operation fails."""

    def __init__(
        self,
        operation: str,
        total_items: int,
        failed_items: int,
        errors: dict[str, Any] | None = None,
    ):
        message = f"Bulk {operation} completed with errors: {failed_items}/{total_items} failed"

        details = {
            "operation": operation,
            "total_items": total_items,
            "failed_items": failed_items,
            "success_items": total_items - failed_items,
        }

        if errors:
            details["errors"] = errors

        super().__init__(
            message=message,
            error_code="BULK_OPERATION_PARTIAL_FAILURE",
            details=details,
        )


class ConfirmationRequiredException(BusinessLogicException):
    """Raised when a destructive operation requires explicit confirmation."""

    def __init__(
        self,
        operation: str,
        message: str | None = None,
        confirmation_param: str = "confirm",
    ):
        if not message:
            message = f"Operation '{operation}' requires confirmation parameter: {confirmation_param}=true"

        super().__init__(
            message=message,
            error_code="CONFIRMATION_REQUIRED",
            details={
                "operation": operation,
                "confirmation_param": confirmation_param,
            },
        )


class VendorVerificationException(BusinessLogicException):
    """Raised when vendor verification fails."""

    def __init__(
        self,
        vendor_id: int,
        reason: str,
        current_verification_status: bool | None = None,
    ):
        details = {
            "vendor_id": vendor_id,
            "reason": reason,
        }

        if current_verification_status is not None:
            details["current_verification_status"] = current_verification_status

        super().__init__(
            message=f"Vendor verification failed for vendor {vendor_id}: {reason}",
            error_code="VENDOR_VERIFICATION_FAILED",
            details=details,
        )


class UserCannotBeDeletedException(BusinessLogicException):
    """Raised when a user cannot be deleted due to ownership constraints."""

    def __init__(self, user_id: int, reason: str, owned_count: int = 0):
        details = {
            "user_id": user_id,
            "reason": reason,
        }
        if owned_count > 0:
            details["owned_companies_count"] = owned_count

        super().__init__(
            message=f"Cannot delete user {user_id}: {reason}",
            error_code="USER_CANNOT_BE_DELETED",
            details=details,
        )


class UserRoleChangeException(BusinessLogicException):
    """Raised when user role cannot be changed."""

    def __init__(self, user_id: int, current_role: str, target_role: str, reason: str):
        super().__init__(
            message=f"Cannot change user {user_id} role from {current_role} to {target_role}: {reason}",
            error_code="USER_ROLE_CHANGE_FAILED",
            details={
                "user_id": user_id,
                "current_role": current_role,
                "target_role": target_role,
                "reason": reason,
            },
        )
