from datetime import UTC, datetime
from typing import Any, cast

import httpx
import logfire
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel
from sqlalchemy import text
from sqlalchemy.ext.asyncio import AsyncSession
from sqlmodel import select

from app.auth.tenant import get_current_restaurant, get_tenant_session
from app.config import get_settings
from app.db.session import commit_write
from app.models.restaurant import Restaurant
from app.models.whatsapp import (
    TemplateCategory,
    TemplateStatus,
    WhatsAppAccount,
    WhatsAppTemplate,
)
from app.services.encryption import encrypt_token

router = APIRouter(prefix="/whatsapp", tags=["whatsapp"])


class WhatsAppCallbackRequest(BaseModel):
    code: str
    waba_id: str | None = None
    phone_number_id: str | None = None


class WhatsAppDirectConnectRequest(BaseModel):
    access_token: str
    phone_number_id: str
    waba_id: str


class WhatsAppStatusResponse(BaseModel):
    connected: bool
    phone_number: str | None = None
    display_name: str | None = None
    quality_rating: str | None = None
    messaging_limit: str | None = None
    is_verified: bool = False
    connected_at: str | None = None


class TemplateCreateRequest(BaseModel):
    name: str
    category: str
    language: str
    components: dict[str, Any] | None = None


class TemplateResponse(BaseModel):
    id: str
    name: str
    category: str
    language: str
    status: str
    components: dict[str, Any] | None = None
    rejection_reason: str | None = None
    quality_score: str | None = None
    created_at: str
    updated_at: str | None = None


def _meta_error_message(response: httpx.Response) -> str:
    try:
        payload = response.json()
    except ValueError:
        payload = None

    meta_error = payload.get("error") if isinstance(payload, dict) else None
    if isinstance(meta_error, dict):
        message = meta_error.get("message")
        if isinstance(message, str) and message:
            return message

    body = response.text.strip()
    if body:
        return body[:500]
    return f"Meta API request failed with status {response.status_code}"


def _meta_http_client() -> httpx.AsyncClient:
    """Factory for the outbound httpx client used to call the Meta Graph API.

    Exposed as a module-level function so tests can patch it without
    interfering with other ``httpx.AsyncClient`` instances in the process
    (notably the FastAPI ``ASGITransport`` test client).
    """
    return httpx.AsyncClient(timeout=30.0)


async def _try_subscribe_to_waba(
    client: httpx.AsyncClient,
    graph_base: str,
    waba_id: str,
    access_token: str,
    *,
    restaurant_id: str | None = None,
) -> tuple[bool, str | None]:
    """Best-effort subscribe to ``waba_id``'s webhooks using ``access_token``.

    ``POST /{waba_id}/subscribed_apps`` subscribes the app that owns the
    bearer token. For Embedded Signup the OAuth-exchanged token is bound
    to our app; for direct-connect the user-supplied token is bound to
    their app and webhooks flow through whatever endpoint that app has
    configured.

    Returns ``(success, error_message_or_None)``. Never raises on Meta
    rejection — the caller decides whether to fail the request or persist
    the account in a degraded (outbound-only) state.
    """
    sub_resp = await client.post(
        f"{graph_base}/{waba_id}/subscribed_apps",
        headers={"Authorization": f"Bearer {access_token}"},
    )
    if sub_resp.is_success:
        return True, None

    error = _meta_error_message(sub_resp)
    logfire.warning(
        "whatsapp_subscribe_app_failed",
        waba_id=waba_id,
        restaurant_id=restaurant_id,
        status_code=sub_resp.status_code,
        error_message=error,
    )
    return False, error


def _attach_webhook_status(
    result: dict[str, Any],
    subscription_ok: bool,
    subscription_error: str | None,
) -> dict[str, Any]:
    """Augment an upsert-account response with webhook subscription status.

    Subscription failure is **not** an error — the credentials still work
    for outbound messages — but the caller (and UI) must know that inbound
    webhooks were not wired so they can resolve it out-of-band.
    """
    result["webhooks_subscribed"] = subscription_ok
    if subscription_ok:
        return result

    result["webhook_subscription_error"] = subscription_error
    hint = (
        "WhatsApp credentials saved. Outbound messages will work, but "
        "inbound webhooks could not be configured: "
        f"{subscription_error or 'permissions error'}. To receive incoming "
        "messages, complete Embedded Signup or grant our app 'Manage messages' "
        "on this WABA in Meta Business Manager → Settings → WhatsApp Accounts → "
        "select the WABA → Partners."
    )
    result["message"] = hint
    return result


