from flask import Blueprint, render_template, redirect, url_for, flash
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import login_user, login_required, logout_user
from forms.login import LoginForm
from forms.signup import SignupForm
from extensions import db

auth = Blueprint('auth', __name__)

class Person:
    """
    Simple Person class compatible with Flask-Login.
    """
    def __init__(self, person_id, name, email, password_hash):
        self.id = person_id
        self.name = name
        self.email = email
        self.password_hash = password_hash

    def get_id(self):
        """Required by Flask-Login to get a unique user identifier."""
        return str(self.id)

    @property
    def is_authenticated(self):
        return True

    @property
    def is_active(self):
        return True

    @property
    def is_anonymous(self):
        return False


# -------------------------
# Database helper functions
# -------------------------

def get_person_by_id(person_id):
    """
    Fetch a person record by person_id and return a Person object.
    """
    sql = """
        SELECT person_id, name, email, password_hash
        FROM person
        WHERE person_id = %s
        LIMIT 1
    """
    row = db.execute(sql, [person_id], one=True)
    if row:
        return Person(row['person_id'], row['name'], row['email'], row['password_hash'])
    return None


def get_person_by_email(email):
    """
    Fetch a person record by email and return a Person object.
    """
    sql = """
        SELECT person_id, name, email, password_hash
        FROM person
        WHERE email = %s
        LIMIT 1
    """
    row = db.execute(sql, [email], one=True)
    if row:
        return Person(row['person_id'], row['name'], row['email'], row['password_hash'])
    return None


def create_person(name, email, password_hash):
    """
    Insert a new person into the database; return the new person's ID.
    """
    sql = """
        INSERT INTO person (name, email, password_hash)
        VALUES (%s, %s, %s)
        RETURNING person_id AS person_id
    """
    row = db.execute(sql, [name, email, password_hash], commit=True, one=True)
    return row['person_id']


# ---------------------
# Blueprint endpoints
# ---------------------

@auth.route('/signup', methods=['GET', 'POST'])
def signup():
    form = SignupForm()
    if form.validate_on_submit():
        hashed_password = generate_password_hash(form.password.data)
        create_person(
            name=form.name.data,
            email=form.email.data,
            password_hash=hashed_password
        )
        flash("Account created successfully. Please log in.", "success")
        return redirect(url_for('auth.login'))
    return render_template('auth/signup.html', form=form)


@auth.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        person = get_person_by_email(form.email.data)
        if person and check_password_hash(person.password_hash, form.password.data):
            login_user(person)
            flash("Logged in successfully.", "success")
            return redirect(url_for('calendar.get_calendar', person_id=person.id))
        else:
            flash("Invalid email or password.", "danger")
    return render_template('auth/login.html', form=form)


@auth.route('/logout')
@login_required
def logout():
    logout_user()
    flash('You have been logged out.', 'success')
    return redirect(url_for('auth.login'))
