from flask import Blueprint, flash, redirect, render_template, session, url_for
from ..extensions import db, limiter
from ..forms import UnlockForm
from ..models import AccessKey
from ..security import hash_access_key, normalize_access_key, utcnow_naive
from ..services import log_event

public_bp = Blueprint("public", __name__)


@public_bp.get("/")
def index():
    form = UnlockForm()
    has_session = bool(session.get("delivery_key_id") and session.get("delivery_batch_id"))
    return render_template("public/unlock.html", form=form, has_session=has_session)


@public_bp.post("/unlock")
@limiter.limit("10 per minute")
def unlock():
    form = UnlockForm()
    has_session = bool(session.get("delivery_key_id") and session.get("delivery_batch_id"))
    if not form.validate_on_submit():
        flash("Enter your purchased access key.", "error")
        return render_template("public/unlock.html", form=form, has_session=has_session), 400

    submitted_key = normalize_access_key(form.access_key.data or "")
    hashed_key = hash_access_key(submitted_key)
    access_key = AccessKey.query.filter_by(key_hash=hashed_key).first()

    if access_key is None or not access_key.batch.is_active or not access_key.is_usable:
        log_event("unlock_failed", detail="Invalid or expired key attempt")
        db.session.commit()
        flash("That key is invalid, expired, revoked, or already used up.", "error")
        return render_template("public/unlock.html", form=form, has_session=has_session), 403

    session["delivery_key_id"] = access_key.id
    session["delivery_batch_id"] = access_key.batch_id
    session["delivery_unlocked_at"] = utcnow_naive().isoformat()
    session.permanent = True

    access_key.view_count += 1
    access_key.last_used_at = utcnow_naive()
    log_event("unlock_success", batch=access_key.batch, access_key=access_key)
    db.session.commit()

    return redirect(url_for("public.delivery"))


@public_bp.get("/delivery")
def delivery():
    key_id = session.get("delivery_key_id")
    batch_id = session.get("delivery_batch_id")
    if not key_id or not batch_id:
        flash("Enter your purchased key first.", "info")
        return redirect(url_for("public.index"))

    access_key = AccessKey.query.filter_by(id=key_id, batch_id=batch_id).first()
    if access_key is None or not access_key.batch.is_active or not access_key.is_active:
        session.pop("delivery_key_id", None)
        session.pop("delivery_batch_id", None)
        session.pop("delivery_unlocked_at", None)
        flash("Your session is no longer valid. Unlock again.", "error")
        return redirect(url_for("public.index"))

    credentials = [item.value for item in access_key.batch.credentials]
    return render_template(
        "public/delivery.html",
        batch=access_key.batch,
        credentials=credentials,
        access_key=access_key,
    )


@public_bp.post("/relock")
def relock():
    session.pop("delivery_key_id", None)
    session.pop("delivery_batch_id", None)
    session.pop("delivery_unlocked_at", None)
    flash("The delivery page is locked again.", "info")
    return redirect(url_for("public.index"))
