from flask import Flask, render_template, request, jsonify
from werkzeug.utils import secure_filename
from pathlib import Path
from argparse import ArgumentParser
import sqlite3

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = Path('./static/uploads')
app.config['UPLOAD_FOLDER'].mkdir(parents=True, exist_ok=True)

DB_PATH = 'letter_data.db'


def query_db(query, query_args=(), one=False):
    conn = sqlite3.connect(DB_PATH)
    conn.row_factory = sqlite3.Row
    cur = conn.cursor()
    cur.execute(query, query_args)
    rv = cur.fetchall()
    conn.commit()
    conn.close()
    return (rv[0] if rv else None) if one else rv


@app.route('/')
def index():
    senders = query_db('SELECT * FROM sender ORDER BY name')
    recipients = query_db('SELECT * FROM recipient ORDER BY name')
    states = query_db('SELECT * FROM state ORDER BY name')
    return render_template('index.html', senders=senders, recipients=recipients, states=states)


@app.route('/generate', methods=['POST'])
def generate():
    sender_id = request.form['sender']
    recipient_id = request.form['recipient']
    text = request.form['text']
    sender = query_db('SELECT * FROM sender WHERE id = ?', [sender_id], one=True)
    query = ('SELECT recipient.*, state.name as state_name FROM recipient LEFT JOIN state ON recipient.state_id = '
             'state.id WHERE recipient.id = ?')
    recipient = query_db(query, [recipient_id], one=True)
    return render_template('letter.html', sender=sender, recipient=recipient, text=text)


@app.route('/api/senders', methods=['POST'])
def api_add_sender():
    name = request.form['name']
    kuralie = request.form['kuralie']
    siegel = request.files['siegel']
    signatur = request.files['signatur']

    siegel_filename = secure_filename(siegel.filename)
    siegel.save(str(app.config['UPLOAD_FOLDER'] / siegel_filename))

    sig_filename = secure_filename(signatur.filename)
    signatur.save(str(app.config['UPLOAD_FOLDER'] / sig_filename))

    query_db('INSERT INTO sender (name, kuralie, siegel, signatur) VALUES (?, ?, ?, ?)',
             [name, kuralie, siegel_filename, sig_filename])
    return jsonify(success=True)


@app.route('/api/recipients', methods=['POST'])
def api_add_recipient():
    name = request.form['name']
    kuralie = request.form['kuralie']
    state_id = request.form['state_id'] or None
    query_db('INSERT INTO recipient (name, kuralie, state_id) VALUES (?, ?, ?)', [name, kuralie, state_id])
    return jsonify(success=True)


@app.route('/api/states', methods=['POST'])
def api_add_state():
    name = request.form['name']
    query_db('INSERT INTO state (name) VALUES (?)', [name])
    return jsonify(success=True)


@app.route('/api/senders', methods=['GET'])
def api_get_senders():
    senders = query_db('SELECT id, name FROM sender ORDER BY name')
    return jsonify([dict(row) for row in senders])


@app.route('/api/senders/<int:sender_id>', methods=['GET'])
def api_get_sender(sender_id):
    sender = query_db('SELECT * FROM sender WHERE id = ?', [sender_id], one=True)
    return jsonify(dict(sender))


@app.route('/api/recipients', methods=['GET'])
def api_get_recipients():
    state_id = request.args.get('state_id')
    if state_id and state_id != 'all':
        recipients = query_db('SELECT id, name FROM recipient WHERE state_id = ? ORDER BY name', [state_id])
    else:
        recipients = query_db('SELECT id, name FROM recipient ORDER BY name')
    return jsonify([dict(row) for row in recipients])


@app.route('/api/recipients/<int:recipient_id>', methods=['GET'])
def api_get_recipient(recipient_id):
    recipient = query_db('SELECT * FROM recipient WHERE id = ?', [recipient_id], one=True)
    return jsonify(dict(recipient))


@app.route('/api/states', methods=['GET'])
def api_get_states():
    states = query_db('SELECT id, name FROM state ORDER BY name')
    return jsonify([dict(row) for row in states])


@app.route('/api/states/<int:state_id>', methods=['GET'])
def api_get_state(state_id):
    state = query_db('SELECT * FROM state WHERE id = ?', [state_id], one=True)
    return jsonify(dict(state))


@app.route('/api/senders/<int:sender_id>', methods=['PUT'])
def api_edit_sender(sender_id):
    name = request.form['name']
    kuralie = request.form['kuralie']
    siegel = request.files['siegel']
    signatur = request.files['signatur']

    siegel_filename = secure_filename(siegel.filename) if siegel else None
    sig_filename = secure_filename(signatur.filename) if signatur else None

    if siegel:
        siegel.save(str(app.config['UPLOAD_FOLDER'] / siegel_filename))
    if signatur:
        signatur.save(str(app.config['UPLOAD_FOLDER'] / sig_filename))

    query_db('UPDATE sender SET name = ?, kuralie = ?, siegel = ?, signatur = ? WHERE id = ?',
             [name, kuralie, siegel_filename, sig_filename, sender_id])
    return jsonify(success=True)


@app.route('/api/recipients/<int:recipient_id>', methods=['PUT'])
def api_edit_recipient(recipient_id):
    name = request.form['name']
    kuralie = request.form['kuralie']
    state_id = request.form['state_id']

    query_db('UPDATE recipient SET name = ?, kuralie = ?, state_id = ? WHERE id = ?',
             [name, kuralie, state_id, recipient_id])
    return jsonify(success=True)


@app.route('/api/states/<int:state_id>', methods=['PUT'])
def api_edit_state(state_id):
    name = request.form['name']
    query_db('UPDATE state SET name = ? WHERE id = ?', [name, state_id])
    return jsonify(success=True)


if __name__ == '__main__':
    parser = ArgumentParser()
    parser.add_argument('-a', '--address', default='127.0.0.1', help="Host IP address to bind to (default: 127.0.0.1)")
    parser.add_argument('-p', '--port', default='5000', help="Port to bind to (default: 5000)")
    args = parser.parse_args()
    print("Falls diese Umgebung produktiv ist, nutze besser:\n"
          f"gunicorn --bind {args.address}:{args.port} --log-level info tharanor_letter:app")
    app.run(debug=True, host=args.address, port=args.port)
