from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask_login import login_user, logout_user, login_required, current_user
from app.extensions import db, limiter, mail
from app.models.user import User
from app.i18n import flash_i18n
from datetime import datetime

auth_bp = Blueprint("auth", __name__, url_prefix="/auth")


@auth_bp.route("/register", methods=["GET", "POST"])
@limiter.limit("10 per hour")
def register():
    if current_user.is_authenticated:
        return redirect(url_for("dashboard.index"))
    if request.method == "POST":
        name = request.form.get("name", "").strip()
        email = request.form.get("email", "").strip().lower()
        password = request.form.get("password", "")
        if not name or not email or not password:
            flash_i18n("flash.all_fields_required", "error")
            return render_template("auth/register.html")
        if len(password) < 8:
            flash_i18n("flash.password_too_short", "error")
            return render_template("auth/register.html")
        if User.query.filter_by(email=email).first():
            flash_i18n("flash.email_exists", "error")
            return render_template("auth/register.html")
        account_type = request.form.get("account_type", "entrepreneur").strip()
        company_name = request.form.get("company_name", "").strip() or None
        interests = request.form.getlist("interests")
        user = User(name=name, email=email, account_type=account_type,
                    company_name=company_name,
                    interests_json=interests if interests else None)
        user.set_password(password)
        db.session.add(user)
        db.session.commit()
        # Auto-create FactoryPartner record for factory accounts
        if account_type == "factory" and company_name:
            from app.models.services import FactoryPartner
            fp = FactoryPartner(
                name=company_name, name_ar=company_name,
                user_id=user.id, sectors_json=interests,
                is_verified=False, is_active=True,
            )
            db.session.add(fp)
            user.factory_partner_id = fp.id
            db.session.commit()
        _send_verification_email(user)
        login_user(user)
        flash_i18n("flash.register_success", "success")
        return redirect(url_for("dashboard.index"))
    return render_template("auth/register.html")


@auth_bp.route("/login", methods=["GET", "POST"])
@limiter.limit("20 per hour")
def login():
    if current_user.is_authenticated:
        return redirect(url_for("dashboard.index"))
    if request.method == "POST":
        email = request.form.get("email", "").strip().lower()
        password = request.form.get("password", "")
        user = User.query.filter_by(email=email).first()
        if user and user.check_password(password):
            if user.two_factor_enabled:
                from flask import session
                session["2fa_user_id"] = user.id
                session["2fa_next"] = request.args.get("next", "")
                return redirect(url_for("auth.verify_2fa"))
            login_user(user)
            next_page = request.args.get("next")
            return redirect(next_page or url_for("dashboard.index"))
        flash_i18n("flash.invalid_credentials", "error")
    return render_template("auth/login.html")


@auth_bp.route("/logout")
@login_required
def logout():
    logout_user()
    return redirect(url_for("auth.login"))


@auth_bp.route("/verify-email/<token>")
def verify_email(token):
    user = User.verify_token(token, "email-verify", expires_sec=86400)
    if not user:
        flash("Invalid or expired verification link.", "error")
        return redirect(url_for("auth.login"))
    if not user.email_verified:
        user.email_verified = True
        user.email_verified_at = datetime.utcnow()
        db.session.commit()
    flash("Email verified successfully!", "success")
    if current_user.is_authenticated:
        return redirect(url_for("dashboard.index"))
    return redirect(url_for("auth.login"))


@auth_bp.route("/resend-verification")
@login_required
@limiter.limit("3 per hour")
def resend_verification():
    if current_user.email_verified:
        flash("Email already verified.", "info")
        return redirect(url_for("dashboard.index"))
    _send_verification_email(current_user)
    flash("Verification email sent!", "success")
    return redirect(url_for("dashboard.index"))


@auth_bp.route("/forgot-password", methods=["GET", "POST"])
@limiter.limit("5 per hour")
def forgot_password():
    if request.method == "POST":
        email = request.form.get("email", "").strip().lower()
        user = User.query.filter_by(email=email).first()
        if user:
            _send_reset_email(user)
        flash("If an account exists with that email, a reset link has been sent.", "success")
        return redirect(url_for("auth.login"))
    return render_template("auth/forgot_password.html")


