from fastapi import APIRouter, Depends
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from uuid import UUID
import logging
import redis.asyncio as redis

from ...db import get_session
from ...auth import get_current_account
from ...services.roles import require_viewer
from ...models import Integration, IntegrationStatus, IntegrationProvider, User
from datetime import datetime
from ... import settings
from ...services.salesforce_gateway import SalesforceGateway, get_salesforce_gateway
from ...services.hubspot_oauth import get_hubspot_status

router = APIRouter(prefix="/api/v2/integrations", tags=["integrations"])
log = logging.getLogger(__name__)


# Redis connection for OAuth state storage
async def get_redis():
    """Get Redis connection for OAuth state storage"""
    redis_client = None
    try:
        redis_client = redis.from_url(settings.REDIS_URL, decode_responses=False)
        yield redis_client
    finally:
        if redis_client:
            await redis_client.close()


@router.get("/status")
async def get_integration_status(
    db: AsyncSession = Depends(get_session),
    account_id: UUID = Depends(get_current_account),
    _user: User = Depends(require_viewer),  # Any authenticated user can view status
):
    """Get status of all integrations with detailed Salesforce info"""

    # Get Salesforce integration with full details
    sf_result = await db.execute(
        select(Integration).where(
            Integration.account_id == str(account_id),
            Integration.provider == IntegrationProvider.SALESFORCE,
        )
    )
    sf_integration = sf_result.scalar_one_or_none()

    # Build Salesforce status
    if not sf_integration:
        sf_status = {
            "connected": False,
            "needs_reconnect": False,
            "status": "disconnected",
            "reason": "not_configured",
        }
    elif sf_integration.status != IntegrationStatus.CONNECTED:
        sf_status = {
            "connected": False,
            "needs_reconnect": True,
            "status": "disconnected",
            "reason": "disconnected",
        }
    else:
        # Check token expiry
        needs_reconnect = False
        expires_in_seconds = None

        if sf_integration.expires_at:
            time_until_expiry = (
                sf_integration.expires_at - datetime.utcnow()
            ).total_seconds()
            expires_in_seconds = max(0, int(time_until_expiry))
            if time_until_expiry <= 0:
                needs_reconnect = True

        sf_status = {
            "connected": True,
            "needs_reconnect": needs_reconnect,
            "status": "connected" if not needs_reconnect else "needs_reconnect",
            "username": sf_integration.config.get("username")
            if sf_integration.config
            else None,
            "instance_url": sf_integration.instance_url,
            "connected_at": sf_integration.config.get("connected_at")
            if sf_integration.config
            else None,
            "expires_in_seconds": expires_in_seconds,
            "scopes": sf_integration.scopes or [],
        }

    # Get other integrations
    other_integrations = await db.execute(
        select(Integration).where(
            Integration.account_id == str(account_id),
            Integration.provider != IntegrationProvider.SALESFORCE,
        )
    )

    status = {}
    for integration in other_integrations.scalars():
        status[integration.provider] = {
            "status": integration.status,
            "connected_at": integration.created_at.isoformat()
            if integration.created_at
            else None,
            "scopes": integration.scopes,
        }

    # Build response with nested structure
    hubspot_status = await get_hubspot_status(db, str(account_id))
    response = {
        "salesforce": sf_status,
        "hubspot": hubspot_status,
        "slack": status.get(IntegrationProvider.SLACK, {"status": "disconnected"}),
        "email": status.get(IntegrationProvider.EMAIL, {"status": "disconnected"}),
    }

    # Add legacy shim for top-level fields (for UI compatibility)
    response["connected"] = sf_status["connected"]
    response["needs_reconnect"] = sf_status.get("needs_reconnect", False)
    response["reason"] = sf_status.get("reason", "unknown")
    response["expires_in_seconds"] = sf_status.get("expires_in_seconds")
    response["username"] = sf_status.get("username")

    return response


