# @File: backend/services/uptimerobot/provisioning.py
# @Desc: WHMCS provisioning hook helpers. A lightweight WHMCS addon (or the
#        equivalent WHMCS server module) should POST to
#        /api/v1/admin/uptimerobot/whmcs-hooks/<event> with a shared secret
#        header. The router then dispatches into these helpers.
from __future__ import annotations

import logging
from typing import Optional

from models.uptimerobot import UptimeClientSubscription
from sqlalchemy.ext.asyncio import AsyncSession

from services.uptimerobot.packages import get_package, get_package_by_whmcs_product
from services.uptimerobot.subscriptions import (
    create_subscription,
    get_subscription_by_whmcs_service,
    resume_subscription,
    suspend_subscription,
    terminate_subscription,
    change_package,
)

logger = logging.getLogger(__name__)


async def on_product_activated(
    session: AsyncSession,
    *,
    user_id: str,
    user_email: Optional[str],
    whmcs_service_id: int,
    whmcs_product_id: int,
    package_id: Optional[int] = None,
) -> UptimeClientSubscription:
    """Activate or reactivate a client subscription."""
    existing = await get_subscription_by_whmcs_service(session, whmcs_service_id)
    if existing is not None:
        if existing.status != "active":
            await resume_subscription(session, existing)
        return existing

    resolved_package = None
    if package_id is not None:
        resolved_package = await get_package(session, package_id)
    if resolved_package is None:
        resolved_package = await get_package_by_whmcs_product(session, whmcs_product_id)
    if resolved_package is None:
        raise ValueError(
            f"No uptime_packages row maps to WHMCS product id {whmcs_product_id}. "
            "Create a package first and set whmcs_product_id."
        )

    return await create_subscription(
        session,
        user_id=user_id,
        package_id=resolved_package.id,
        user_email=user_email,
        whmcs_service_id=whmcs_service_id,
        whmcs_product_id=whmcs_product_id,
    )


async def on_product_changed(
    session: AsyncSession,
    *,
    whmcs_service_id: int,
    new_whmcs_product_id: int,
    new_package_id: Optional[int] = None,
) -> Optional[UptimeClientSubscription]:
    sub = await get_subscription_by_whmcs_service(session, whmcs_service_id)
    if sub is None:
        logger.warning(
            "on_product_changed: no subscription for WHMCS service %s", whmcs_service_id
        )
        return None
    target_package = None
    if new_package_id is not None:
        target_package = await get_package(session, new_package_id)
    if target_package is None:
        target_package = await get_package_by_whmcs_product(session, new_whmcs_product_id)
    if target_package is None:
        raise ValueError(
            f"No uptime_packages row maps to WHMCS product id {new_whmcs_product_id}."
        )
    sub.whmcs_product_id = new_whmcs_product_id
    return await change_package(session, sub, target_package.id)


async def on_product_suspended(
    session: AsyncSession, *, whmcs_service_id: int
) -> Optional[UptimeClientSubscription]:
    sub = await get_subscription_by_whmcs_service(session, whmcs_service_id)
    if sub is None:
        return None
    return await suspend_subscription(session, sub)


async def on_product_unsuspended(
    session: AsyncSession, *, whmcs_service_id: int
) -> Optional[UptimeClientSubscription]:
    sub = await get_subscription_by_whmcs_service(session, whmcs_service_id)
    if sub is None:
        return None
    return await resume_subscription(session, sub)


async def on_product_terminated(
    session: AsyncSession, *, whmcs_service_id: int
) -> Optional[UptimeClientSubscription]:
    sub = await get_subscription_by_whmcs_service(session, whmcs_service_id)
    if sub is None:
        return None
    return await terminate_subscription(session, sub)