@auth_bp.route("/reset-password/<token>", methods=["GET", "POST"])
@limiter.limit("10 per hour")
def reset_password(token):
    user = User.verify_token(token, "password-reset", expires_sec=3600)
    if not user:
        flash("Invalid or expired reset link.", "error")
        return redirect(url_for("auth.forgot_password"))
    if request.method == "POST":
        password = request.form.get("password", "")
        confirm = request.form.get("confirm_password", "")
        if len(password) < 8:
            flash("Password must be at least 8 characters.", "error")
            return render_template("auth/reset_password.html", token=token)
        if password != confirm:
            flash("Passwords do not match.", "error")
            return render_template("auth/reset_password.html", token=token)
        user.set_password(password)
        db.session.commit()
        flash("Password reset successfully! Please log in.", "success")
        return redirect(url_for("auth.login"))
    return render_template("auth/reset_password.html", token=token)


@auth_bp.route("/profile", methods=["GET", "POST"])
@login_required
def profile():
    if request.method == "POST":
        action = request.form.get("action")
        if action == "update_profile":
            name = request.form.get("name", "").strip()
            language = request.form.get("language", "ar")
            currency = request.form.get("currency", "SAR")
            if name:
                current_user.name = name
            current_user.language_pref = language
            current_user.currency = currency
            db.session.commit()
            flash_i18n("flash.profile_updated", "success")
        elif action == "change_password":
            current_pw = request.form.get("current_password", "")
            new_pw = request.form.get("new_password", "")
            confirm = request.form.get("confirm_password", "")
            if not current_user.check_password(current_pw):
                flash_i18n("flash.wrong_password", "error")
            elif len(new_pw) < 8:
                flash_i18n("flash.password_too_short", "error")
            elif new_pw != confirm:
                flash_i18n("flash.password_mismatch", "error")
            else:
                current_user.set_password(new_pw)
                db.session.commit()
                flash_i18n("flash.password_changed", "success")
        return redirect(url_for("auth.profile"))

    from app.models.platform_keys import UserPlatformKey, PLATFORM_REGISTRY
    user_keys = {pk.platform: pk for pk in UserPlatformKey.query.filter_by(user_id=current_user.id).all()}
    is_admin = getattr(current_user, 'is_admin', False)
    visible_platforms = {
        k: v for k, v in PLATFORM_REGISTRY.items()
        if not v.get("admin_only") or is_admin
    }
    return render_template("auth/profile.html",
        platform_registry=visible_platforms,
        user_keys=user_keys,
    )


@auth_bp.route("/profile/platform-key", methods=["POST"])
@login_required
def save_platform_key():
    """Save or update a platform API key."""
    from app.models.platform_keys import UserPlatformKey, PLATFORM_REGISTRY
    platform = request.form.get("platform", "").strip()
    if platform not in PLATFORM_REGISTRY:
        flash("منصة غير معروفة.", "error")
        return redirect(url_for("auth.profile"))

    pk = UserPlatformKey.query.filter_by(user_id=current_user.id, platform=platform).first()
    if not pk:
        pk = UserPlatformKey(user_id=current_user.id, platform=platform)
        db.session.add(pk)

    info = PLATFORM_REGISTRY[platform]
    for field in info["fields"]:
        val = request.form.get(field, "").strip()
        if val:
            setattr(pk, field, val)

    pk.is_active = True
    db.session.commit()
    flash(f"تم حفظ مفتاح {info['name_ar']} بنجاح.", "success")
    return redirect(url_for("auth.profile") + "#platforms")


@auth_bp.route("/profile/platform-key/delete", methods=["POST"])
@login_required
def delete_platform_key():
    """Delete a platform API key."""
    from app.models.platform_keys import UserPlatformKey, PLATFORM_REGISTRY
    platform = request.form.get("platform", "").strip()
    pk = UserPlatformKey.query.filter_by(user_id=current_user.id, platform=platform).first()
    if pk:
        db.session.delete(pk)
        db.session.commit()
        info = PLATFORM_REGISTRY.get(platform, {})
        flash(f"تم حذف مفتاح {info.get('name_ar', platform)}.", "success")
    return redirect(url_for("auth.profile") + "#platforms")


