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

from . import (
    user_required,
    shop_owner_required,
    trial_active_required,
    get_referer_or_home,
)

from ..models.gift_card import (
    GiftCard,
    get_gift_card_by_id,
    get_gift_card_by_code,
    get_gift_cards_by_shop,
)
from ..models.cart import get_cart_by_id
from ..lib.currency import validate_int, cents_to_dollars, dollars_to_cents


@view_config(route_name="gift_card_page", renderer="gift_card.j2")
def gift_card_page(request):
    """Gift card purchase page for a shop."""
    shop = request.shop
    if not shop or not shop.gift_card_enabled:
        request.session.flash(("Gift cards are not available for this shop.", "error"))
        return HTTPFound(get_referer_or_home(request))

    # Handle balance check
    balance_result = None
    check_code = request.params.get("check_code", "").strip()
    if check_code:
        card = get_gift_card_by_code(request.dbsession, check_code, shop=shop)
        if card and card.is_valid:
            balance_result = {
                "code": card.code,
                "balance": card.balance,
                "initial_amount": card.initial_amount,
            }
        elif card and card.disabled:
            balance_result = {"error": "This gift card has been disabled."}
        elif card and card.is_fully_redeemed:
            balance_result = {"error": "This gift card has been fully redeemed."}
        else:
            balance_result = {"error": "Gift card not found for this shop."}

    return {
        "shop": shop,
        "min_dollars": cents_to_dollars(shop.gift_card_min_in_cents),
        "max_dollars": cents_to_dollars(shop.gift_card_max_in_cents),
        "balance_result": balance_result,
    }


@view_config(route_name="gift_card_add_to_cart", request_method="POST", require_csrf=True)
@user_required()
@trial_active_required()
def gift_card_add_to_cart(request):
    """Add a gift card to the active cart."""
    shop = request.shop
    if not shop or not shop.gift_card_enabled:
        request.session.flash(("Gift cards are not available for this shop.", "error"))
        return HTTPFound(get_referer_or_home(request))

    try:
        amount_dollars = float(request.params.get("amount", "0"))
        amount_in_cents = int(amount_dollars * 100)
    except (ValueError, TypeError):
        request.session.flash(("Invalid amount.", "error"))
        return HTTPFound(get_referer_or_home(request))

    if amount_in_cents < shop.gift_card_min_in_cents:
        request.session.flash(
            (f"Minimum gift card amount is ${cents_to_dollars(shop.gift_card_min_in_cents):,.2f}.", "error")
        )
        return HTTPFound(get_referer_or_home(request))

    if amount_in_cents > shop.gift_card_max_in_cents:
        request.session.flash(
            (f"Maximum gift card amount is ${cents_to_dollars(shop.gift_card_max_in_cents):,.2f}.", "error")
        )
        return HTTPFound(get_referer_or_home(request))

    gift_email = request.params.get("gift_email", "").strip() or None
    gift_message = request.params.get("gift_message", "").strip() or None

    # Store gift card purchase intent in cart's json_gift_cards
    import json
    cart = request.active_cart
    gift_cards_data = json.loads(cart.json_gift_cards) if hasattr(cart, 'json_gift_cards') and cart.json_gift_cards else []
    gift_cards_data.append({
        "shop_id": shop.uuid_str,
        "amount_in_cents": amount_in_cents,
        "gift_email": gift_email,
        "gift_message": gift_message,
    })
    cart.json_gift_cards = json.dumps(gift_cards_data)
    request.dbsession.add(cart)
    request.dbsession.flush()

    request.session.flash(
        (f"${amount_dollars:,.2f} gift card added to cart.", "success")
    )
    return HTTPFound(f"/cart/{cart.id}")


