"""
Marziel AI — Billing & License Management

Handles Stripe payment integration and local license file management.
Exposes Flask routes as a Blueprint for clean separation from the main server.
"""

import json
import time
import logging
import urllib.request
import urllib.parse
from flask import Blueprint, request, jsonify

import hashlib
import hmac
from marziel.config import (
    STRIPE_SECRET_KEY,
    STRIPE_PRICES,
    PRICE_TO_TIER,
    LICENSE_FILE,
    STRIPE_WEBHOOK_SECRET,
    MARZIEL_HF_TOKEN,
)

logger = logging.getLogger("marziel.billing")

billing_bp = Blueprint("billing", __name__)


# ── Webhook signature verification ────────────────────────

def _verify_stripe_signature(payload: bytes, sig_header: str, secret: str) -> bool:
    """Verify Stripe webhook signature (v1 scheme, HMAC-SHA256)."""
    if not sig_header or not secret:
        return False
    try:
        parts = dict(kv.split("=", 1) for kv in sig_header.split(","))
        timestamp = parts.get("t", "")
        expected_sig = parts.get("v1", "")
        if not timestamp or not expected_sig:
            return False

        signed_payload = f"{timestamp}.".encode() + payload
        computed = hmac.new(
            secret.encode(), signed_payload, hashlib.sha256
        ).hexdigest()
        return hmac.compare_digest(computed, expected_sig)
    except Exception:
        return False


# ── License file helpers ──────────────────────────────────

def read_license() -> dict:
    """Read the current license from ~/.marziel/license.json."""
    try:
        if LICENSE_FILE.exists():
            return json.loads(LICENSE_FILE.read_text())
    except Exception:
        pass
    return {"tier": "free"}


def write_license(data: dict) -> None:
    """Write license data to ~/.marziel/license.json."""
    LICENSE_FILE.parent.mkdir(parents=True, exist_ok=True)
    LICENSE_FILE.write_text(json.dumps(data, indent=2))


# ── Stripe API helpers ────────────────────────────────────

def _stripe_request(endpoint: str, params: dict) -> dict:
    """Make a form-encoded POST to the Stripe API."""
    form_data = urllib.parse.urlencode(params).encode()
    req = urllib.request.Request(
        f"https://api.stripe.com{endpoint}",
        data=form_data,
        headers={
            "Authorization": f"Bearer {STRIPE_SECRET_KEY}",
            "Content-Type": "application/x-www-form-urlencoded",
        },
    )
    resp = urllib.request.urlopen(req, timeout=30)
    return json.loads(resp.read().decode())


# ── Flask Routes ──────────────────────────────────────────

@billing_bp.route("/api/license", methods=["GET", "POST"])
def handle_license():
    """GET: return license. POST: update tier (for downgrade/testing)."""
    if request.method == "GET":
        return jsonify(read_license())

    data = request.get_json(force=True)
    new_tier = data.get("tier", "")
    if new_tier not in ("free", "pro", "enterprise"):
        return jsonify({"error": "Invalid tier"}), 400

    current = read_license()
    current["tier"] = new_tier
    if new_tier == "free":
        current.pop("hf_token", None)
    write_license(current)
    logger.info(f"License updated: {new_tier}")
    return jsonify(current)


@billing_bp.route("/api/checkout", methods=["POST"])
def create_checkout():
    """Create a Stripe Checkout session for a tier upgrade."""
    data = request.get_json(force=True)
    tier = data.get("tier", "")
    price_id = STRIPE_PRICES.get(tier)

    if not price_id:
        return jsonify({"error": f"Invalid tier: {tier}"}), 400

    try:
        session = _stripe_request("/v1/checkout/sessions", {
            "mode": "subscription",
            "line_items[0][price]": price_id,
            "line_items[0][quantity]": "1",

            "success_url": f"http://localhost:3333/?checkout=success&tier={tier}",
            "cancel_url": "http://localhost:3333/?checkout=cancel",
            "metadata[tier]": tier,
        })
        return jsonify({"url": session.get("url", "")})
    except Exception as e:
        logger.error(f"Stripe checkout failed: {e}")
        return jsonify({"error": str(e)}), 500


@billing_bp.route("/api/webhook", methods=["POST"])
def stripe_webhook():
    """Handle Stripe webhook events with signature verification."""
    payload = request.get_data()
    sig_header = request.headers.get("Stripe-Signature", "")

    # Verify signature if webhook secret is configured (production)
    if STRIPE_WEBHOOK_SECRET:
        if not _verify_stripe_signature(payload, sig_header, STRIPE_WEBHOOK_SECRET):
            logger.warning("⚠️ Webhook signature verification failed")
            return jsonify({"error": "Invalid signature"}), 400
    else:
        logger.warning("⚠️ No STRIPE_WEBHOOK_SECRET set — skipping signature verification (dev mode)")

    try:
        event = json.loads(payload)
    except Exception as e:
        logger.error(f"Webhook parse failed: {e}")
        return jsonify({"error": "Invalid payload"}), 400

    event_type = event.get("type", "")
    session = event.get("data", {}).get("object", {})

    if event_type == "checkout.session.completed":
        tier = session.get("metadata", {}).get("tier", "pro")
        license_data = {
            "tier": tier,
            "email": session.get("customer_email", ""),
            "subscription_id": session.get("subscription", ""),
            "activated_at": time.strftime("%Y-%m-%d %H:%M:%S"),
            "stripe_customer": session.get("customer", ""),
        }
        # Provision HF token for model download
        if MARZIEL_HF_TOKEN:
            license_data["hf_token"] = MARZIEL_HF_TOKEN
        write_license(license_data)
        logger.info(f"✅ License activated: {tier} (model access granted)")

    elif event_type == "customer.subscription.deleted":
        write_license({"tier": "free", "deactivated_at": time.strftime("%Y-%m-%d %H:%M:%S")})
        logger.info("⚠️ Subscription cancelled → reverted to free")

    return jsonify({"received": True})

