from __future__ import annotations

from typing import Any, Dict, Optional

from .errors import MetaApiError
from .logging import get_logger
from .meta_client import get_client, MetaClient
from .schemas import ToolResult

logger = get_logger(__name__)


async def list_businesses_handler(arguments: Dict[str, Any], client: Optional[MetaClient] = None) -> ToolResult:
    """List all businesses the user has access to.
    
    Args:
        arguments: Empty dict or optional filters
        client: Optional MetaClient instance
        
    Returns:
        ToolResult with list of businesses
    """
    try:
        client = client or get_client()
        
        fields = [
            "id",
            "name",
            "primary_page",
            "timezone_id",
            "created_time",
            "updated_time",
            "verification_status",
        ]
        
        response = await client.get(
            "me/businesses",
            params={"fields": ",".join(fields)}
        )
        
        businesses = response.get("data", [])
        
        return ToolResult(
            ok=True,
            data={
                "businesses": businesses,
                "count": len(businesses),
            }
        )
    except MetaApiError as exc:
        logger.error("list_businesses_failed", **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def get_business_handler(arguments: Dict[str, Any], client: Optional[MetaClient] = None) -> ToolResult:
    """Get detailed information about a specific business.
    
    Args:
        arguments: {"business_id": "123"}
        client: Optional MetaClient instance
        
    Returns:
        ToolResult with business details
    """
    try:
        client = client or get_client()
        business_id = arguments.get("business_id")
        
        if not business_id:
            return ToolResult(ok=False, error={"message": "business_id is required"})
        
        fields = [
            "id",
            "name",
            "primary_page",
            "timezone_id",
            "created_time",
            "updated_time",
            "verification_status",
            "profile_picture_uri",
            "two_factor_type",
        ]
        
        response = await client.get(
            business_id,
            params={"fields": ",".join(fields)}
        )
        
        return ToolResult(ok=True, data=response)
    except MetaApiError as exc:
        logger.error("get_business_failed", business_id=business_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def list_business_users_handler(arguments: Dict[str, Any], client: Optional[MetaClient] = None) -> ToolResult:
    """List all users associated with a business.
    
    Args:
        arguments: {"business_id": "123"}
        client: Optional MetaClient instance
        
    Returns:
        ToolResult with list of users and their roles
    """
    try:
        client = client or get_client()
        business_id = arguments.get("business_id")
        
        if not business_id:
            return ToolResult(ok=False, error={"message": "business_id is required"})
        
        # Get business users with roles
        response = await client.get(
            f"{business_id}/business_users",
            params={
                "fields": "id,name,email,role,pending_email,two_fac_status"
            }
        )
        
        users = response.get("data", [])
        
        return ToolResult(
            ok=True,
            data={
                "users": users,
                "count": len(users),
                "business_id": business_id,
            }
        )
    except MetaApiError as exc:
        logger.error("list_business_users_failed", business_id=business_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def list_business_pages_handler(arguments: Dict[str, Any], client: Optional[MetaClient] = None) -> ToolResult:
    """List all Facebook Pages associated with a business.
    
    Args:
        arguments: {"business_id": "123"}
        client: Optional MetaClient instance
        
    Returns:
        ToolResult with list of pages
    """
    try:
        client = client or get_client()
        business_id = arguments.get("business_id")
        
        if not business_id:
            return ToolResult(ok=False, error={"message": "business_id is required"})
        
        fields = [
            "id",
            "name",
            "category",
            "category_list",
            "verification_status",
            "fan_count",
            "link",
        ]
        
        response = await client.get(
            f"{business_id}/owned_pages",
            params={"fields": ",".join(fields)}
        )
        
        pages = response.get("data", [])
        
        return ToolResult(
            ok=True,
            data={
                "pages": pages,
                "count": len(pages),
                "business_id": business_id,
            }
        )
    except MetaApiError as exc:
        logger.error("list_business_pages_failed", business_id=business_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


async def list_business_adaccounts_handler(arguments: Dict[str, Any], client: Optional[MetaClient] = None) -> ToolResult:
    """List all ad accounts associated with a business.
    
    Args:
        arguments: {"business_id": "123"}
        client: Optional MetaClient instance
        
    Returns:
        ToolResult with list of ad accounts
    """
    try:
        client = client or get_client()
        business_id = arguments.get("business_id")
        raw_limit = arguments.get("limit")
        if raw_limit is None:
            limit: int | None = None
        else:
            try:
                limit = int(raw_limit)
            except (TypeError, ValueError):
                return ToolResult(ok=False, error={"message": "limit must be an integer"})
            if limit < 1:
                return ToolResult(ok=False, error={"message": "limit must be >= 1"})
        
        if not business_id:
            return ToolResult(ok=False, error={"message": "business_id is required"})
        
        fields = [
            "id",
            "account_id",
            "name",
            "account_status",
            "currency",
            "timezone_name",
            "business",
            "amount_spent",
            "balance",
            "spend_cap",
        ]
        
        # Enterprise Scale: Use get_all for robust fetching if no limit specified or very high
        if not limit or limit > 100:
            # We need to construct the path manually for get_all
            path = f"{business_id}/client_ad_accounts"
            params = {"fields": ",".join(fields)}
            
            # We need to access the client instance. The handler receives it.
            if client:
                try:
                    data = await client.get_all(path, params=params, limit=limit or 5000)
                    return ToolResult(
                        ok=True,
                        data={
                            "ad_accounts": data,
                            "count": len(data),
                            "business_id": business_id,
                        }
                    )
                except Exception as e:
                    # Fallback to standard if get_all fails or methods change
                    logger.warning(f"get_all for ad accounts failed, falling back to standard get: {e}")
                    pass

        # Standard path
        response = await client.get(
            f"{business_id}/client_ad_accounts",
            params={
                "fields": ",".join(fields),
                **({"limit": limit} if limit else {}),
            }
        )
        
        ad_accounts = response.get("data", [])
        
        return ToolResult(
            ok=True,
            data={
                "ad_accounts": ad_accounts,
                "count": len(ad_accounts),
                "business_id": business_id,
            }
        )
    except MetaApiError as exc:
        logger.error("list_business_adaccounts_failed", business_id=business_id, **exc.to_dict())
        return ToolResult(ok=False, error=exc.to_dict())


