"""
BizNode Webhook Sync Service
==============================
Polls the VPS (biznode.1bz.biz) for unprocessed Stripe webhook events
and processes them locally (license key generation, email notifications, etc.).

Architecture:
  VPS webhook.php → stores in MySQL dzit_stripe_tracker → marks pending
  This service → polls /api_webhook_queue.php?action=poll every 2 min
               → processes events (license purchases, payments)
               → acknowledges via /api_webhook_queue.php?action=ack

ADMIN-ONLY — never included in customer packages.
"""

import importlib.util
import logging
import os
from datetime import datetime, timezone
from pathlib import Path

import requests

log = logging.getLogger("biznode.webhook_sync")
_PROJECT_ROOT = Path(__file__).resolve().parent.parent


# ── Config (from admin.env via config.py) ─────────────────────────────────────

def _get_config():
    """Load admin config."""
    try:
        from tools.admin.config import admin_config
        return admin_config
    except ImportError:
        pass
    # Fallback: load manually
    admin_env = _PROJECT_ROOT / "tools" / "admin" / "admin.env"
    cfg = {}
    if admin_env.exists():
        with open(admin_env, encoding="utf-8") as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith("#") and "=" in line:
                    k, _, v = line.partition("=")
                    cfg[k.strip()] = v.strip().strip("\"'")
    return cfg


def _cfg_val(key: str, default: str = "") -> str:
    """Get config value from admin config or env."""
    cfg = _get_config()
    if hasattr(cfg, key):
        return getattr(cfg, key)
    if isinstance(cfg, dict):
        return cfg.get(key, os.getenv(key, default))
    return os.getenv(key, default)


VPS_BASE_URL = _cfg_val("ADMIN_SITE_URL", "https://biznode.1bz.biz")
ADMIN_API_KEY = _cfg_val("ADMIN_API_KEY", "biznode-admin-2026")
WEBHOOK_QUEUE_URL = f"{VPS_BASE_URL}/api_webhook_queue.php"


# ── DB loader ─────────────────────────────────────────────────────────────────

def _load_db():
    spec = importlib.util.spec_from_file_location(
        "_db", str(_PROJECT_ROOT / "memory" / "database.py")
    )
    mod = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mod)
    return mod


# ── Telegram alert (to owner) ────────────────────────────────────────────────

ALERT_BOT_TOKEN = os.getenv(
    "ALERT_BOT_TOKEN", "8736395099:AAE3Vr8l8tf4gjF2yFUgO64-Gb83A-hqy-c"
)
ALERT_CHAT_ID = _cfg_val("ADMIN_TELEGRAM_CHAT_ID", "7668967550")


def _send_telegram_alert(message: str):
    """Send Telegram notification to owner."""
    try:
        url = f"https://api.telegram.org/bot{ALERT_BOT_TOKEN}/sendMessage"
        requests.post(url, json={
            "chat_id": ALERT_CHAT_ID,
            "text": message,
            "parse_mode": "HTML",
        }, timeout=5)
    except Exception as e:
        log.warning("Telegram alert failed: %s", e)


# ── Poll VPS for unprocessed events ──────────────────────────────────────────

def poll_webhook_queue(limit: int = 50) -> dict:
    """
    Poll VPS for unprocessed webhook events.
    Returns: {"ok": bool, "events": [...], "count": int}
    """
    try:
        resp = requests.get(
            WEBHOOK_QUEUE_URL,
            params={"action": "poll", "limit": limit},
            headers={"X-Admin-Key": ADMIN_API_KEY},
            timeout=15,
        )
        if resp.status_code != 200:
            log.warning("VPS poll returned HTTP %d: %s", resp.status_code, resp.text[:200])
            return {"ok": False, "error": f"HTTP {resp.status_code}"}
        return resp.json()
    except requests.RequestException as e:
        log.warning("VPS poll failed: %s", e)
        return {"ok": False, "error": str(e)}


