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.predev import predev_bp
from app.predev.forms import PreDevForm
from app.models import PreDevSubmission
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"


@predev_bp.route("/predev", methods=["GET", "POST"], endpoint="index")
def index():
    form = PreDevForm()
    
    if request.method == "GET":
        return render_template("pages/predev.html", form=form)

    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 = PreDevSubmission.query.filter(
        PreDevSubmission.ip_address == client_ip,
        PreDevSubmission.created_at >= one_hour_ago
    ).order_by(PreDevSubmission.created_at.desc()).first()

    if recent_submission:
        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 Pre-Dev expression of interest 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 redirect(url_for('predev.index'))

    # 2. Process Validated Form
    if form.validate_on_submit():
        try:
            submission = PreDevSubmission(
                name=form.name.data,
                email=form.email.data,
                whatsapp=form.whatsapp.data,
                location=form.location.data,
                current_status=form.current_status.data,
                primary_skill=form.primary_skill.data,
                experience_level=form.experience_level.data,
                preferred_start_period=form.preferred_start_period.data,
                development_goal=form.development_goal.data,
                program_understanding=bool(form.program_understanding.data),
                ip_address=client_ip
            )
            db.session.add(submission)
            db.session.commit()

            send_predev_submission_emails(submission)

            success_msg = "Thank you! Your expression of interest for Pre-Dev has been received successfully. CodNesta will review and reach out soon."

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

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

        except Exception as e:
            db.session.rollback()
            current_app.logger.error(f"Pre-Dev 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('predev.index'))

    # 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

    # Fallback for standard form posts with errors
    first_error = extract_first_error(next(iter(form.errors.values()), "Please check the form fields."))
    flash(first_error, 'danger')
    return redirect(url_for('predev.index'))


def send_predev_submission_emails(submission):
    """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"[Pre-Dev Interest] {submission.primary_skill} - {submission.name}",
            recipients=[str(admin_email)],
            body=(
                f"New Pre-Dev Expression of Interest:\n\n"
                f"Name: {submission.name}\n"
                f"Email: {submission.email}\n"
                f"WhatsApp: {submission.whatsapp}\n"
                f"Location: {submission.location}\n"
                f"Current Status: {submission.current_status}\n"
                f"Primary Skill: {submission.primary_skill}\n"
                f"Experience Level: {submission.experience_level}\n"
                f"Preferred Start: {submission.preferred_start_period}\n\n"
                f"Development Goal:\n{submission.development_goal}"
            )
        )

        user_msg = Message(
            subject="We've received your Expression of Interest | CodNesta Pre-Dev",
            recipients=[str(submission.email)],
            body=(
                f"Hello {submission.name},\n\n"
                f"Thank you for submitting your expression of interest for the CodNesta Pre-Dev program. "
                f"Our team has received your profile and goals. We will review your application and communicate "
                f"the next steps regarding verification and membership details.\n\n"
                f"Best regards,\nCodNesta Team"
            )
        )

        # Attach HTML templates dynamically with fallback protection
        try:
            formatted_date = datetime.now(timezone.utc).strftime("%B %d, %Y at %I:%M %p UTC")
            current_year = datetime.now().year

            admin_msg.html = render_template(
                "emails/predev/admin_predev.html",
                application=submission,
                created_at=formatted_date
            )

            user_msg.html = render_template(
                "emails/predev/client_predev.html",
                application=submission,
                current_year=current_year
            )
        except Exception as render_err:
            current_app.logger.warning(
                f"Could not render Pre-Dev HTML email templates, falling back to plain text: {render_err}"
            )

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