def _send_verification_email(user):
    from flask import current_app
    from flask_mail import Message
    try:
        token = user.generate_token("email-verify")
        verify_url = url_for("auth.verify_email", token=token, _external=True)
        msg = Message(
            "Verify Your Email - Jadwa AI",
            recipients=[user.email],
        )
        msg.html = f"""
        <div style="font-family:Arial,sans-serif;max-width:500px;margin:0 auto;padding:20px">
            <h2 style="color:#D2AF20">Jadwa AI</h2>
            <p>Hello {user.name},</p>
            <p>Please verify your email by clicking the button below:</p>
            <a href="{verify_url}" style="display:inline-block;background:#D2AF20;color:#000;padding:12px 24px;border-radius:8px;text-decoration:none;font-weight:bold">Verify Email</a>
            <p style="color:#999;font-size:12px;margin-top:20px">This link expires in 24 hours.</p>
        </div>
        """
        mail.send(msg)
    except Exception as e:
        current_app.logger.warning(f"Could not send verification email: {e}")


def _send_reset_email(user):
    from flask import current_app
    from flask_mail import Message
    try:
        token = user.generate_token("password-reset")
        reset_url = url_for("auth.reset_password", token=token, _external=True)
        msg = Message(
            "Reset Your Password - Jadwa AI",
            recipients=[user.email],
        )
        msg.html = f"""
        <div style="font-family:Arial,sans-serif;max-width:500px;margin:0 auto;padding:20px">
            <h2 style="color:#D2AF20">Jadwa AI</h2>
            <p>Hello {user.name},</p>
            <p>You requested a password reset. Click the button below:</p>
            <a href="{reset_url}" style="display:inline-block;background:#D2AF20;color:#000;padding:12px 24px;border-radius:8px;text-decoration:none;font-weight:bold">Reset Password</a>
            <p style="color:#999;font-size:12px;margin-top:20px">This link expires in 1 hour. If you didn't request this, ignore this email.</p>
        </div>
        """
        mail.send(msg)
    except Exception as e:
        current_app.logger.warning(f"Could not send reset email: {e}")


@auth_bp.route("/setup-2fa", methods=["GET", "POST"])
@login_required
def setup_2fa():
    import pyotp
    import qrcode
    import io
    import base64

    if request.method == "POST":
        code = request.form.get("code", "").strip()
        secret = current_user.totp_secret
        if not secret:
            flash("Setup error. Try again.", "error")
            return redirect(url_for("auth.setup_2fa"))
        totp = pyotp.TOTP(secret)
        if totp.verify(code, valid_window=1):
            current_user.two_factor_enabled = True
            db.session.commit()
            flash("2FA enabled successfully!", "success")
            return redirect(url_for("auth.profile"))
        flash("Invalid code. Try again.", "error")
        return redirect(url_for("auth.setup_2fa"))

    if not current_user.totp_secret:
        current_user.totp_secret = pyotp.random_base32()
        db.session.commit()

    totp = pyotp.TOTP(current_user.totp_secret)
    uri = totp.provisioning_uri(name=current_user.email, issuer_name="Jadwa AI")

    img = qrcode.make(uri)
    buf = io.BytesIO()
    img.save(buf, format="PNG")
    buf.seek(0)
    qr_b64 = base64.b64encode(buf.read()).decode()

    return render_template("auth/setup_2fa.html", qr_b64=qr_b64, secret=current_user.totp_secret)


@auth_bp.route("/disable-2fa", methods=["POST"])
@login_required
def disable_2fa():
    code = request.form.get("code", "").strip()
    if current_user.totp_secret:
        import pyotp
        totp = pyotp.TOTP(current_user.totp_secret)
        if totp.verify(code, valid_window=1):
            current_user.two_factor_enabled = False
            current_user.totp_secret = None
            db.session.commit()
            flash("2FA disabled.", "success")
        else:
            flash("Invalid code.", "error")
    return redirect(url_for("auth.profile"))


@auth_bp.route("/verify-2fa", methods=["GET", "POST"])
@limiter.limit("10 per hour")
def verify_2fa():
    from flask import session
    user_id = session.get("2fa_user_id")
    if not user_id:
        return redirect(url_for("auth.login"))

    if request.method == "POST":
        code = request.form.get("code", "").strip()
        user = User.query.get(user_id)
        if user and user.totp_secret:
            import pyotp
            totp = pyotp.TOTP(user.totp_secret)
            if totp.verify(code, valid_window=1):
                session.pop("2fa_user_id", None)
                next_page = session.pop("2fa_next", "")
                login_user(user)
                return redirect(next_page or url_for("dashboard.index"))
        flash("Invalid 2FA code.", "error")

    return render_template("auth/verify_2fa.html")
