import os
from datetime import datetime
from flask import Flask, render_template, request, redirect, url_for, flash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired
from weasyprint import HTML
from werkzeug.security import generate_password_hash, check_password_hash
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app.secret_key = os.urandom(24)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://symbolica_factuur:factuurSymbolica@172.17.0.1:3306/factuur'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
migrate = Migrate(app, db)

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(150), unique=True, nullable=False)
    password_hash = db.Column(db.String(255), nullable=False)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

class Customer(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    company_name = db.Column(db.String(150))
    contact_person = db.Column(db.String(150))
    address = db.Column(db.String(150))
    number = db.Column(db.String(50))
    postal_code = db.Column(db.String(20))
    city = db.Column(db.String(100))
    vat = db.Column(db.String(50))

class Invoice(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    customer_id = db.Column(db.Integer, db.ForeignKey('customer.id'))
    number = db.Column(db.Integer)
    amount = db.Column(db.Float)
    categorie = db.Column(db.String(100))
    description = db.Column(db.Text)
    betaling = db.Column(db.String(50))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)

    customer = db.relationship('Customer', backref='invoices')

class LoginForm(FlaskForm):
    username = StringField('Gebruikersnaam', validators=[DataRequired()])
    password = PasswordField('Wachtwoord', validators=[DataRequired()])
    submit = SubmitField('Log in')

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

@app.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        if user and user.check_password(form.password.data):
            login_user(user)
            flash("Je bent succesvol ingelogd!", "success")
            return redirect(request.args.get('next') or url_for('index'))
        else:
            flash("Ongeldige gebruikersnaam of wachtwoord", "danger")
    return render_template('login.html', form=form)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash("Je bent uitgelogd.", "info")
    return redirect(url_for('login'))

@app.route('/')
@login_required
def index():
    customers = Customer.query.all()
    return render_template('index.html', customers=customers)

@app.route('/klant/nieuw', methods=['GET', 'POST'])
@login_required
def create_customer():
    if request.method == 'POST':
        customer = Customer(
            company_name=request.form['company_name'],
            contact_person=request.form['contact_person'],
            address=request.form['address'],
            number=request.form['number'],
            postal_code=request.form['postal_code'],
            city=request.form['city'],
            vat=request.form['vat']
        )
        db.session.add(customer)
        db.session.commit()
        return redirect(url_for('index'))
    return render_template('create_customer.html')

@app.route('/klant/<int:customer_id>/bewerken', methods=['GET', 'POST'])
@login_required
def edit_customer(customer_id):
    customer = Customer.query.get_or_404(customer_id)
    if request.method == 'POST':
        customer.company_name = request.form['company_name']
        customer.contact_person = request.form['contact_person']
        customer.address = request.form['address']
        customer.number = request.form['number']
        customer.postal_code = request.form['postal_code']
        customer.city = request.form['city']
        customer.vat = request.form['vat']
        db.session.commit()
        return redirect(url_for('index'))
    return render_template('edit_customer.html', customer=customer)

@app.route('/create_invoice', methods=['GET', 'POST'])
@login_required
def create_invoice():
    customers = Customer.query.all()
    if request.method == 'POST':
        invoice = Invoice(
            customer_id=request.form['customer_id'],
            number=request.form['number'],
            amount=request.form['amount'],
            description=request.form['description'],
            categorie=request.form['categorie'],
            betaling=request.form['betaling']
        )
        db.session.add(invoice)
        db.session.commit()
        generate_pdf(invoice.id)
        return redirect(url_for('invoice_list'))
    return render_template('create_invoice.html', customers=customers)

@app.route('/invoices')
@login_required
def invoice_list():
    invoices = Invoice.query.all()
    invoice_data = []
    for invoice in invoices:
        customer = invoice.customer
        formatted_id = str(invoice.id).zfill(3)
        pdf_filename = f"S2425_{formatted_id}-VlaggendansgroepSymbolica_{invoice.categorie}_{customer.company_name}.pdf"
        invoice_data.append({
            'id': invoice.id,
            'customer_name': customer.company_name,
            'amount': invoice.amount,
            'categorie': invoice.categorie,
            'description': invoice.description,
            'number': invoice.number,
            'betaling': invoice.betaling,
            'created_at': invoice.created_at.strftime('%d/%m/%Y %H:%M'),
            'pdf_link': url_for('static', filename=f'pdfs/{pdf_filename}')
        })
    return render_template('invoices.html', invoices=invoice_data)

def generate_pdf(invoice_id):
    invoice = Invoice.query.get_or_404(invoice_id)
    customer = invoice.customer

    logo_url = url_for('static', filename='images/logo.png', _external=True)
    pdf_filename = f"S2425_{str(invoice_id).zfill(3)}-VlaggendansgroepSymbolica_{invoice.categorie}_{customer.company_name}.pdf"
    pdf_path = os.path.join('static/pdfs', pdf_filename)

    rendered_html = render_template(
        'invoice_tmpl.html',
        invoice=invoice,
        customer=customer,
        datetime=datetime.now().strftime('%d/%m/%Y'),
        logo_path=logo_url,
        formatted_invoice_id=str(invoice.id).zfill(3)
    )

    HTML(string=rendered_html).write_pdf(pdf_path)
    return pdf_path

os.makedirs('static/pdfs', exist_ok=True)

with app.app_context():
    db.create_all()

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000, debug=True)