async def _exchange_token_and_fetch_metadata(
    *,
    code: str,
    phone_number_id: str | None,
    waba_id: str | None,
) -> tuple[str, str, str, dict[str, Any] | None, bool, str | None]:
    """Exchange OAuth code for token, discover WABA/phone if needed, fetch metadata.

    Returns (access_token, waba_id, phone_number_id, metadata, subscription_ok, subscription_error).
    Raises HTTPException on unrecoverable failures.
    """
    settings = get_settings()
    graph_base = f"https://graph.facebook.com/{settings.META_GRAPH_API_VERSION}"
    metadata: dict[str, Any] | None = None

    async with _meta_http_client() as client:
        # --- Step 1: Exchange code for access token ---
        token_resp = await client.get(
            f"{graph_base}/oauth/access_token",
            params={
                "client_id": settings.META_APP_ID,
                "client_secret": settings.META_APP_SECRET,
                "code": code,
            },
        )
        if not token_resp.is_success:
            raise HTTPException(status_code=502, detail=_meta_error_message(token_resp))

        token_payload = token_resp.json()
        access_token = (
            token_payload.get("access_token") if isinstance(token_payload, dict) else None
        )
        if not isinstance(access_token, str) or not access_token:
            raise HTTPException(
                status_code=502,
                detail="Meta token exchange did not return an access token",
            )

        # --- Step 2: Discover WABA and phone number if not provided ---
        if not waba_id or not phone_number_id:
            discovered_waba, discovered_phone = await _discover_waba_and_phone(
                client, graph_base, access_token, settings
            )
            waba_id = waba_id or discovered_waba
            phone_number_id = phone_number_id or discovered_phone

        if not waba_id or not phone_number_id:
            raise HTTPException(
                status_code=502,
                detail=(
                    "Could not determine WhatsApp Business Account or phone number. "
                    "Ensure the Meta app has whatsapp_business_management permission."
                ),
            )

        # --- Step 3: Fetch phone number metadata ---
        meta_resp = await client.get(
            f"{graph_base}/{phone_number_id}",
            params={
                "fields": (
                    "display_phone_number,verified_name,quality_rating,"
                    "messaging_limit_tier,code_verification_status"
                ),
                "access_token": access_token,
            },
        )
        if meta_resp.is_success:
            meta_payload = meta_resp.json()
            if isinstance(meta_payload, dict):
                metadata = meta_payload
        else:
            logfire.warning(
                "whatsapp_oauth_metadata_fetch_failed",
                phone_number_id=phone_number_id,
                status_code=meta_resp.status_code,
                error_message=_meta_error_message(meta_resp),
            )

        # --- Step 4: Subscribe to WABA webhooks (best-effort) ---
        subscription_ok, subscription_error = await _try_subscribe_to_waba(
            client,
            graph_base,
            waba_id,
            access_token,
        )

    return (
        access_token,
        waba_id,
        phone_number_id,
        metadata,
        subscription_ok,
        subscription_error,
    )