def acknowledge_events(event_ids: list) -> dict:
    """Mark events as processed on VPS."""
    if not event_ids:
        return {"ok": True, "acknowledged": 0}
    try:
        resp = requests.post(
            f"{WEBHOOK_QUEUE_URL}?action=ack",
            headers={
                "X-Admin-Key": ADMIN_API_KEY,
                "Content-Type": "application/json",
            },
            json={"event_ids": event_ids},
            timeout=15,
        )
        return resp.json()
    except requests.RequestException as e:
        log.warning("VPS ack failed: %s", e)
        return {"ok": False, "error": str(e)}


# ── Process individual events ────────────────────────────────────────────────

def _process_license_event(event: dict) -> bool:
    """Process a BizNode license purchase event.
    Handles 7-tier system: detects tier from amount, creates hosted agent, sends welcome email."""
    try:
        from services.license_purchase_service import handle_stripe_license_payment

        email = event.get("customer_email", "")
        amount_cents = event.get("amount_cents", 0)
        stripe_event_id = event.get("stripe_event_id", "")
        payment_link = event.get("payment_link", "")

        amount_usd = amount_cents / 100

        # Detect tier from amount (7-tier system)
        AMOUNT_TO_TIER = {
            20: ("basic", "basic"),
            50: ("standard", "basic"),
            100: ("pro", "basic"),
            150: ("bizplus", "basic"),
            200: ("bizmax", "basic"),
            499: ("biznode", "pro"),
            1500: ("onezbnode", "pro"),
        }
        # Find closest tier match
        tier_name, license_type = "basic", "basic"
        for price, (t, lt) in sorted(AMOUNT_TO_TIER.items()):
            if amount_usd >= price:
                tier_name, license_type = t, lt

        log.info(
            "Processing license purchase: email=%s tier=%s amount=$%.2f event=%s",
            email, tier_name, amount_usd, stripe_event_id
        )

        # Check if already processed (idempotency)
        db = _load_db()
        existing = None
        try:
            conn = db.get_connection()
            cursor = conn.cursor()
            cursor.execute(
                "SELECT id FROM license_purchases WHERE stripe_payment_intent = %s",
                (stripe_event_id,)
            )
            existing = cursor.fetchone()
            cursor.close()
            conn.close()
        except Exception:
            pass

        if existing:
            log.info("License purchase already processed: %s", stripe_event_id)
            return True

        # Process via legacy license system (generates key, emails customer)
        result = handle_stripe_license_payment(
            reference_no=None,
            payment_intent=stripe_event_id,
            amount=amount_usd,
            currency="usd",
            telegram_id="",
            email=email,
            license_type=license_type,
        )

        # Auto-create hosted agent for the customer
        agent_id = ""
        try:
            from services.hosted_agent_service import HostedAgentService
            svc = HostedAgentService()
            agent_result = svc.register_agent(
                owner_email=email,
                tier=tier_name,
            )
            if agent_result.get("success"):
                agent_id = agent_result["agent_id"]
                log.info("Hosted agent created: %s for %s (tier=%s)", agent_id, email, tier_name)
            else:
                log.warning("Hosted agent creation failed: %s", agent_result.get("error"))
        except Exception as exc:
            log.warning("Hosted agent auto-creation failed: %s", exc)

        if result.get("ok"):
            license_key = result.get("license_key", "")
            tier_label = tier_name.upper()
            agent_info = f"\nAgent: <code>{agent_id}</code>" if agent_id else ""
            _send_telegram_alert(
                f"<b>New {tier_label} Purchase!</b>\n\n"
                f"Tier: <b>{tier_label}</b> (${amount_usd:.0f})\n"
                f"Key: <code>{license_key}</code>\n"
                f"Email: {email}{agent_info}\n"
                f"Stripe: <code>{stripe_event_id[:20]}...</code>"
            )
            log.info("License generated: %s for %s (tier=%s)", license_key, email, tier_name)
            return True
        else:
            log.error("License generation failed: %s", result.get("error"))
            return False

    except Exception as e:
        log.error("License event processing failed: %s", e, exc_info=True)
        return False


