"""Billing routes — Stripe Checkout (B-2.7).

URL space (prefix `/checkout`, set on billing_bp):
- GET  /checkout/<plan>?period=monthly|yearly  → 303 redirect to Stripe-hosted Checkout
- GET  /checkout/success?session_id=...        → confirmation page (async activation note)
- GET  /checkout/cancel                        → friendly "no charge made" page

The webhook route (B-2.8) is registered at /checkout/webhooks/stripe (under
the same blueprint prefix) and is CSRF-exempt (signature-verified instead).
"""
import logging

from flask import (
    Blueprint, current_app, flash, redirect, render_template,
    request, url_for,
)
from flask_login import current_user, login_required

from src.billing import billing_bp
from src.billing.plans import VALID_PERIODS, get_plan
from src.billing.stripe_client import (
    StripeNotConfiguredError,
    create_checkout_session,
    is_stripe_configured,
)

logger = logging.getLogger(__name__)


@billing_bp.route('/<plan>')
@login_required
def checkout(plan):
    """Initiate Stripe Checkout for the given plan + period.

    Redirects to /tarifs with a French flash on any error (unknown plan,
    Stripe not configured, plan Price IDs missing, Stripe API failure).
    Returns a 303 See Other redirect to the Stripe-hosted Checkout on success
    (303 is what Stripe documents for HTTP redirects to checkout.stripe.com).
    """
    plan_obj = get_plan(plan)
    if plan_obj is None:
        flash('Forfait inconnu.', 'danger')
        return redirect(url_for('marketing.tarifs'))

    period = request.args.get('period', 'monthly')
    if period not in VALID_PERIODS:
        period = 'monthly'

    if not is_stripe_configured():
        flash(
            "Le paiement en ligne n'est pas disponible pour le moment. "
            "Contactez info@dictia.ca pour finaliser votre abonnement.",
            'warning',
        )
        return redirect(url_for('marketing.tarifs'))

    if not plan_obj.is_configured():
        flash(
            "Ce forfait n'est pas encore configuré. Contactez info@dictia.ca.",
            'warning',
        )
        return redirect(url_for('marketing.tarifs'))

    success_url = url_for('billing.success', _external=True)
    cancel_url = url_for('billing.cancel', _external=True)

    try:
        session = create_checkout_session(
            plan_slug=plan,
            period=period,
            user=current_user,
            success_url=success_url,
            cancel_url=cancel_url,
        )
    except StripeNotConfiguredError as e:
        logger.error('Stripe not configured at checkout: %s', e)
        flash(
            "Le paiement en ligne n'est pas disponible. "
            "Contactez info@dictia.ca.",
            'warning',
        )
        return redirect(url_for('marketing.tarifs'))
    except ValueError as e:
        logger.warning('Invalid checkout request: %s', e)
        flash('Demande de paiement invalide.', 'danger')
        return redirect(url_for('marketing.tarifs'))
    except Exception as e:  # noqa: BLE001
        logger.exception(
            'Stripe Checkout creation failed for user %s plan %s: %s',
            getattr(current_user, 'id', '?'), plan, e,
        )
        flash(
            "Une erreur est survenue lors de l'ouverture du paiement. "
            "Réessayez ou contactez info@dictia.ca.",
            'danger',
        )
        return redirect(url_for('marketing.tarifs'))

    # Stripe documents 303 See Other for hosted-Checkout redirects.
    return redirect(session.url, code=303)


@billing_bp.route('/success')
def success():
    """Post-payment confirmation page.

    The session_id query param is preserved for optional client-side analytics
    but is NOT trusted server-side — Stripe's webhook (B-2.8) is the source of
    truth for subscription state. This page makes that asynchrony explicit
    ("Votre abonnement sera activé sous quelques minutes.").
    """
    session_id = request.args.get('session_id')
    return render_template(
        'billing/success.html',
        title='Paiement confirmé — DictIA',
        session_id=session_id,
    )


@billing_bp.route('/cancel')
def cancel():
    """User cancelled the Stripe Checkout. No state to revert; no charge made."""
    return render_template(
        'billing/cancel.html',
        title='Paiement annulé — DictIA',
    )