async def _discover_waba_and_phone(
    client: httpx.AsyncClient,
    graph_base: str,
    access_token: str,
    settings: Any,
) -> tuple[str | None, str | None]:
    """Discover WABA ID and phone number ID from a token's granted scopes.

    Uses debug_token to find which WABAs the token can access, then queries
    the first WABA's phone numbers.
    """
    app_token = f"{settings.META_APP_ID}|{settings.META_APP_SECRET}"

    # debug_token returns granular_scopes with target_ids per permission
    debug_resp = await client.get(
        f"{graph_base}/debug_token",
        params={"input_token": access_token, "access_token": app_token},
    )
    if not debug_resp.is_success:
        logfire.warning(
            "whatsapp_oauth_debug_token_failed",
            status_code=debug_resp.status_code,
            error_message=_meta_error_message(debug_resp),
        )
        return None, None

    debug_data = debug_resp.json()
    data = debug_data.get("data") if isinstance(debug_data, dict) else None
    if not isinstance(data, dict):
        return None, None

    # Extract WABA IDs from granular_scopes for whatsapp_business_management
    waba_id: str | None = None
    scopes = data.get("granular_scopes")
    if isinstance(scopes, list):
        for scope in scopes:
            if not isinstance(scope, dict):
                continue
            if scope.get("scope") != "whatsapp_business_management":
                continue
            target_ids = scope.get("target_ids")
            if isinstance(target_ids, list) and target_ids:
                waba_id = str(target_ids[0])
                break

    if not waba_id:
        logfire.warning("whatsapp_oauth_no_waba_in_token_scopes")
        return None, None

    # Query the WABA's phone numbers
    phones_resp = await client.get(
        f"{graph_base}/{waba_id}/phone_numbers",
        params={"access_token": access_token},
    )
    if not phones_resp.is_success:
        logfire.warning(
            "whatsapp_oauth_phone_numbers_fetch_failed",
            waba_id=waba_id,
            status_code=phones_resp.status_code,
            error_message=_meta_error_message(phones_resp),
        )
        return waba_id, None

    phones_payload = phones_resp.json()
    phone_data = phones_payload.get("data") if isinstance(phones_payload, dict) else None
    if isinstance(phone_data, list) and phone_data:
        first_phone = phone_data[0]
        if isinstance(first_phone, dict):
            phone_number_id = first_phone.get("id")
            if isinstance(phone_number_id, str) and phone_number_id:
                return waba_id, phone_number_id

    logfire.warning("whatsapp_oauth_no_phone_numbers_found", waba_id=waba_id)
    return waba_id, None


def _serialize_template(template: WhatsAppTemplate) -> TemplateResponse:
    return TemplateResponse(
        id=template.id,
        name=template.name,
        category=template.category,
        language=template.language,
        status=template.status,
        components=template.components,
        rejection_reason=template.rejection_reason,
        quality_score=template.quality_score,
        created_at=template.created_at.isoformat(),
        updated_at=template.updated_at.isoformat() if template.updated_at else None,
    )


async def _get_active_account(
    session: AsyncSession,
    restaurant_id: str,
) -> WhatsAppAccount | None:
    result = await session.execute(
        select(WhatsAppAccount)
        .where(WhatsAppAccount.restaurant_id == restaurant_id)
        .where(WhatsAppAccount.is_active)
    )
    return result.scalar_one_or_none()


async def _require_active_account(
    session: AsyncSession,
    restaurant_id: str,
) -> WhatsAppAccount:
    account = await _get_active_account(session, restaurant_id)
    if account is None:
        raise HTTPException(status_code=404, detail="No active WhatsApp account found")
    return account


async def _provision_default_templates(
    session: AsyncSession,
    restaurant_id: str,
    account_id: str,
) -> list[WhatsAppTemplate]:
    defaults = [
        {
            "name": "reservation_confirmed",
            "category": TemplateCategory.UTILITY.value,
            "language": "en_US",
            "components": {
                "components": [
                    {
                        "type": "BODY",
                        "text": (
                            "Hi {{1}}, your reservation at {{2}} on {{3}} for {{4}} "
                            "guests is confirmed."
                        ),
                    }
                ]
            },
        },
        {
            "name": "reservation_reminder",
            "category": TemplateCategory.UTILITY.value,
            "language": "en_US",
            "components": {
                "components": [
                    {
                        "type": "BODY",
                        "text": (
                            "Reminder: You have a reservation at {{1}} tomorrow at {{2}} "
                            "for {{3}} guests."
                        ),
                    }
                ]
            },
        },
        {
            "name": "order_status_update",
            "category": TemplateCategory.UTILITY.value,
            "language": "en_US",
            "components": {
                "components": [
                    {
                        "type": "BODY",
                        "text": "Your order #{{1}} at {{2}} is now {{3}}.",
                    }
                ]
            },
        },
    ]

    existing_result = await session.execute(
        select(WhatsAppTemplate.name, WhatsAppTemplate.language).where(
            WhatsAppTemplate.whatsapp_account_id == account_id
        )
    )
    existing = {(name, language) for name, language in existing_result.all()}

    created: list[WhatsAppTemplate] = []
    for default in defaults:
        key = (default["name"], default["language"])
        if key in existing:
            continue

        name = cast(str, default.get("name")) if isinstance(default.get("name"), str) else ""
        category = (
            cast(str, default.get("category"))
            if isinstance(default.get("category"), str)
            else TemplateCategory.UTILITY.value
        )
        language = (
            cast(str, default.get("language"))
            if isinstance(default.get("language"), str)
            else "en_US"
        )
        components = (
            cast(dict[str, Any], default.get("components"))
            if isinstance(default.get("components"), dict)
            else None
        )

        template = WhatsAppTemplate(
            restaurant_id=restaurant_id,
            whatsapp_account_id=account_id,
            name=name,
            category=category,
            language=language,
            status=TemplateStatus.PENDING.value,
            components=components,
        )
        session.add(template)
        created.append(template)

    return created