@view_config(route_name="gift_card_apply_to_cart", request_method="POST", require_csrf=True)
def gift_card_apply_to_cart(request):
    """Apply a gift card code to the active cart (for redemption at checkout)."""
    code = request.params.get("gift_card_code", "").strip()

    if not code:
        request.session.flash(("Please enter a gift card code.", "error"))
        return HTTPFound(f"/cart/{request.active_cart.id}")

    gift_card = get_gift_card_by_code(request.dbsession, code)

    if gift_card is None:
        request.session.flash(("That gift card code does not exist.", "error"))
        return HTTPFound(f"/cart/{request.active_cart.id}")

    if gift_card.disabled:
        request.session.flash(("That gift card has been disabled.", "error"))
        return HTTPFound(f"/cart/{request.active_cart.id}")

    if gift_card.balance_in_cents <= 0:
        request.session.flash(("That gift card has no remaining balance.", "error"))
        return HTTPFound(f"/cart/{request.active_cart.id}")

    # Check if gift card's shop is in the cart
    if gift_card.shop_uuid_str not in request.active_cart.shop_totals_in_cents:
        request.session.flash(
            ("That gift card is not valid for any shop in your cart.", "error")
        )
        return HTTPFound(f"/cart/{request.active_cart.id}")

    if gift_card not in request.active_cart.gift_cards:
        request.active_cart.gift_cards.append(gift_card)
        request.active_cart._bust_memoized_attributes()
        request.dbsession.add(request.active_cart)
        request.dbsession.flush()
        msg = (
            f"Gift card applied! Balance: ${gift_card.balance:,.2f}",
            "success",
        )
    else:
        msg = ("That gift card is already applied to your cart.", "info")

    request.session.flash(msg)
    return HTTPFound(f"/cart/{request.active_cart.id}")


@view_config(route_name="gift_card_remove_from_cart", request_method="POST", require_csrf=True)
def gift_card_remove_from_cart(request):
    """Remove a gift card from a cart."""
    cart_id = request.params.get("cart_id")
    gift_card_id = request.params.get("gift_card_id")

    cart = get_cart_by_id(request.dbsession, cart_id)
    gift_card = get_gift_card_by_id(request.dbsession, gift_card_id)

    if cart is None:
        msg = ("That cart does not exist.", "error")
    elif gift_card is None:
        msg = ("That gift card does not exist.", "error")
    elif request.user and request.user.does_not_own_cart(cart):
        msg = ("You do not own that cart.", "error")
    elif request.user is None and cart.user is not None:
        msg = ("You do not own this cart.", "error")
    else:
        if gift_card in cart.gift_cards:
            cart.gift_cards.remove(gift_card)
            cart._bust_memoized_attributes()
            request.dbsession.add(cart)
            request.dbsession.flush()
            msg = ("Gift card removed from your cart.", "success")
        else:
            msg = ("That gift card was already removed from your cart.", "info")
        request.session.flash(msg)
        return HTTPFound(f"/cart/{cart_id}")

    request.session.flash(msg)
    return HTTPFound(get_referer_or_home(request))


# --- Shop Admin Views ---


@view_config(route_name="gift_card_manage", renderer="gift_card_manage.j2")
@shop_owner_required()
def gift_card_manage(request):
    """Gift card management page for shop owners."""
    shop = request.shop
    gift_cards = get_gift_cards_by_shop(request.dbsession, shop).all()
    total_issued = sum(gc.initial_amount_in_cents for gc in gift_cards)
    total_balance = sum(gc.balance_in_cents for gc in gift_cards)

    return {
        "gift_cards": gift_cards,
        "total_issued_dollars": cents_to_dollars(total_issued),
        "total_balance_dollars": cents_to_dollars(total_balance),
    }


@view_config(route_name="gift_card_detail", renderer="gift_card_detail.j2")
@shop_owner_required()
def gift_card_detail(request):
    """Gift card detail page for shop owners."""
    gift_card = get_gift_card_by_id(request.dbsession, request.matchdict["gift_card_id"])
    if gift_card is None:
        request.session.flash(("Gift card not found.", "error"))
        return HTTPFound(get_referer_or_home(request))

    from ..models.gift_card_transaction import GiftCardTransaction as GCT
    transactions = list(gift_card.transactions)

    return {
        "gift_card": gift_card,
        "transactions": transactions,
    }


@view_config(route_name="gift_card_toggle", request_method="POST", require_csrf=True)
@shop_owner_required()
def gift_card_toggle(request):
    """Enable/disable a gift card (admin kill switch)."""
    gift_card = get_gift_card_by_id(request.dbsession, request.matchdict["gift_card_id"])
    if gift_card is None:
        request.session.flash(("Gift card not found.", "error"))
        return HTTPFound(get_referer_or_home(request))

    gift_card.disabled = not gift_card.disabled
    request.dbsession.add(gift_card)
    request.dbsession.flush()

    status = "disabled" if gift_card.disabled else "enabled"
    request.session.flash((f"Gift card {gift_card.code} {status}.", "success"))
    return HTTPFound(get_referer_or_home(request))
