from pyramid.view import view_config
from pyramid.httpexceptions import HTTPFound

from . import get_referer_or_home

from ..models.shop_subscription import (
    ShopSubscription,
    FREQUENCY_DAILY,
    FREQUENCY_WEEKLY,
    FREQUENCY_IMMEDIATE,
    get_subscription_for_email_and_shop,
    get_subscription_by_unsubscribe_token,
    get_subscription_by_verify_token,
)

from ..lib.mail import send_pyramid_email

from ..lib.mail_messages import (
    VERIFY_SUBSCRIPTION_TEXT,
    VERIFY_SUBSCRIPTION_HTML,
)

import logging

log = logging.getLogger(__name__)


@view_config(route_name="subscribe", renderer="subscribe.j2")
def subscribe(request):
    """Subscribe page — GET renders form, POST handles subscription."""
    shop = request.shop

    if not shop:
        request.session.flash(("No shop found.", "error"))
        return HTTPFound("/")

    if not shop.subscriptions_enabled:
        request.session.flash(("Subscriptions are not available for this shop.", "info"))
        return HTTPFound("/")

    not_authenticated = not (request.user and request.user.authenticated)

    # Look up existing subscription for logged-in users
    current_frequency = None
    if request.user and request.user.authenticated:
        existing_sub = get_subscription_for_email_and_shop(
            request.dbsession, request.user.email, shop.id
        )
        if existing_sub and not existing_sub.disabled:
            current_frequency = existing_sub.frequency
        elif existing_sub and existing_sub.disabled:
            current_frequency = -1

    if request.method == "GET" and not_authenticated:
        request.session.flash(
            ("Enter your email and verify it to get notifications.", "info")
        )

    if request.method == "POST":
        frequency_str = request.params.get("frequency", "0")
        try:
            frequency = int(frequency_str)
        except (ValueError, TypeError):
            frequency = FREQUENCY_DAILY

        # frequency -1 means "None" — disable notifications
        wants_unsubscribe = frequency == -1

        if frequency not in (FREQUENCY_DAILY, FREQUENCY_WEEKLY, FREQUENCY_IMMEDIATE):
            frequency = FREQUENCY_DAILY

        if request.user and request.user.authenticated:
            # Logged-in user: one-click subscribe
            email = request.user.email
            existing = get_subscription_for_email_and_shop(
                request.dbsession, email, shop.id
            )

            if wants_unsubscribe:
                if existing and not existing.disabled:
                    existing.disabled = True
                    request.session.flash(
                        ("You have been unsubscribed.", "success")
                    )
                else:
                    request.session.flash(
                        ("You are not currently subscribed.", "info")
                    )
                return HTTPFound("/subscribe")

            if existing:
                if existing.disabled:
                    # Re-subscribe
                    existing.disabled = False
                    existing.verified = True
                    existing.frequency = frequency
                    request.session.flash(
                        ("You have been re-subscribed.", "success")
                    )
                else:
                    # Update frequency
                    existing.frequency = frequency
                    request.session.flash(
                        ("Your subscription preferences have been updated.", "success")
                    )
            else:
                sub = ShopSubscription(email, shop.id, user_id=request.user.id)
                sub.frequency = frequency
                request.dbsession.add(sub)
                request.dbsession.flush()
                request.session.flash(
                    ("You are now subscribed.", "success")
                )

            return HTTPFound("/subscribe")

        else:
            # Anonymous user: needs email verification
            email = request.params.get("email", "").strip().lower()

            if not email or "@" not in email:
                request.session.flash(
                    ("Please enter a valid email address.", "error")
                )
                return HTTPFound("/subscribe")

            if wants_unsubscribe:
                existing = get_subscription_for_email_and_shop(
                    request.dbsession, email, shop.id
                )
                if existing and not existing.disabled:
                    existing.disabled = True
                    request.session.flash(
                        ("You have been unsubscribed.", "success")
                    )
                else:
                    request.session.flash(
                        ("No active subscription found for that email.", "info")
                    )
                return HTTPFound("/subscribe")

            existing = get_subscription_for_email_and_shop(
                request.dbsession, email, shop.id
            )

            if existing:
                if existing.disabled:
                    # Re-subscribe — send new verification
                    existing.disabled = False
                    existing.verified = False
                    existing.frequency = frequency
                    import secrets
                    existing.verify_token = secrets.token_urlsafe(32)
                    _send_verification_email(request, existing)
                    request.session.flash(
                        (
                            "A verification email has been sent. Please check your inbox.",
                            "success",
                        )
                    )
                elif existing.verified:
                    # Already subscribed, update frequency
                    existing.frequency = frequency
                    request.session.flash(
                        (
                            "You are already subscribed. Your preferences have been updated.",
                            "success",
                        )
                    )
                else:
                    # Resend verification
                    _send_verification_email(request, existing)
                    request.session.flash(
                        (
                            "A verification email has been sent. Please check your inbox.",
                            "success",
                        )
                    )
            else:
                sub = ShopSubscription(email, shop.id)
                sub.frequency = frequency
                request.dbsession.add(sub)
                request.dbsession.flush()
                _send_verification_email(request, sub)
                request.session.flash(
                    (
                        "A verification email has been sent. Please check your inbox.",
                        "success",
                    )
                )

            return HTTPFound("/subscribe")

    return {"current_frequency": current_frequency}


@view_config(route_name="subscribe_verify", renderer="subscribe.j2")
def subscribe_verify(request):
    """Verify an email subscription via token link."""
    token = request.matchdict.get("token", "")
    sub = get_subscription_by_verify_token(request.dbsession, token)

    if sub:
        sub.verified = True
        sub.verify_token = None
        request.session.flash(
            ("Your email has been verified. You are now subscribed.", "success")
        )
    else:
        request.session.flash(
            ("Invalid or expired verification link.", "error")
        )

    return HTTPFound("/subscribe")


@view_config(route_name="unsubscribe", renderer="subscribe.j2")
def unsubscribe(request):
    """One-click unsubscribe via token link."""
    token = request.matchdict.get("token", "")
    sub = get_subscription_by_unsubscribe_token(request.dbsession, token)

    if sub:
        sub.disabled = True
        request.session.flash(
            ("You have been unsubscribed.", "success")
        )
    else:
        request.session.flash(
            ("Invalid unsubscribe link.", "error")
        )

    return HTTPFound("/")


def _send_verification_email(request, subscription):
    """Send a verification email for anonymous subscriptions."""
    verify_url = request.route_url(
        "subscribe_verify", token=subscription.verify_token
    )
    unsubscribe_url = request.route_url(
        "unsubscribe", token=subscription.unsubscribe_token
    )
    shop_name = request.shop.name if request.shop else "this shop"

    subject = f"Verify your subscription to {shop_name}"
    message_text = VERIFY_SUBSCRIPTION_TEXT.format(
        shop_name, verify_url, unsubscribe_url
    )
    message_html = VERIFY_SUBSCRIPTION_HTML.format(
        subject, shop_name, verify_url, unsubscribe_url
    )
    send_pyramid_email(request, subscription.email, subject, message_text, message_html)
