"""
Channel Gateway — FastAPI application.

Mounts the slack-bolt AsyncApp as a sub-application at /slack/events.
Registers the WhatsApp webhook router at /whatsapp/webhook.
Serves all Phase 3 portal API routes under /api/portal/* and /api/webhooks/*.

Port: 8001

Endpoints:
  POST /slack/events                      — Slack Events API webhook (handled by slack-bolt)
  GET  /whatsapp/webhook                  — WhatsApp hub challenge verification
  POST /whatsapp/webhook                  — WhatsApp inbound message webhook
  GET  /api/portal/*                      — Portal management API (tenants, agents, billing, etc.)
  GET  /api/portal/billing/*              — Stripe billing endpoints
  GET  /api/portal/channels/*             — Channel connection endpoints (Slack OAuth, WhatsApp)
  GET  /api/portal/tenants/{id}/llm-keys  — BYO LLM key management
  GET  /api/portal/usage/*                — Usage and cost analytics
  POST /api/webhooks/*                    — Stripe webhook receiver
  GET  /health                            — Health check

Startup sequence:
  1. Create Redis connection
  2. Create slack-bolt AsyncApp (signing_secret=...)
  3. Register Slack event handlers
  4. Mount slack-bolt request handler at /slack/events
  5. Include WhatsApp router
  6. Include Phase 3 portal API routers
  7. Expose /health
"""

from __future__ import annotations

import logging

from fastapi import FastAPI, Request, Response
from redis.asyncio import Redis
from slack_bolt.adapter.fastapi.async_handler import AsyncSlackRequestHandler
from slack_bolt.async_app import AsyncApp

from gateway.channels.slack import register_slack_handlers
from gateway.channels.web import web_chat_router
from gateway.channels.whatsapp import whatsapp_router
from shared.api import (
    billing_router,
    channels_router,
    chat_router,
    invitations_router,
    llm_keys_router,
    portal_router,
    push_router,
    templates_router,
    usage_router,
    webhook_router,
)
from shared.config import settings
from shared.db import async_session_factory, engine
from shared.rls import configure_rls_hook

logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# FastAPI app
# ---------------------------------------------------------------------------
# Register RLS hook so tenant context is set for all DB operations
configure_rls_hook(engine)

app = FastAPI(
    title="Konstruct Channel Gateway",
    description="Unified ingress for all messaging platforms",
    version="0.1.0",
)

# ---------------------------------------------------------------------------
# CORS — allow portal origin to call gateway API
# ---------------------------------------------------------------------------
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=[
        "http://localhost:3000",
        "http://127.0.0.1:3000",
        "http://100.64.0.10:3000",
    ],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ---------------------------------------------------------------------------
# Slack bolt app — initialized at module import time.
# signing_secret="" is safe for local dev/testing; set via env in production.
# ---------------------------------------------------------------------------
slack_app: AsyncApp | None = None
if settings.slack_bot_token and settings.slack_signing_secret:
    slack_app = AsyncApp(
        token=settings.slack_bot_token,
        signing_secret=settings.slack_signing_secret,
    )
else:
    import logging
    logging.getLogger(__name__).warning(
        "SLACK_BOT_TOKEN or SLACK_SIGNING_SECRET not set — Slack adapter disabled"
    )

# Async Redis client — shared across all request handlers
_redis: Redis | None = None  # type: ignore[type-arg]


def _get_redis() -> Redis:  # type: ignore[type-arg]
    """Return the module-level Redis client, creating it if necessary."""
    global _redis
    if _redis is None:
        _redis = Redis.from_url(settings.redis_url, decode_responses=True)
    return _redis


# ---------------------------------------------------------------------------
# Register Slack event handlers
# ---------------------------------------------------------------------------
slack_handler: AsyncSlackRequestHandler | None = None
if slack_app is not None:
    register_slack_handlers(
        slack_app=slack_app,
        redis=_get_redis(),
        get_session=async_session_factory,
    )
    slack_handler = AsyncSlackRequestHandler(slack_app)

# ---------------------------------------------------------------------------
# Register channel routers
# ---------------------------------------------------------------------------
app.include_router(whatsapp_router)

# ---------------------------------------------------------------------------
# Register Phase 3 portal API routers
# ---------------------------------------------------------------------------
app.include_router(portal_router)
app.include_router(billing_router)
app.include_router(channels_router)
app.include_router(llm_keys_router)
app.include_router(usage_router)
app.include_router(webhook_router)

# ---------------------------------------------------------------------------
# Register Phase 4 RBAC routers
# ---------------------------------------------------------------------------
app.include_router(invitations_router)

# ---------------------------------------------------------------------------
# Register Phase 5 Employee Design routers
# ---------------------------------------------------------------------------
app.include_router(templates_router)

# ---------------------------------------------------------------------------
# Phase 6 Web Chat routers
# ---------------------------------------------------------------------------
app.include_router(chat_router)       # REST: /api/portal/chat/*
app.include_router(web_chat_router)   # WebSocket: /chat/ws/{conversation_id}

# ---------------------------------------------------------------------------
# Phase 8 Push Notification router
# ---------------------------------------------------------------------------
app.include_router(push_router)       # Push subscribe/unsubscribe/send


# ---------------------------------------------------------------------------
# Routes
# ---------------------------------------------------------------------------


@app.post("/slack/events")
async def slack_events(request: Request) -> Response:
    """
    Slack Events API webhook endpoint.

    slack-bolt's AsyncSlackRequestHandler handles:
      - Slack signature verification (X-Slack-Signature)
      - URL verification challenge (type=url_verification)
      - Event routing to registered handlers

    CRITICAL: This endpoint MUST return HTTP 200 within 3 seconds.
    All LLM/heavy work is dispatched to Celery inside the event handlers.
    """
    if slack_handler is None:
        return Response(content='{"error":"Slack not configured"}', status_code=503, media_type="application/json")
    return await slack_handler.handle(request)


@app.get("/health")
async def health() -> dict[str, str]:
    """Health check endpoint."""
    return {"status": "ok", "service": "gateway"}
