from flask import Flask, render_template, request, redirect, url_for, session, g
import sqlite3
from db import get_db, init_db
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)
app.secret_key = "CHANGE_THIS_SECRET_KEY"

from markupsafe import Markup

@app.template_filter('nl2br')
def nl2br(value):
    return Markup(value.replace("\n", "<br>"))


@app.before_request
def before_request():
    g.db = get_db()


@app.teardown_request
def teardown_request(exception):
    db = getattr(g, 'db', None)
    if db is not None:
        db.close()


@app.route('/')
def index():
    if 'user_id' in session:
        return redirect(url_for('inbox'))
    return redirect(url_for('login'))


@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username'].strip().lower()
        password = request.form['password']

        if not username or not password:
            return render_template('register.html', error="Bitte alle Felder ausfüllen.")

        email_alias = f"{username}@mailplsme"
        password_hash = generate_password_hash(password)

        cur = g.db.execute("SELECT id FROM users WHERE username = ?", (username,))
        if cur.fetchone():
            return render_template('register.html', error="Benutzername existiert bereits.")

        g.db.execute(
            "INSERT INTO users (username, email_alias, password_hash) VALUES (?, ?, ?)",
            (username, email_alias, password_hash)
        )
        g.db.commit()
        return redirect(url_for('login'))

    return render_template('register.html')


@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username'].strip().lower()
        password = request.form['password']

        cur = g.db.execute(
            "SELECT id, password_hash FROM users WHERE username = ?",
            (username,)
        )
        row = cur.fetchone()
        if row and check_password_hash(row['password_hash'], password):
            session['user_id'] = row['id']
            session['username'] = username
            return redirect(url_for('inbox'))
        return render_template('login.html', error="Login fehlgeschlagen.")

    return render_template('login.html')


@app.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('login'))


@app.route('/inbox')
def inbox():
    if 'user_id' not in session:
        return redirect(url_for('login'))

    user_id = session['user_id']
    cur = g.db.execute(
        """SELECT m.id, u.email_alias AS sender, m.subject, m.timestamp, m.read
           FROM messages m
           JOIN users u ON m.sender_id = u.id
           WHERE m.receiver_id = ? AND m.folder = 'inbox'
           ORDER BY m.timestamp DESC""",
        (user_id,)
    )
    messages = cur.fetchall()
    return render_template('inbox.html', messages=messages)

@app.route('/delete/<int:msg_id>')
def delete_message(msg_id):
    if 'user_id' not in session:
        return redirect(url_for('login'))

    user_id = session['user_id']

    g.db.execute(
        """UPDATE messages
           SET folder = 'trash'
           WHERE id = ? AND receiver_id = ?""",
        (msg_id, user_id)
    )
    g.db.commit()

    return redirect(url_for('trash'))


@app.route('/send', methods=['GET', 'POST'])
def send():
    if 'user_id' not in session:
        return redirect(url_for('login'))

    if request.method == 'POST':
        to_alias = request.form['to'].strip().lower()
        subject = request.form['subject'].strip()
        body = request.form['body'].strip()

        cur = g.db.execute(
            "SELECT id FROM users WHERE email_alias = ?",
            (to_alias,)
        )
        receiver = cur.fetchone()
        if not receiver:
            return render_template('send.html', error="Empfänger nicht gefunden.")

        sender_id = session['user_id']
        receiver_id = receiver['id']

        g.db.execute(
            """INSERT INTO messages (sender_id, receiver_id, subject, body, folder, read)
               VALUES (?, ?, ?, ?, 'inbox', 0)""",
            (sender_id, receiver_id, subject, body)
        )
        g.db.execute(
            """INSERT INTO messages (sender_id, receiver_id, subject, body, folder, read)
               VALUES (?, ?, ?, ?, 'sent', 1)""",
            (sender_id, receiver_id, subject, body)
        )
        g.db.commit()
        return redirect(url_for('inbox'))

    return render_template('send.html')

@app.route('/sent')
def sent():
    if 'user_id' not in session:
        return redirect(url_for('login'))

    user_id = session['user_id']
    cur = g.db.execute(
        """SELECT m.id, u.email_alias AS receiver, m.subject, m.timestamp
           FROM messages m
           JOIN users u ON m.receiver_id = u.id
           WHERE m.sender_id = ? AND m.folder = 'sent'
           ORDER BY m.timestamp DESC""",
        (user_id,)
    )
    messages = cur.fetchall()
    return render_template('sent.html', messages=messages)

@app.route('/spam')
def spam():
    if 'user_id' not in session:
        return redirect(url_for('login'))

    user_id = session['user_id']
    cur = g.db.execute(
        """SELECT m.id, u.email_alias AS sender, m.subject, m.timestamp
           FROM messages m
           JOIN users u ON m.sender_id = u.id
           WHERE m.receiver_id = ? AND m.folder = 'spam'
           ORDER BY m.timestamp DESC""",
        (user_id,)
    )
    messages = cur.fetchall()
    return render_template('spam.html', messages=messages)

@app.route('/spammsg/<int:msg_id>')
def spam_message(msg_id):
    if 'user_id' not in session:
        return redirect(url_for('login'))

    user_id = session['user_id']

    g.db.execute(
        """UPDATE messages
           SET folder = 'spam'
           WHERE id = ? AND receiver_id = ?""",
        (msg_id, user_id)
    )
    g.db.commit()

    return redirect(url_for('spam'))


