from datetime import datetime, timezone, timedelta
from flask import render_template, request, jsonify, current_app, flash, redirect, url_for
from flask_mail import Message

from app.contact import contact_bp
from app.contact.forms import ContactForm
from app.models import ContactMessage
from app.extensions import db, mail


def get_client_ip():
    """Retrieve real client IP behind reverse proxies safely."""
    forwarded_for = request.headers.get('X-Forwarded-For')
    if forwarded_for:
        return forwarded_for.split(',')[0].strip()
    return request.remote_addr or "127.0.0.1"


def extract_first_error(err_data):
    """Safely retrieve the first error message string to clear Pylance type warnings."""
    if isinstance(err_data, dict):
        return str(next(iter(err_data.values()), "Invalid input"))
    if isinstance(err_data, (list, tuple)) and err_data:
        return str(err_data[0])
    return "Invalid input"


@contact_bp.route("/contact", methods=["GET", "POST"], endpoint="index")
def index():
    form = ContactForm()

    if request.method == "POST":
        client_ip = get_client_ip()
        one_hour_ago = datetime.now(timezone.utc) - timedelta(hours=1)

        # 1. Check IP Rate Limit (1 submission per hour)
        recent_submission = ContactMessage.query.filter(
            ContactMessage.ip_address == client_ip,
            ContactMessage.created_at >= one_hour_ago
        ).order_by(ContactMessage.created_at.desc()).first()

        if recent_submission:
            # Standardize datetime comparison for timezone safety
            created_at = recent_submission.created_at
            if created_at.tzinfo is None:
                created_at = created_at.replace(tzinfo=timezone.utc)

            time_passed = datetime.now(timezone.utc) - created_at
            seconds_remaining = int(3600 - time_passed.total_seconds())
            minutes_remaining = max(1, (seconds_remaining + 59) // 60)

            err_msg = f"You can only submit one enquiry per hour. Please wait {minutes_remaining} minute(s) before trying again."

            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify({'success': False, 'message': err_msg}), 429

            flash(err_msg, 'warning')
            return render_template("pages/contact.html", form=form), 429

        # 2. Process Validated Form
        if form.validate_on_submit():
            try:
                msg = ContactMessage(
                    name=form.name.data,
                    email=form.email.data,
                    phone=form.phone.data,
                    subject=form.subject.data,
                    message=form.message.data,
                    privacy_consent=form.privacy_consent.data,
                    ip_address=client_ip
                )
                db.session.add(msg)
                db.session.commit()

                send_contact_emails(msg)

                success_msg = "Thank you! Your message has been sent successfully."

                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return jsonify({'success': True, 'message': success_msg}), 200

                flash(success_msg, 'success')
                return redirect(url_for('contact.index'))

            except Exception as e:
                db.session.rollback()
                current_app.logger.error(f"Contact submission failed: {e}")
                err_msg = "An internal server error occurred. Please try again."

                if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                    return jsonify({'success': False, 'message': err_msg}), 500

                flash(err_msg, 'danger')

        # 3. Handle Form Validation Errors (AJAX)
        if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
            formatted_errors = {
                field: extract_first_error(err_data)
                for field, err_data in form.errors.items()
            }
            return jsonify({'success': False, 'errors': formatted_errors}), 400

    return render_template("pages/contact.html", form=form)


def send_contact_emails(contact_msg):
    """Sends notification to contact@codnesta.com and confirmation email to sender."""
    try:
        admin_email = (
            current_app.config.get('ADMIN_EMAIL') 
            or current_app.config.get('MAIL_DEFAULT_SENDER') 
            or "contact@codnesta.com"
        )

        admin_msg = Message(
            subject=f"[CodNesta Contact] {contact_msg.subject} - {contact_msg.name}",
            recipients=[str(admin_email)],
            body=f"Name: {contact_msg.name}\nEmail: {contact_msg.email}\nPhone: {contact_msg.phone or 'N/A'}\nSubject: {contact_msg.subject}\n\nMessage:\n{contact_msg.message}"
        )

        user_msg = Message(
            subject="We've received your message | CodNesta",
            recipients=[str(contact_msg.email)],
            body=f"Hello {contact_msg.name},\n\nThank you for reaching out to CodNesta regarding '{contact_msg.subject}'. We have received your message and will respond within 24–48 business hours.\n\nBest regards,\nCodNesta Team"
        )

        mail.send(admin_msg)
        mail.send(user_msg)
    except Exception as e:
        current_app.logger.error(f"Failed to send contact emails: {e}")