# File: plugins/auth/routes.py

from datetime import datetime
from flask import (
    Blueprint, render_template, redirect,
    flash, url_for, request
)
from flask_login import (
    login_user, logout_user, login_required,
    current_user
)
from sqlalchemy.exc import SQLAlchemyError

from app import db
from .models import User, Invitation
from .forms import LoginForm, RegistrationForm, InviteForm

bp = Blueprint(
    'auth', __name__,
    url_prefix='/auth',
    template_folder='templates'
)

@bp.route('/login', methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('home'))

    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(
            email=form.email.data.lower()
        ).first()
        if user and user.check_password(form.password.data):
            now = datetime.utcnow()
            # Block banned or suspended accounts
            if user.is_banned or (user.suspended_until and user.suspended_until > now):
                flash('Your account is not active.', 'danger')
                return redirect(url_for('auth.login'))

            login_user(user, remember=form.remember_me.data)
            next_page = request.args.get('next')
            return redirect(next_page or url_for('home'))

        flash('Invalid email or password.', 'danger')

    return render_template('auth/login.html', form=form)

@bp.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('home'))

@bp.route('/register', methods=['GET', 'POST'])
def register():
    if current_user.is_authenticated:
        return redirect(url_for('home'))

    # Pull invite code from query param 'invite'
    invite_code = request.args.get('invite', '').strip()
    # Look up a valid, unused invitation
    invitation_obj = Invitation.query.filter_by(
        code=invite_code,
        is_active=True,
        is_used=False
    ).first()

    # Secure the GET: only allow viewing form if invite is valid
    if request.method == 'GET':
        if not invitation_obj:
            flash('Registration is by invitation only. Provide a valid invite link.', 'warning')
            return redirect(url_for('home'))

    form = RegistrationForm(invitation_code=invite_code)

    if form.validate_on_submit():
        # Re-validate invitation on POST
        invitation = Invitation.query.filter_by(
            code=form.invitation_code.data,
            is_active=True,
            is_used=False
        ).first()
        if not invitation:
            flash('Invalid or expired invitation code.', 'warning')
            return render_template('auth/register.html', form=form)

        # Create the new user
        user = User(
            email=form.email.data.lower(),
            username=form.username.data
        )
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.flush()

        # Mark the invitation as used
        invitation.mark_used(user, request.remote_addr)
        db.session.commit()

        flash('Account created! Please log in.', 'success')
        return redirect(url_for('auth.login'))

    return render_template('auth/register.html', form=form)

@bp.route('/invite', methods=['GET', 'POST'])
@login_required
def send_invite():
    now = datetime.utcnow()
    # Block banned or suspended users from generating invites
    if current_user.is_banned or (current_user.suspended_until and current_user.suspended_until > now):
        flash('Your account cannot send invitations.', 'danger')
        return redirect(url_for('home'))

    form = InviteForm()
    invites_left = current_user.invites_remaining

    if form.validate_on_submit():
        if invites_left < 1:
            flash('No invites remaining.', 'danger')
        else:
            # Create the invitation record
            inv = Invitation(
                recipient_email=form.email.data,
                created_by=current_user.id,
                sender_ip=request.remote_addr
            )
            db.session.add(inv)
            current_user.invites_remaining = invites_left - 1
            try:
                db.session.commit()
            except SQLAlchemyError:
                db.session.rollback()
                flash('An error occurred creating the invitation.', 'danger')
                return redirect(url_for('auth.send_invite'))

            # Build shareable link and messages
            link = url_for('auth.register', invite=inv.code, _external=True)
            blurb = (
                "I'd like to invite you to join Nature In Pots Community! "
                f"Use this link to register: {link}"
            )
            email_preview = (
                "Subject: Join me on Nature In Pots Community\n\n"
                "Hi there,\n\n"
                "I'd love for you to join me on Nature In Pots Community. "
                "Please click this link to sign up:\n\n"
                f"{link}\n\n"
                "See you inside!\n"
            )

            return render_template(
                'auth/invite.html',
                form=form,
                invites=current_user.invites_remaining,
                inv_link=link,
                inv_blurb=blurb,
                email_preview=email_preview
            )

    # GET: simply render the form if allowed
    return render_template(
        'auth/invite.html',
        form=form,
        invites=invites_left
    )
