"""
Shared tenant deletion utilities
Base classes and utilities for implementing tenant data deletion across services
"""
from typing import Dict, Any, List
from abc import ABC, abstractmethod
import structlog
from datetime import datetime

logger = structlog.get_logger()


class TenantDataDeletionResult:
    """Standard result for tenant data deletion operations"""

    def __init__(self, tenant_id: str, service_name: str):
        self.tenant_id = tenant_id
        self.service_name = service_name
        self.deleted_counts: Dict[str, int] = {}
        self.errors: List[str] = []
        self.timestamp = datetime.utcnow().isoformat()
        self.success = True

    def add_deleted_items(self, entity_type: str, count: int):
        """Record deleted items for an entity type"""
        self.deleted_counts[entity_type] = count

    def add_error(self, error: str):
        """Add an error message"""
        self.errors.append(error)
        self.success = False

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary for API response"""
        return {
            "tenant_id": self.tenant_id,
            "service_name": self.service_name,
            "deleted_counts": self.deleted_counts,
            "total_deleted": sum(self.deleted_counts.values()),
            "errors": self.errors,
            "success": self.success,
            "timestamp": self.timestamp
        }


class BaseTenantDataDeletionService(ABC):
    """
    Base class for tenant data deletion services
    Each microservice should implement this to handle their own data cleanup
    """

    def __init__(self, service_name: str):
        self.service_name = service_name
        self.logger = structlog.get_logger().bind(service=service_name)

    @abstractmethod
    async def delete_tenant_data(self, tenant_id: str) -> TenantDataDeletionResult:
        """
        Delete all data associated with a tenant

        Args:
            tenant_id: The tenant whose data should be deleted

        Returns:
            TenantDataDeletionResult with deletion summary
        """
        pass

    @abstractmethod
    async def get_tenant_data_preview(self, tenant_id: str) -> Dict[str, int]:
        """
        Get a preview of what would be deleted (counts only)

        Args:
            tenant_id: The tenant to preview

        Returns:
            Dict mapping entity types to counts
        """
        pass

    async def safe_delete_tenant_data(self, tenant_id: str) -> TenantDataDeletionResult:
        """
        Safely delete tenant data with error handling

        Args:
            tenant_id: The tenant whose data should be deleted

        Returns:
            TenantDataDeletionResult with deletion summary
        """
        result = TenantDataDeletionResult(tenant_id, self.service_name)

        try:
            self.logger.info("Starting tenant data deletion",
                           tenant_id=tenant_id,
                           service=self.service_name)

            # Call the implementation-specific deletion
            result = await self.delete_tenant_data(tenant_id)

            self.logger.info("Tenant data deletion completed",
                           tenant_id=tenant_id,
                           service=self.service_name,
                           deleted_counts=result.deleted_counts,
                           total_deleted=sum(result.deleted_counts.values()),
                           errors=len(result.errors))

            return result

        except Exception as e:
            self.logger.error("Tenant data deletion failed",
                            tenant_id=tenant_id,
                            service=self.service_name,
                            error=str(e))
            result.add_error(f"Fatal error: {str(e)}")
            return result


def create_tenant_deletion_endpoint_handler(deletion_service: BaseTenantDataDeletionService):
    """
    Factory function to create a FastAPI endpoint handler for tenant deletion

    Usage in service API file:
    ```python
    from shared.services.tenant_deletion import create_tenant_deletion_endpoint_handler

    deletion_service = MyServiceTenantDeletionService()
    delete_tenant_data = create_tenant_deletion_endpoint_handler(deletion_service)

    @router.delete("/tenant/{tenant_id}")
    async def delete_tenant_data_endpoint(tenant_id: str, current_user: dict = Depends(get_current_user)):
        return await delete_tenant_data(tenant_id, current_user)
    ```
    """

    async def handler(tenant_id: str, current_user: Dict[str, Any]) -> Dict[str, Any]:
        """Handle tenant data deletion request"""

        # Only allow internal service calls
        if current_user.get("type") != "service":
            from fastapi import HTTPException, status
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="This endpoint is only accessible to internal services"
            )

        # Perform deletion
        result = await deletion_service.safe_delete_tenant_data(tenant_id)

        return {
            "message": f"Tenant data deletion completed in {deletion_service.service_name}",
            "summary": result.to_dict()
        }

    return handler


def create_tenant_deletion_preview_handler(deletion_service: BaseTenantDataDeletionService):
    """
    Factory function to create a FastAPI endpoint handler for deletion preview

    Usage in service API file:
    ```python
    preview_handler = create_tenant_deletion_preview_handler(deletion_service)

    @router.get("/tenant/{tenant_id}/deletion-preview")
    async def preview_endpoint(tenant_id: str, current_user: dict = Depends(get_current_user)):
        return await preview_handler(tenant_id, current_user)
    ```
    """

    async def handler(tenant_id: str, current_user: Dict[str, Any]) -> Dict[str, Any]:
        """Handle deletion preview request"""

        # Allow internal services and admins
        is_service = current_user.get("type") == "service"
        is_admin = current_user.get("role") in ["owner", "admin"]

        if not (is_service or is_admin):
            from fastapi import HTTPException, status
            raise HTTPException(
                status_code=status.HTTP_403_FORBIDDEN,
                detail="Insufficient permissions"
            )

        # Get preview
        preview = await deletion_service.get_tenant_data_preview(tenant_id)

        return {
            "tenant_id": tenant_id,
            "service": deletion_service.service_name,
            "data_counts": preview,
            "total_items": sum(preview.values())
        }

    return handler
