#!/usr/bin/env python3
"""BizHub CRM webhook receiver (Phase 8 sample).

Verify Stripe-style signature:
  X-BizHub-Signature: sha256=<hex>
  X-BizHub-Timestamp: <unix>
  signed payload = f"{timestamp}.{raw_body}"

Env:
  BIZHUB_WEBHOOK_SECRET  — secret from кабинет → Уведомления → Webhooks (shown once)
  BIZHUB_API_KEY         — optional bh_live_… for auto-reply demo
  BIZHUB_APP_URL         — default https://bizhub.com.ru
  PORT                   — default 8787

Run:
  pip install flask
  BIZHUB_WEBHOOK_SECRET=whsec_… python3 crm-webhook-receiver.py
"""

from __future__ import annotations

import hashlib
import hmac
import json
import os
import time
import urllib.request

from flask import Flask, abort, request

app = Flask(__name__)
SECRET = os.environ.get("BIZHUB_WEBHOOK_SECRET", "").encode()
API_KEY = os.environ.get("BIZHUB_API_KEY", "")
APP_URL = os.environ.get("BIZHUB_APP_URL", "https://bizhub.com.ru").rstrip("/")
MAX_SKEW = 300  # seconds


def verify(secret: bytes, timestamp: str, body: bytes, header: str) -> bool:
    if not secret or not timestamp or not header:
        return False
    try:
        ts = int(timestamp)
    except ValueError:
        return False
    if abs(int(time.time()) - ts) > MAX_SKEW:
        return False
    sig = header.removeprefix("sha256=").strip()
    mac = hmac.new(secret, f"{timestamp}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(mac, sig)


def reply_review(review_id: str, text: str) -> dict:
    req = urllib.request.Request(
        f"{APP_URL}/api/v1/reviews/{review_id}/reply",
        data=json.dumps({"text": text}).encode(),
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
        method="POST",
    )
    with urllib.request.urlopen(req, timeout=20) as res:
        return json.loads(res.read().decode())


@app.post("/bizhub/webhook")
def webhook():
    body = request.get_data()
    if not verify(
        SECRET,
        request.headers.get("X-BizHub-Timestamp", ""),
        body,
        request.headers.get("X-BizHub-Signature", ""),
    ):
        abort(401)
    payload = json.loads(body.decode() or "{}")
    event = payload.get("event") or request.headers.get("X-BizHub-Event")
    review = (payload.get("data") or {}).get("review") or {}
    print("event", event, "review", review.get("id"), "rating", review.get("rating"))

    # Demo: auto-ack only 5★ if API key set (never for ≤3★).
    if (
        event == "review.created"
        and API_KEY
        and int(review.get("rating") or 0) >= 5
        and not review.get("replied")
    ):
        try:
            out = reply_review(
                review["id"],
                "Спасибо за высокую оценку! Будем рады видеть вас снова.",
            )
            print("reply", out.get("status"), out.get("published"))
        except Exception as exc:  # noqa: BLE001
            print("reply_failed", exc)

    return {"ok": True}


if __name__ == "__main__":
    if not SECRET:
        raise SystemExit("Set BIZHUB_WEBHOOK_SECRET")
    app.run(host="0.0.0.0", port=int(os.environ.get("PORT", "8787")))