@app.route('/trash')
def trash():
    if 'user_id' not in session:
        return redirect(url_for('login'))

    user_id = session['user_id']
    cur = g.db.execute(
        """SELECT m.id, u.email_alias AS sender, m.subject, m.timestamp
           FROM messages m
           JOIN users u ON m.sender_id = u.id
           WHERE m.receiver_id = ? AND m.folder = 'trash'
           ORDER BY m.timestamp DESC""",
        (user_id,)
    )
    messages = cur.fetchall()
    return render_template('trash.html', messages=messages)

@app.route('/message/<int:msg_id>')
def message(msg_id):
    if 'user_id' not in session:
        return redirect(url_for('login'))

    user_id = session['user_id']

    cur = g.db.execute(
        """SELECT m.id, m.subject, m.body, m.timestamp, m.folder,
                  u1.email_alias AS sender, u2.email_alias AS receiver
           FROM messages m
           JOIN users u1 ON m.sender_id = u1.id
           JOIN users u2 ON m.receiver_id = u2.id
           WHERE m.id = ? AND (m.receiver_id = ? OR m.sender_id = ?)""",
        (msg_id, user_id, user_id)
    )
    msg = cur.fetchone()

    if not msg:
        return "Nachricht nicht gefunden.", 404

    # Als gelesen markieren
    g.db.execute("UPDATE messages SET read = 1 WHERE id = ?", (msg_id,))
    g.db.commit()

    return render_template('message.html', msg=msg)


@app.route('/reply/<int:msg_id>', methods=['GET', 'POST'])
def reply(msg_id):
    if 'user_id' not in session:
        return redirect(url_for('login'))

    cur = g.db.execute(
        """SELECT m.subject, m.body, u.email_alias AS sender
           FROM messages m
           JOIN users u ON m.sender_id = u.id
           WHERE m.id = ?""",
        (msg_id,)
    )
    msg = cur.fetchone()

    if request.method == 'POST':
        to_alias = request.form['to']
        subject = request.form['subject']
        body = request.form['body']

        # Empfänger suchen
        cur = g.db.execute("SELECT id FROM users WHERE email_alias = ?", (to_alias,))
        receiver = cur.fetchone()
        if not receiver:
            return render_template('send.html', error="Empfänger nicht gefunden.")

        sender_id = session['user_id']
        receiver_id = receiver['id']

        # Nachricht speichern
        g.db.execute(
            """INSERT INTO messages (sender_id, receiver_id, subject, body, folder, read)
               VALUES (?, ?, ?, ?, 'inbox', 0)""",
            (sender_id, receiver_id, subject, body)
        )
        g.db.execute(
            """INSERT INTO messages (sender_id, receiver_id, subject, body, folder, read)
               VALUES (?, ?, ?, ?, 'sent', 1)""",
            (sender_id, receiver_id, subject, body)
        )
        g.db.commit()

        return redirect(url_for('inbox'))

    return render_template('send.html',
                           pre_to=msg['sender'],
                           pre_subject="Re: " + msg['subject'],
                           pre_body="\n\n--- Originalnachricht ---\n" + msg['body'])


@app.route('/forward/<int:msg_id>', methods=['GET', 'POST'])
def forward(msg_id):
    if 'user_id' not in session:
        return redirect(url_for('login'))

    cur = g.db.execute(
        """SELECT subject, body
           FROM messages
           WHERE id = ?""",
        (msg_id,)
    )
    msg = cur.fetchone()

    if request.method == 'POST':
        to_alias = request.form['to']
        subject = request.form['subject']
        body = request.form['body']

        cur = g.db.execute("SELECT id FROM users WHERE email_alias = ?", (to_alias,))
        receiver = cur.fetchone()
        if not receiver:
            return render_template('send.html', error="Empfänger nicht gefunden.")

        sender_id = session['user_id']
        receiver_id = receiver['id']

        g.db.execute(
            """INSERT INTO messages (sender_id, receiver_id, subject, body, folder, read)
               VALUES (?, ?, ?, ?, 'inbox', 0)""",
            (sender_id, receiver_id, subject, body)
        )
        g.db.execute(
            """INSERT INTO messages (sender_id, receiver_id, subject, body, folder, read)
               VALUES (?, ?, ?, ?, 'sent', 1)""",
            (sender_id, receiver_id, subject, body)
        )
        g.db.commit()

        return redirect(url_for('inbox'))

    return render_template('send.html',
                           pre_subject="Fwd: " + msg['subject'],
                           pre_body="\n\n--- Weitergeleitet ---\n" + msg['body'])

@app.route('/search')
def search():
    if 'user_id' not in session:
        return redirect(url_for('login'))

    query = request.args.get('q', '').strip()
    user_id = session['user_id']

    cur = g.db.execute(
        """SELECT m.id, u.email_alias AS sender, m.subject, m.timestamp
           FROM messages m
           JOIN users u ON m.sender_id = u.id
           WHERE m.receiver_id = ?
             AND m.folder = 'inbox'
             AND (m.subject LIKE ? OR m.body LIKE ?)
           ORDER BY m.timestamp DESC""",
        (user_id, f"%{query}%", f"%{query}%")
    )
    messages = cur.fetchall()

    return render_template('inbox.html', messages=messages, search=query)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=51101, debug=True)