async def _upsert_whatsapp_account(
    session: AsyncSession,
    restaurant_id: str,
    waba_id: str,
    phone_number_id: str,
    encrypted_token: bytes,
    metadata: dict[str, Any] | None,
) -> dict[str, Any]:
    existing_by_phone_result = await session.execute(
        select(WhatsAppAccount).where(WhatsAppAccount.phone_number_id == phone_number_id)
    )
    account = existing_by_phone_result.scalar_one_or_none()
    if account is not None and account.restaurant_id != restaurant_id:
        raise HTTPException(
            status_code=409,
            detail="This WhatsApp phone number is already connected to another restaurant",
        )

    if account is None:
        existing_by_waba_result = await session.execute(
            select(WhatsAppAccount)
            .where(WhatsAppAccount.restaurant_id == restaurant_id)
            .where(WhatsAppAccount.waba_id == waba_id)
        )
        account = existing_by_waba_result.scalar_one_or_none()

    active_accounts_result = await session.execute(
        select(WhatsAppAccount)
        .where(WhatsAppAccount.restaurant_id == restaurant_id)
        .where(WhatsAppAccount.is_active)
    )
    for active_account in active_accounts_result.scalars().all():
        if account is not None and active_account.id == account.id:
            continue
        active_account.is_active = False
        session.add(active_account)

    connected_at = datetime.now(UTC).replace(tzinfo=None)
    metadata_phone_number = (
        metadata.get("display_phone_number") if isinstance(metadata, dict) else None
    )
    metadata_display_name = metadata.get("verified_name") if isinstance(metadata, dict) else None
    metadata_quality_rating = metadata.get("quality_rating") if isinstance(metadata, dict) else None
    metadata_messaging_limit = (
        metadata.get("messaging_limit_tier") if isinstance(metadata, dict) else None
    )
    metadata_verification_status = (
        metadata.get("code_verification_status") if isinstance(metadata, dict) else None
    )
    is_verified = metadata_verification_status == "verified"

    if account is None:
        account = WhatsAppAccount(
            restaurant_id=restaurant_id,
            waba_id=waba_id,
            phone_number_id=phone_number_id,
            phone_number=(metadata_phone_number if isinstance(metadata_phone_number, str) else ""),
            display_name=metadata_display_name if isinstance(metadata_display_name, str) else "",
            access_token_encrypted=encrypted_token,
            quality_rating=(
                metadata_quality_rating if isinstance(metadata_quality_rating, str) else None
            ),
            messaging_limit=(
                metadata_messaging_limit if isinstance(metadata_messaging_limit, str) else None
            ),
            is_verified=is_verified,
            connected_at=connected_at,
            is_active=True,
        )
    else:
        account.waba_id = waba_id
        account.phone_number_id = phone_number_id
        if isinstance(metadata_phone_number, str):
            account.phone_number = metadata_phone_number
        if isinstance(metadata_display_name, str):
            account.display_name = metadata_display_name
        if isinstance(metadata_quality_rating, str):
            account.quality_rating = metadata_quality_rating
        if isinstance(metadata_messaging_limit, str):
            account.messaging_limit = metadata_messaging_limit
        if metadata_verification_status is not None:
            account.is_verified = is_verified
        account.access_token_encrypted = encrypted_token
        account.connected_at = connected_at
        account.is_active = True

    session.add(account)
    await _provision_default_templates(session, restaurant_id, account.id)
    await commit_write(session)
    await session.refresh(account)

    templates_result = await session.execute(
        select(WhatsAppTemplate).where(WhatsAppTemplate.whatsapp_account_id == account.id)
    )
    templates = templates_result.scalars().all()

    return {
        "connected": True,
        "account_id": account.id,
        "template_count": len(templates),
        "message": "WhatsApp account connected successfully",
    }