def _process_payment_event(event: dict) -> bool:
    """Process a general payment event (voucher, topup, book sale)."""
    try:
        category = event.get("category", "UNKNOWN")
        email = event.get("customer_email", "")
        amount_cents = event.get("amount_cents", 0)
        worker_type = event.get("worker_type", "unknown")

        log.info(
            "Synced payment event: cat=%s worker=%s email=%s amount=%d",
            category, worker_type, email, amount_cents
        )

        # Store in local DB for admin dashboard visibility
        db = _load_db()
        try:
            conn = db.get_connection()
            cursor = conn.cursor()
            cursor.execute("""
                INSERT INTO owner_actions (action_type, details, created_at)
                VALUES (%s, %s, %s)
            """, (
                f"webhook_sync:{worker_type}",
                f"Payment from {email}: {amount_cents} cents ({category})",
                datetime.now(timezone.utc).isoformat(),
            ))
            conn.commit()
            cursor.close()
            conn.close()
        except Exception as e:
            log.warning("Could not log payment event locally: %s", e)

        return True

    except Exception as e:
        log.error("Payment event processing failed: %s", e)
        return False


# ── Main sync function ───────────────────────────────────────────────────────

def sync_webhook_events() -> dict:
    """
    Poll VPS for unprocessed webhook events, process them, and acknowledge.
    Called by scheduler every 2 minutes.

    Returns: {"polled": int, "processed": int, "failed": int, "errors": [...]}
    """
    result = {"polled": 0, "processed": 0, "failed": 0, "errors": []}

    # Poll
    poll_result = poll_webhook_queue()
    if not poll_result.get("ok"):
        result["errors"].append(poll_result.get("error", "Poll failed"))
        return result

    events = poll_result.get("events", [])
    license_events = poll_result.get("license_events", [])
    result["polled"] = len(events)

    if not events and not license_events:
        return result  # Nothing to process

    log.info("Webhook sync: %d events, %d license events", len(events), len(license_events))

    # Collect license event IDs for priority processing
    license_event_ids = {e.get("id") for e in license_events}

    processed_ids = []
    failed_ids = []

    for event in events:
        event_id = event.get("id")
        category = event.get("category", "")

        # License purchases get special handling
        if event_id in license_event_ids or category == "BIZNODE_LICENSE":
            success = _process_license_event(event)
        else:
            success = _process_payment_event(event)

        if success:
            processed_ids.append(event_id)
            result["processed"] += 1
        else:
            failed_ids.append(event_id)
            result["failed"] += 1

    # Acknowledge processed events
    if processed_ids:
        ack_result = acknowledge_events(processed_ids)
        if not ack_result.get("ok"):
            result["errors"].append(f"Ack failed: {ack_result.get('error')}")
        else:
            log.info("Acknowledged %d events on VPS", len(processed_ids))

    if result["processed"] > 0 or result["failed"] > 0:
        log.info(
            "Webhook sync complete: polled=%d processed=%d failed=%d",
            result["polled"], result["processed"], result["failed"]
        )

    return result


def get_queue_status() -> dict:
    """Check VPS webhook queue status."""
    try:
        resp = requests.get(
            WEBHOOK_QUEUE_URL,
            params={"action": "status"},
            headers={"X-Admin-Key": ADMIN_API_KEY},
            timeout=10,
        )
        return resp.json()
    except Exception as e:
        return {"ok": False, "error": str(e)}


# ── CLI ──────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    import sys
    logging.basicConfig(level=logging.INFO, format="%(levelname)s %(name)s %(message)s")

    if len(sys.argv) > 1 and sys.argv[1] == "status":
        print(get_queue_status())
    else:
        print("Running webhook sync...")
        result = sync_webhook_events()
        print(f"Result: {result}")
