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 sqlalchemy import select

from app.subscribe import subscribe_bp
from app.subscribe.forms import SubscribeForm
from app.extensions import db, mail
from app.models import WebSubscribers 


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"

@subscribe_bp.route("/subscribe", methods=["GET"], endpoint="index")
def index():
    return redirect(request.referrer or url_for('main.index'))


@subscribe_bp.route("/subscribe/submit", methods=["POST"], endpoint="submit_enquiry")
def submit_enquiry():
    form = SubscribeForm()
    
    # 1. Validate Form Input First
    if form.validate_on_submit():
        # Clean conversion to string clears Pylance Optional[str] warning
        email = str(form.email.data).lower().strip()
        client_ip = get_client_ip()

        # Modern SQLAlchemy 2.0 select query clears Pylance query warning
        stmt = select(WebSubscribers).where(WebSubscribers.email == email)
        existing_subscriber = db.session.scalars(stmt).first()

        if existing_subscriber:
            err_msg = "You are already subscribed! If you entered a wrong email, please enter the correct one."
            if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
                return jsonify({'success': False, 'message': err_msg}), 400
            
            flash(err_msg, 'warning')
            return redirect(url_for('subscribe.index'))

        # 2. Save New Subscription
        try:
            subscriber = WebSubscribers(
                email=email,
                ip_address=client_ip
            )
            db.session.add(subscriber)
            db.session.commit()

            send_subscription_emails(subscriber)

            success_msg = "Thank you! Your subscription was successful."

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

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

        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"Subscription 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')
            return redirect(url_for('subscribe.index'))

    # 3. Handle Form Validation Errors
    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

    first_error = extract_first_error(next(iter(form.errors.values()), "Please check the form fields."))
    flash(first_error, 'danger')
    return redirect(url_for('subscribe.index'))


def send_subscription_emails(subscriber):
    """Sends HTML notification to admin and HTML confirmation email to subscriber."""
    try:
        admin_email = (
            current_app.config.get('ADMIN_EMAIL') 
            or current_app.config.get('MAIL_DEFAULT_SENDER') 
            or "contact@codnesta.com"
        )

        formatted_date = datetime.now(timezone.utc).strftime("%B %d, %Y at %I:%M %p UTC")
        current_year = datetime.now().year

        # Admin HTML email
        admin_html = render_template(
            "emails/subscribe/admin_email.html",
            email=subscriber.email,
            ip_address=subscriber.ip_address,
            created_at=formatted_date
        )

        admin_msg = Message(
            subject=f"[New Subscriber] {subscriber.email}",
            recipients=[str(admin_email)],
            html=admin_html
        )

        # Subscriber HTML email
        user_html = render_template(
            "emails/subscribe/subscriber_email.html",
            email=subscriber.email,
            current_year=current_year
        )

        user_msg = Message(
            subject="Welcome to CodNesta!",
            recipients=[str(subscriber.email)],
            html=user_html
        )

        # Send both emails
        mail.send(admin_msg)
        mail.send(user_msg)

    except Exception as e:
        current_app.logger.error(f"Failed to send subscription confirmation emails: {e}")