"""WhatsApp adapter for the Fetch Data Toggle system.

* ``fetch_clients``  — WHMCS clients count (shared).
* ``fetch_accounts`` — counts registered WhatsApp devices/accounts
  (from the local mirror maintained by the WhatsApp Reseller module).
* ``fetch_domains``  — WHMCS domains, matched against device labels /
  phone numbers if any; otherwise reports all as unlinked.
"""
from __future__ import annotations

import logging
from typing import Any, List

from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

from services.module_sync.adapters import registry
from services.module_sync.engine import STATUS_FAILED, STATUS_OK, SyncAttempt

logger = logging.getLogger(__name__)


class _WhatsAppAdapter:
    module_name = "whatsapp"
    module_label = "WhatsApp"

    async def fetch_clients(self, db: AsyncSession) -> SyncAttempt:
        try:
            from services import whmcs

            result = await whmcs.call_whmcs_safe("GetClients", {"limitnum": 1000})
            payload = (result or {}).get("clients") or {}
            clients: List[Any] = list(payload.get("client", []) or [])
            return SyncAttempt(
                status=STATUS_OK,
                items_fetched=len(clients),
                raw_response=_safe_preview(result),
            )
        except Exception as exc:  # noqa: BLE001
            logger.exception("whatsapp.fetch_clients failed")
            return SyncAttempt(status=STATUS_FAILED, error_message=str(exc)[:500])

    async def fetch_accounts(self, db: AsyncSession) -> SyncAttempt:
        try:
            # Try to count rows in any whatsapp_* "device/account" table.
            # Using a defensive import so missing tables do not crash.
            try:
                from models.whatsapp import WhatsappDevice  # type: ignore

                total = (
                    await db.execute(select(func.count(WhatsappDevice.id)))
                ).scalar() or 0
                return SyncAttempt(
                    status=STATUS_OK,
                    items_fetched=int(total),
                    raw_response=f"mirrored {total} devices",
                )
            except Exception:  # noqa: BLE001
                # Fall back to counting conversations if devices are not modelled yet.
                from models.whatsapp import WhatsappConversation  # type: ignore

                total = (
                    await db.execute(select(func.count(WhatsappConversation.id)))
                ).scalar() or 0
                return SyncAttempt(
                    status=STATUS_OK,
                    items_fetched=int(total),
                    raw_response=f"mirrored {total} conversations",
                )
        except Exception as exc:  # noqa: BLE001
            logger.exception("whatsapp.fetch_accounts failed")
            return SyncAttempt(status=STATUS_FAILED, error_message=str(exc)[:500])

    async def fetch_domains(self, db: AsyncSession) -> SyncAttempt:
        try:
            from services import whmcs

            result = await whmcs.call_whmcs_safe("GetClientsDomains", {"limitnum": 1000})
            domains_block = (result or {}).get("domains") or {}
            whmcs_domains = list(domains_block.get("domain", []) or [])
            domain_names = [
                (d.get("domainname") or "").strip().lower()
                for d in whmcs_domains
                if isinstance(d, dict)
            ]
            domain_names = [d for d in domain_names if d]

            # WhatsApp devices rarely carry a domain; default unlinked.
            linked = 0
            unlinked = len(domain_names)
            return SyncAttempt(
                status=STATUS_OK,
                items_fetched=len(domain_names),
                raw_response=_safe_preview(result),
                extra={"linked": linked, "unlinked": unlinked},
            )
        except Exception as exc:  # noqa: BLE001
            logger.exception("whatsapp.fetch_domains failed")
            return SyncAttempt(status=STATUS_FAILED, error_message=str(exc)[:500])


def _safe_preview(result: Any) -> str:
    try:
        import json

        return json.dumps(result, default=str)[:4000]
    except Exception:  # noqa: BLE001
        return str(result)[:4000]


registry.register(_WhatsAppAdapter())