@router.get("/salesforce/headroom")
async def sf_headroom(sf: SalesforceGateway = Depends(get_salesforce_gateway)):
    """Return current Salesforce API usage headroom based on last limit header.

    Parses Sforce-Limit-Info if available (e.g., "api-usage=185/15000").
    """
    raw = getattr(sf, "_last_limit_info", None)
    used = None
    limit = None
    if raw:
        import re

        # Use same robust parsing as gateway
        for pattern in [
            r"api-usage=(\d+)/(\d+)",  # Standard format
            r"api-usage:\s*(\d+)/(\d+)",  # Colon separator
            r"(\d+)/(\d+)",  # Just numbers if api-usage prefix missing
        ]:
            # Try each part of the comma-separated header
            for part in str(raw).split(","):
                if "api" in part.lower() or "/" in part:  # Quick filter
                    match = re.search(pattern, part)
                    if match:
                        try:
                            used = int(match.group(1))
                            limit = int(match.group(2))
                            break
                        except (ValueError, IndexError):
                            continue
            if used is not None:
                break  # Found a match, stop trying patterns
    headroom = None
    if used is not None and limit:
        try:
            headroom = max(0, 100 - int(100 * used / max(1, limit)))
        except Exception:
            headroom = None
    return {"api_usage": {"used": used, "limit": limit, "headroom_percent": headroom}}


# COMMENTED OUT - Using the implementation in salesforce.py instead
# @router.get("/salesforce/connect")
# async def connect_salesforce(
#     db: AsyncSession = Depends(get_session),
#     account_id: UUID = Depends(get_current_account),
#     redis_conn = Depends(get_redis),
#     _user: User = Depends(require_admin)  # Only admins can connect integrations
# ):
#     """Get Salesforce OAuth URL with CSRF protection"""
#     auth_url, state = await SalesforceClient.get_authorization_url(
#         redis_conn,
#         str(account_id)
#     )
#
#     return {
#         "auth_url": auth_url,
#         "state": state,  # Frontend should store this for verification
#         "message": "Redirect user to auth_url to connect Salesforce"
#     }

# COMMENTED OUT - Using the implementation in salesforce.py instead
# @router.get("/salesforce/callback")
# async def salesforce_callback(
#     code: str = Query(...),
#     state: Optional[str] = Query(None),
#     db: AsyncSession = Depends(get_session),
#     account_id: UUID = Depends(get_current_account),
#     redis_conn = Depends(get_redis),
#     _user: User = Depends(require_admin)  # Only admins can complete connection
# ):
#     """Handle Salesforce OAuth callback with CSRF verification"""
#     try:
#         # Verify state to prevent CSRF attacks
#         if not state or not await SalesforceClient.verify_state(redis_conn, state, str(account_id)):
#             raise HTTPException(403, "Invalid state parameter - possible CSRF attack")
#         legacy_client_removed = True
#         tokens = await client.exchange_code_for_tokens(code)
#
#         # Check if integration exists
#         existing = await db.execute(
#             select(Integration).where(
#                 Integration.account_id == str(account_id),
#                 Integration.provider == IntegrationProvider.SALESFORCE
#             )
#         )
#         integration = existing.scalar_one_or_none()
#
#         if not integration:
#             integration = Integration(
#                 account_id=str(account_id),
#                 provider=IntegrationProvider.SALESFORCE
#             )
#             db.add(integration)
#
#         # Update with new tokens
#         integration.access_token = encrypt_str(tokens["access_token"])
#         integration.refresh_token = encrypt_str(tokens.get("refresh_token"))
#         integration.instance_url = tokens.get("instance_url")
#         integration.status = IntegrationStatus.CONNECTED
#         integration.scopes = ["api", "refresh_token"]
#         integration.expires_at = datetime.utcnow() + timedelta(hours=2)
#         integration.updated_at = datetime.utcnow()
#
#         await db.commit()
#
#         # Return HTML that closes the popup and notifies the parent window
#         frontend_origin = settings.FRONTEND_ORIGIN
#         html_content = f"""
#         <html><body>
#         <script>
#           try {{
#             if (window.opener) {{
#               window.opener.postMessage({{type:'salesforce_connected'}}, '{frontend_origin}');
#             }}
#           }} finally {{
#             window.close();
#           }}
#         </script>
#         Success — you can close this window.
#         </body></html>
#         """
#
#         return Response(content=html_content, media_type="text/html")
#
#     except Exception as e:
#         log.error(f"Salesforce OAuth callback failed: {e}")
#         raise HTTPException(500, f"Failed to connect: {str(e)}")
