"""Payment routes (thin). All logic lives in :mod:`app.payments.services`.

Two JSON endpoints back the Razorpay Checkout flow:

* ``POST /create-order`` — server creates the gateway order from the plan price
  and returns the public checkout context (never a secret, never a client amount).
* ``POST /verify`` — verify the Checkout callback signature and, only then,
  activate premium.

Both are login-required and CSRF-protected (the browser sends the CSRF token).
The webhook lives in :mod:`app.payments.webhook` and is CSRF-exempt by design.
"""

from __future__ import annotations

from flask import jsonify, render_template, request, url_for
from flask_login import current_user, login_required

from app.payments import payments_bp, services
from app.payments.razorpay_service import PaymentConfigError, SignatureError


def _payload():
    """Accept either a JSON body or form-encoded fields."""
    return request.get_json(silent=True) or request.form


@payments_bp.route("/create-order", methods=["POST"])
@login_required
def create_order():
    """Create a gateway order for the chosen plan and return checkout context."""
    from app.premium.services import get_active_subscription

    if get_active_subscription(current_user):
        return jsonify(error="already_premium",
                       message="You already have an active Premium subscription."), 400

    plan_name = (_payload().get("plan") or "").strip()
    if not plan_name:
        return jsonify(error="missing_plan", message="Choose a plan to continue."), 400

    try:
        context = services.create_premium_order(current_user, plan_name)
    except services.PlanUnavailableError as exc:
        return jsonify(error="plan_unavailable", message=str(exc)), 400
    except PaymentConfigError:
        return jsonify(error="payments_unavailable",
                       message="Online payments are not available right now."), 503
    return jsonify(context)


@payments_bp.route("/verify", methods=["POST"])
@login_required
def verify():
    """Verify a Checkout callback signature and activate premium on success."""
    data = _payload()
    order_id = (data.get("razorpay_order_id") or "").strip()
    payment_id = (data.get("razorpay_payment_id") or "").strip()
    signature = (data.get("razorpay_signature") or "").strip()
    if not (order_id and payment_id and signature):
        return jsonify(error="missing_fields", message="Incomplete payment details."), 400

    try:
        services.verify_callback(current_user, order_id, payment_id, signature)
    except services.PaymentNotFoundError as exc:
        return jsonify(error="not_found", message=str(exc)), 404
    except SignatureError as exc:
        return jsonify(error="verification_failed", message=str(exc)), 400

    return jsonify(success=True, redirect=url_for("premium.index"))


@payments_bp.route("/history")
@login_required
def history():
    """The user's own payment history + current subscription summary."""
    from app.premium import config
    from app.premium.services import (
        cleanup_expired_premium_users,
        get_active_subscription,
        get_latest_subscription,
        premium_days_remaining,
    )

    cleanup_expired_premium_users()
    active = get_active_subscription(current_user)
    return render_template(
        "payments/history.html",
        payments=services.get_user_payments(current_user),
        active_subscription=active,
        latest_subscription=get_latest_subscription(current_user),
        days_left=premium_days_remaining(current_user) if active else 0,
        currency=config.CURRENCY_SYMBOL,
    )


@payments_bp.route("/receipt/<public_id>")
@login_required
def receipt(public_id: str):
    """A printable receipt for one of the user's own payments (own-only)."""
    from app.premium import config

    payment = services.get_user_payment_or_404(public_id, current_user)
    return render_template(
        "payments/receipt.html",
        payment=payment,
        currency=config.CURRENCY_SYMBOL,
    )
