import re
import time
import threading

from flask import jsonify, render_template, request

from app.admin import admin_blueprint
from app.admin.auth import admin_login_required
from app.email_service import send_email_to_user
from models.user_model import get_site_assets, get_user_by_email, get_user_matched_image_ids, log_email_deliveries
from models.email_queries import get_email_delivery_stats

EMAIL_PATTERN = re.compile(r"^[^@\s]+@[^@\s]+\.[^@\s]+$")

# Idempotency guard — prevents duplicate sends within 10 seconds
_send_lock = threading.Lock()
_recent_sends: dict = {}  # key: (user_id, new_email) → timestamp
_DEDUP_WINDOW = 10  # seconds


def _is_duplicate_send(user_id, new_email):
    """Return True if this (user_id, email) was sent within the dedup window."""
    key = (user_id, new_email)
    now = time.time()
    with _send_lock:
        # Clean up old entries
        expired = [k for k, t in _recent_sends.items() if now - t > _DEDUP_WINDOW]
        for k in expired:
            del _recent_sends[k]
        # Check and register
        if key in _recent_sends:
            return True
        _recent_sends[key] = now
        return False


def normalize_email(value):
    return (value or "").strip().lower()


@admin_blueprint.route("/emails", methods=["GET"])
@admin_login_required
def emails_page():
    return render_template("emails.html", site_assets=get_site_assets())


@admin_blueprint.route("/api/emails/stats", methods=["GET"])
@admin_login_required
def email_stats():
    """Return total / sent / remaining email delivery statistics."""
    try:
        stats = get_email_delivery_stats()
        # Convert datetime objects to ISO strings for JSON
        for row in stats.get("sent", []):
            if row.get("last_sent_at") and hasattr(row["last_sent_at"], "isoformat"):
                row["last_sent_at"] = row["last_sent_at"].isoformat()
        return jsonify(stats)
    except Exception as exc:
        return jsonify({"error": str(exc)}), 500


@admin_blueprint.route("/api/emails/suggestions", methods=["GET"])
@admin_login_required
def email_suggestions():
    """Fetch email suggestions based on search query (predictive search)."""
    query = (request.args.get("q") or "").strip().lower()

    if len(query) < 2:
        return jsonify({"suggestions": []}), 400

    from config.db_config import get_db_connection

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

        search_pattern = f"%{query}%"
        cursor.execute(
            """
            SELECT id, name, email
            FROM users
            WHERE LOWER(email) LIKE LOWER(%s)
               OR LOWER(name) LIKE LOWER(%s)
            ORDER BY email ASC LIMIT 10
            """,
            (search_pattern, search_pattern)
        )

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

        suggestions = [
            {"id": r["id"], "name": r["name"], "email": r["email"]}
            for r in results
        ]

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


@admin_blueprint.route("/api/emails/user-lookup", methods=["GET"])
@admin_login_required
def lookup_user_by_old_email():
    """Lookup user by existing email."""
    old_email = normalize_email(request.args.get("old_email"))
    if not old_email:
        return jsonify({"error": "Old email is required."}), 400

    user = get_user_by_email(old_email)
    if not user:
        return jsonify(
            {
                "error": f"No user found with email: {old_email}",
                "message": "Please check the email and try again.",
            }
        ), 404

    return jsonify(
        {
            "user": {
                "id": user["id"],
                "name": user["name"],
                "email": user["email"],
                "phone": user["phone"],
                "s3_image_url": user.get("s3_image_url"),
                "image_url": user.get("image_url"),
                "created_at": user.get("created_at").isoformat() if user.get("created_at") else None,
            }
        }
    )


@admin_blueprint.route("/api/emails/send", methods=["POST"])
@admin_login_required
def send_to_new_email():
    """Send gallery email to new email address (or same email for resend)."""
    payload = request.get_json(silent=True) or {}
    old_email = normalize_email(payload.get("old_email"))
    new_email = normalize_email(payload.get("new_email"))

    if not old_email or not new_email:
        return jsonify({"error": "Old email and new email are required."}), 400

    if not EMAIL_PATTERN.match(new_email):
        return jsonify({"error": "New email is invalid."}), 400

    user = get_user_by_email(old_email)
    if not user:
        return jsonify({"error": "No user found for the provided old email."}), 404

    # Prevent duplicate sends (Flask debug mode runs two processes)
    if _is_duplicate_send(user["id"], new_email):
        return jsonify({"error": "Duplicate request — email already sent just now."}), 429

    header_asset = get_site_assets().get("header")
    header_image_url = header_asset["image_path"] if header_asset else ""
    if header_image_url and not header_image_url.startswith("http"):
        header_image_url = request.url_root.rstrip("/") + "/static/" + header_image_url.lstrip("/")

    image_ids = get_user_matched_image_ids(user["id"])

    try:
        send_email_to_user(
            new_email,
            user["id"],
            user.get("s3_image_url") or user.get("image_url"),
            header_image_url,
        )
        if image_ids:
            log_email_deliveries(user["id"], image_ids)
    except Exception as exc:
        return jsonify({"error": f"Failed to send email: {exc}"}), 500

    # Determine message based on whether it's a resend or new email
    is_resend = old_email == new_email
    if is_resend:
        message = "Email resent successfully to the same address."
    else:
        message = "Email sent to the new address successfully."

    return jsonify(
        {
            "success": True,
            "message": message,
            "user_id": user["id"],
            "old_email": old_email,
            "new_email": new_email,
            "is_resend": is_resend,
            "logged_images": len(image_ids),
        }
    )