"""HTTP error handlers."""
import os
import traceback
from flask import flash, jsonify, redirect, render_template, request, session, url_for

from nexora.config import BASE_DIR, logger
from nexora.core import app
from nexora.utils.helpers import wants_json_response


@app.errorhandler(400)
def bad_request(_error):
    if wants_json_response():
        return jsonify({"ok": False, "status": "bad_request", "message": "Bad request."}), 400
    if request.path.startswith("/admin"):
        flash("Bad request. Please reload the admin page and try again.", "danger")
        return redirect(url_for("admin_dashboard") if session.get("admin") else url_for("admin_login")), 302
    flash("Bad request.", "danger")
    return redirect(request.referrer or url_for("index")), 302


@app.errorhandler(403)
def forbidden(_error):
    wants_json = request.is_json or request.headers.get("X-Requested-With") == "XMLHttpRequest"
    if request.path.startswith("/admin/api") or (request.path.startswith("/admin") and wants_json):
        return jsonify({"ok": False, "status": "forbidden", "message": "403 Forbidden: you do not have permission."}), 403
    if request.path.startswith("/admin") or request.accept_mimetypes.best == "application/json":
        return render_template("403.html"), 403
    flash("You do not have permission to access this page.", "danger")
    return redirect(request.referrer or url_for("index")), 302


@app.errorhandler(404)
def not_found(_error):
    if wants_json_response():
        return jsonify({"ok": False, "status": "not_found", "message": "Resource not found."}), 404
    if request.path.startswith("/admin"):
        flash("Admin page not found.", "danger")
        return redirect(url_for("admin_dashboard") if session.get("admin") else url_for("admin_login")), 302
    return render_template("404.html"), 404


@app.errorhandler(405)
def method_not_allowed(_error):
    if wants_json_response():
        return jsonify({"ok": False, "status": "method_not_allowed", "message": "Method not allowed."}), 405
    if request.path.startswith("/admin"):
        flash("That admin action needs to be submitted from the page again.", "warning")
        return redirect(url_for("admin_dashboard") if session.get("admin") else url_for("admin_login")), 302
    flash("This action is not allowed.", "danger")
    return redirect(request.referrer or url_for("index")), 302


@app.errorhandler(429)
def rate_limited(_error):
    if wants_json_response():
        return jsonify({"ok": False, "status": "rate_limited", "message": "Too many requests. Please try again later."}), 429
    flash("Too many requests. Please try again later.", "danger")
    return redirect(request.referrer or url_for("index")), 302


@app.errorhandler(500)
def server_error(_error):
    details = traceback.format_exc()
    logger.exception("Internal server error on %s", request.path)
    try:
        (BASE_DIR / "runtime_error.log").write_text(details, encoding="utf-8")
    except Exception:
        pass
    if os.environ.get("CPANEL_HEALTHCHECK_OK", "1") == "1":
        import html
        return (
            "<!doctype html><html><head><meta charset='utf-8'>"
            "<title>Nexora Runtime Error</title></head>"
            "<body style='font-family:Arial,Helvetica,sans-serif;padding:24px;background:#f8fafc;color:#111827;'>"
            "<h1 style='font-size:22px;'>Nexora runtime error</h1>"
            "<p>The application started, but this request failed. Check <strong>runtime_error.log</strong> in the app root.</p>"
            "<pre style='white-space:pre-wrap;background:#111827;color:#f9fafb;padding:16px;border-radius:8px;overflow:auto;'>"
            + html.escape(details)
            + "</pre></body></html>",
            200,
            {"Content-Type": "text/html"},
        )
    if wants_json_response():
        return jsonify({"ok": False, "status": "server_error", "message": "An internal error occurred. Please try again later."}), 500
    if request.path.startswith("/admin"):
        flash("Something went wrong. Please reload the admin page and try again.", "danger")
        return redirect(url_for("admin_dashboard") if session.get("admin") else url_for("admin_login")), 302
    return render_template("500.html"), 500


@app.errorhandler(413)
def too_large(_error):
    flash("File too large. Please upload an image under 8 MB.", "danger")
    return redirect(request.referrer or url_for("index")), 302
