import math

from flask import flash, jsonify, redirect, render_template, request, url_for

from app.admin import admin_blueprint
from app.admin.auth import admin_login_required
from models.user_model import count_visitors, create_visitor, get_visitor_by_id, get_visitor_registration_by_identifier, \
    get_visitors, update_visitor


@admin_blueprint.route("/visitors", methods=["GET"])
@admin_login_required
def visitors_page():
    search = (request.args.get("search") or "").strip()
    limit = request.args.get("limit", type=int)
    page = request.args.get("page", 1, type=int)

    if limit not in [25, 50, 100]:
        limit = 25

    offset = (page - 1) * limit
    total = count_visitors(search=search if search else None)
    total_pages = math.ceil(total / limit) if total > 0 else 1

    # Fetch visitors with face registration info from users table
    from config.db_config import get_db_connection
    conn = get_db_connection()
    cursor = conn.cursor(dictionary=True)

    conditions = []
    params = []
    if search:
        pattern = f"%{search}%"
        conditions.append("(vr.name LIKE %s OR vr.mobile_number LIKE %s OR vr.email LIKE %s)")
        params.extend([pattern, pattern, pattern])

    where = f"WHERE {' AND '.join(conditions)}" if conditions else ""

    cursor.execute(f"""
        SELECT
            vr.id,
            vr.name,
            vr.mobile_number,
            vr.email,
            u.s3_image_url AS face_photo,
            u.created_at   AS face_registered_at
        FROM visitors_registration vr
        LEFT JOIN users u
            ON LOWER(TRIM(u.email)) = LOWER(TRIM(vr.email))
            OR u.phone = vr.mobile_number
        {where}
        ORDER BY vr.id DESC
        LIMIT %s OFFSET %s
    """, params + [limit, offset])

    visitors = cursor.fetchall()
    cursor.close()
    conn.close()

    return render_template(
        "visitors.html",
        visitors=visitors,
        search=search,
        limit=limit,
        page=page,
        total=total,
        total_pages=total_pages,
    )


@admin_blueprint.route("/visitors/edit/<int:visitor_id>", methods=["GET", "POST"])
@admin_login_required
def edit_visitor(visitor_id):
    visitor = get_visitor_by_id(visitor_id)
    if not visitor:
        flash("Visitor not found.", "error")
        return redirect(url_for("admin.visitors_page"))

    if request.method == "POST":
        name = (request.form.get("name") or "").strip()
        mobile_number = (request.form.get("mobile_number") or "").strip()
        email = (request.form.get("email") or "").strip()

        if not name:
            flash("Name is required.", "error")
            return redirect(url_for("admin.edit_visitor", visitor_id=visitor_id))

        try:
            update_visitor(visitor_id, name, mobile_number, email)
            flash("Visitor updated successfully.", "success")
        except Exception as exc:
            flash(f"Failed to update visitor: {exc}", "error")

        return redirect(url_for("admin.visitors_page"))

    return render_template("visitors_edit.html", visitor=visitor)


@admin_blueprint.route("/api/visitors/search", methods=["GET"])
@admin_login_required
def search_visitors_api():
    """API endpoint for real-time visitor search."""
    from config.db_config import get_db_connection

    search = (request.args.get("search") or "").strip()
    limit = request.args.get("limit", 25, type=int)

    # Limit results for real-time search to prevent too much data
    if limit > 50:
        limit = 50

    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)

        if search:
            sql = """
                  SELECT id, name, mobile_number, email
                  FROM visitors_registration
                  WHERE name LIKE %s
                     OR email LIKE %s
                     OR mobile_number LIKE %s
                  ORDER BY id DESC
                      LIMIT %s \
                  """
            like_query = f"%{search}%"
            cursor.execute(sql, (like_query, like_query, like_query, limit))
        else:
            sql = """
                  SELECT id, name, mobile_number, email
                  FROM visitors_registration
                  ORDER BY id DESC
                      LIMIT %s \
                  """
            cursor.execute(sql, (limit,))

        results = cursor.fetchall()
        cursor.close()
        conn.close()

        return jsonify(results)

    except Exception as e:
        return jsonify({"error": str(e)}), 500


@admin_blueprint.route("/api/visitors/add", methods=["POST"])
@admin_login_required
def add_visitor_api():
    """API endpoint to add a new visitor."""
    data = request.get_json()

    if not data:
        return jsonify({"success": False, "message": "No data provided"}), 400

    name = (data.get("name") or "").strip()
    mobile = (data.get("mobile") or "").strip()
    email = (data.get("email") or "").strip()

    if not name:
        return jsonify({"success": False, "message": "Name is required"}), 400

    if not email and not mobile:
        return jsonify({"success": False, "message": "Either email or mobile number is required"}), 400

    try:
        # Check for duplicate email if email is provided
        if email:
            existing_visitor = get_visitor_registration_by_identifier(email)
            if existing_visitor:
                return jsonify({"success": False, "message": "A visitor with this email already exists"}), 400

        # Check for duplicate mobile if mobile is provided
        if mobile:
            existing_visitor = get_visitor_registration_by_identifier(mobile)
            if existing_visitor:
                return jsonify({"success": False, "message": "A visitor with this mobile number already exists"}), 400

        # Create the visitor
        visitor_id = create_visitor(name, mobile, email)

        return jsonify({"success": True, "message": "Visitor added successfully", "visitor_id": visitor_id})
    except Exception as exc:
        return jsonify({"success": False, "message": f"Failed to add visitor: {str(exc)}"}), 500


@admin_blueprint.route("/api/visitors/export", methods=["GET"])
@admin_login_required
def api_export_visitors():
    """Export all visitors as JSON for CSV download."""
    try:
        from models.user_model import get_visitors, count_visitors
        total = count_visitors()
        visitors = get_visitors(limit=total or 10000, offset=0)
        return jsonify({"visitors": visitors, "total": len(visitors)})
    except Exception as exc:
        return jsonify({"error": str(exc), "visitors": []}), 500