@router.post("/callback")
async def complete_whatsapp_oauth(
    payload: WhatsAppCallbackRequest,
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> dict[str, Any]:
    if not payload.code.strip():
        raise HTTPException(status_code=400, detail="OAuth code is required")

    settings = get_settings()
    if not settings.WHATSAPP_TOKEN_ENCRYPTION_KEY:
        raise HTTPException(status_code=503, detail="WhatsApp token encryption is not configured")

    (
        access_token,
        waba_id,
        phone_number_id,
        metadata,
        subscription_ok,
        subscription_error,
    ) = await _exchange_token_and_fetch_metadata(
        code=payload.code,
        phone_number_id=payload.phone_number_id,
        waba_id=payload.waba_id,
    )
    encrypted_token = encrypt_token(access_token)

    result = await _upsert_whatsapp_account(
        session=session,
        restaurant_id=restaurant.id,
        waba_id=waba_id,
        phone_number_id=phone_number_id,
        encrypted_token=encrypted_token,
        metadata=metadata,
    )
    return _attach_webhook_status(result, subscription_ok, subscription_error)


@router.post("/connect-direct")
async def connect_whatsapp_direct(
    payload: WhatsAppDirectConnectRequest,
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> dict[str, Any]:
    access_token = payload.access_token.strip()
    phone_number_id = payload.phone_number_id.strip()
    waba_id = payload.waba_id.strip()
    if not access_token or not phone_number_id or not waba_id:
        raise HTTPException(
            status_code=400,
            detail="Access token, phone number ID, and WABA ID are required",
        )

    settings = get_settings()
    if not settings.WHATSAPP_TOKEN_ENCRYPTION_KEY:
        raise HTTPException(status_code=503, detail="WhatsApp token encryption is not configured")

    graph_base = f"https://graph.facebook.com/{settings.META_GRAPH_API_VERSION}"
    async with _meta_http_client() as client:
        metadata_resp = await client.get(
            f"{graph_base}/{phone_number_id}",
            params={
                "fields": (
                    "display_phone_number,verified_name,quality_rating,"
                    "messaging_limit_tier,code_verification_status"
                ),
                "access_token": access_token,
            },
        )
        if not metadata_resp.is_success:
            raise HTTPException(status_code=502, detail=_meta_error_message(metadata_resp))

        metadata_payload = metadata_resp.json()
        metadata = metadata_payload if isinstance(metadata_payload, dict) else None

        subscription_ok, subscription_error = await _try_subscribe_to_waba(
            client,
            graph_base,
            waba_id,
            access_token,
            restaurant_id=restaurant.id,
        )

    encrypted_token = encrypt_token(access_token)
    result = await _upsert_whatsapp_account(
        session=session,
        restaurant_id=restaurant.id,
        waba_id=waba_id,
        phone_number_id=phone_number_id,
        encrypted_token=encrypted_token,
        metadata=metadata,
    )
    return _attach_webhook_status(result, subscription_ok, subscription_error)


@router.get("/status", response_model=WhatsAppStatusResponse)
async def get_whatsapp_status(
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> WhatsAppStatusResponse:
    account = await _get_active_account(session, restaurant.id)
    if account is None:
        return WhatsAppStatusResponse(connected=False)

    return WhatsAppStatusResponse(
        connected=True,
        phone_number=account.phone_number or None,
        display_name=account.display_name or None,
        quality_rating=account.quality_rating,
        messaging_limit=account.messaging_limit,
        is_verified=account.is_verified,
        connected_at=account.connected_at.isoformat() if account.connected_at else None,
    )


@router.delete("/disconnect", status_code=status.HTTP_200_OK)
async def disconnect_whatsapp(
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> dict[str, str]:
    account = await _require_active_account(session, restaurant.id)
    account.is_active = False
    session.add(account)
    await commit_write(session)
    return {"message": "WhatsApp disconnected successfully"}


@router.post("/refresh-token", status_code=status.HTTP_200_OK)
async def refresh_whatsapp_token(
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> dict[str, Any]:
    await _require_active_account(session, restaurant.id)
    return {
        "reauth_required": True,
        "message": "Re-authentication is required via WhatsApp Embedded Signup",
    }


@router.get("/templates", response_model=list[TemplateResponse])
async def list_whatsapp_templates(
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> list[TemplateResponse]:
    account = await _require_active_account(session, restaurant.id)
    result = await session.execute(
        select(WhatsAppTemplate)
        .where(WhatsAppTemplate.restaurant_id == restaurant.id)
        .where(WhatsAppTemplate.whatsapp_account_id == account.id)
        .order_by(text("created_at DESC"))
    )
    return [_serialize_template(template) for template in result.scalars().all()]


@router.post("/templates", response_model=TemplateResponse, status_code=status.HTTP_201_CREATED)
async def create_whatsapp_template(
    payload: TemplateCreateRequest,
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> TemplateResponse:
    account = await _require_active_account(session, restaurant.id)

    try:
        category = TemplateCategory(payload.category.strip().upper()).value
    except ValueError as exc:
        raise HTTPException(status_code=400, detail="Invalid template category") from exc

    name = payload.name.strip()
    language = payload.language.strip()
    existing_result = await session.execute(
        select(WhatsAppTemplate)
        .where(WhatsAppTemplate.restaurant_id == restaurant.id)
        .where(WhatsAppTemplate.whatsapp_account_id == account.id)
        .where(WhatsAppTemplate.name == name)
        .where(WhatsAppTemplate.language == language)
    )
    if existing_result.scalar_one_or_none() is not None:
        raise HTTPException(
            status_code=409,
            detail="A WhatsApp template with this name and language already exists",
        )

    template = WhatsAppTemplate(
        restaurant_id=restaurant.id,
        whatsapp_account_id=account.id,
        name=name,
        category=category,
        language=language,
        status=TemplateStatus.PENDING.value,
        components=payload.components,
    )
    session.add(template)

    # TODO: Submit template to Meta template API and persist the returned meta_template_id.
    await commit_write(session)
    await session.refresh(template)
    return _serialize_template(template)


@router.get("/templates/{template_id}", response_model=TemplateResponse)
async def get_whatsapp_template(
    template_id: str,
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> TemplateResponse:
    account = await _require_active_account(session, restaurant.id)
    result = await session.execute(
        select(WhatsAppTemplate)
        .where(WhatsAppTemplate.id == template_id)
        .where(WhatsAppTemplate.restaurant_id == restaurant.id)
        .where(WhatsAppTemplate.whatsapp_account_id == account.id)
    )
    template = result.scalar_one_or_none()
    if template is None:
        raise HTTPException(status_code=404, detail="WhatsApp template not found")
    return _serialize_template(template)


@router.delete("/templates/{template_id}", status_code=status.HTTP_200_OK)
async def delete_whatsapp_template(
    template_id: str,
    restaurant: Restaurant = Depends(get_current_restaurant),
    session: AsyncSession = Depends(get_tenant_session),
) -> dict[str, str]:
    account = await _require_active_account(session, restaurant.id)
    result = await session.execute(
        select(WhatsAppTemplate)
        .where(WhatsAppTemplate.id == template_id)
        .where(WhatsAppTemplate.restaurant_id == restaurant.id)
        .where(WhatsAppTemplate.whatsapp_account_id == account.id)
    )
    template = result.scalar_one_or_none()
    if template is None:
        raise HTTPException(status_code=404, detail="WhatsApp template not found")

    # TODO: Delete the template in Meta before removing the local record.
    await session.delete(template)
    await commit_write(session)
    return {"message": "WhatsApp template deleted successfully"}
