"""
HFS Abrechnung – Minimal Flask-App (Flask + SQLAlchemy + MariaDB)
---------------------------------------------------------------
Funktionen:
- CRUD für grunddaten, kurs, rechnungen
- Simple Verknüpfung: rechnungen.dgid -> grunddaten.elleid
- PDF-Rechnung pro Kunde/Einrichtung (grunddaten) und Datumsbereich
- Einfache HTML-Views via render_template_string (keine externen Templates nötig)

Voraussetzungen:
- Python 3.10+
- pip install flask SQLAlchemy pymysql reportlab python-dotenv
- Laufende MariaDB mit Schema/Tables wie vom Nutzer beschrieben
- .env mit DB_URL (siehe unten)

Start:
    export FLASK_APP=hfs_app.py
    flask run --debug

Beispiel .env:
    DB_URL=mysql+pymysql://www_usr:yOPbAI8Pd@localhost:3306/hfs?charset=utf8mb4

Hinweis Sicherheit: Bitte die echten Zugangsdaten nicht commiten. Für Produktion weitere Härtung (Auth, CSRF, Rollen, etc.).
"""
from __future__ import annotations

import io
import os
from datetime import date, datetime, time
from decimal import Decimal
from typing import Optional

from flask import Flask, request, redirect, url_for, send_file
from flask import render_template_string, flash
from sqlalchemy import create_engine, Column, Integer, String, DECIMAL, Date, Time, ForeignKey, select, func
from sqlalchemy.orm import declarative_base, sessionmaker, relationship, scoped_session
from reportlab.lib.pagesizes import A4
from reportlab.pdfgen import canvas
from reportlab.lib.units import mm
from reportlab.lib.utils import simpleSplit
from dotenv import load_dotenv

load_dotenv()

DB_URL = os.getenv("DB_URL", "mysql+pymysql://www_usr:yOPbAI8Pd@localhost:3306/hfs?charset=utf8mb4")

engine = create_engine(DB_URL, pool_pre_ping=True, future=True)
SessionLocal = scoped_session(sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True))
Base = declarative_base()

# --- Models entsprechend vorhandener Tabellen ---
class Grunddaten(Base):
    __tablename__ = "grunddaten"
    elleid = Column(Integer, primary_key=True, autoincrement=True)
    firma = Column(String(25))
    bereich = Column(String(25))
    abteilung = Column(String(25))
    strasse = Column(String(45))
    plz = Column(String(5))
    ort = Column(String(45))
    verguetung1 = Column(DECIMAL(6, 2))
    verguetung2 = Column(DECIMAL(6, 2))

    rechnungen = relationship("Rechnung", back_populates="kunde", cascade="all, delete-orphan")

    def __repr__(self):
        return f"<Grunddaten {self.elleid} {self.firma or ''}>"

class Kurs(Base):
    __tablename__ = "kurs"
    elleid = Column(Integer, primary_key=True, autoincrement=True)
    kurs = Column(String(25))
    status = Column(String(25))
    bemerkung = Column(String(255))

    def __repr__(self):
        return f"<Kurs {self.elleid} {self.kurs or ''}>"

class Rechnung(Base):
    __tablename__ = "rechnungen"
    elleid = Column(Integer, primary_key=True, autoincrement=True)
    datum = Column(Date)
    von = Column(Time)
    bis = Column(Time)
    stunden = Column(Time)  # gespeichert als HH:MM:SS
    bemerkung = Column(String(45))
    km = Column(Integer)
    kurs = Column(String(25))  # Hinweis: String-Ref auf kurs.kurs
    dgid = Column(Integer, ForeignKey("grunddaten.elleid", ondelete="CASCADE"))

    kunde = relationship("Grunddaten", back_populates="rechnungen")

    def stunden_decimal(self) -> Decimal:
        """Wandelt stunden (Time) in Dezimalstunden um (z. B. 01:30:00 -> 1.5)."""
        if not self.stunden:
            return Decimal("0")
        h, m, s = self.stunden.hour, self.stunden.minute, self.stunden.second
        return Decimal(h) + Decimal(m) / Decimal(60) + Decimal(s) / Decimal(3600)

# --- Flask App ---
app = Flask(__name__)
app.secret_key = os.getenv("FLASK_SECRET", "dev-secret")

# --- Helpers ---
BASE_HTML = """
<!doctype html>
<html lang="de">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>HFS Abrechnung</title>
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
  <style>
    body { font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif; margin: 24px; }
    header { display:flex; gap:12px; align-items:center; margin-bottom: 16px; }
    nav a { margin-right: 12px; text-decoration:none; color:#0b57d0; }
    table { border-collapse: collapse; width: 100%; }
    th, td { border: 1px solid #ddd; padding: 8px; }
    th { background: #f7f7f7; text-align: left; }
    input, select { padding:6px; width: 100%; box-sizing: border-box; }
    .btn { display:inline-block; padding:8px 12px; background:#0b57d0; color:#fff; text-decoration:none; border-radius:6px; }
    .btn.secondary { background:#666; }
    .btn.danger { background:#c62828; }
    .grid { display:grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap:12px; }
    .row { display:flex; gap:8px; align-items:center; }
    .flash { background:#fff3cd; border:1px solid #ffecb5; color:#664d03; padding:8px 12px; border-radius:6px; margin-bottom:12px; }
  </style>
</head>
<body>
  <header>
    <h2 style="margin:0">HFS Abrechnung</h2>
    <nav>
      <a href="{{ url_for('index') }}">Dashboard</a>
      <a href="{{ url_for('grunddaten_list') }}">Grunddaten</a>
      <a href="{{ url_for('kurs_list') }}">Kurse</a>
      <a href="{{ url_for('rechnungen_list') }}">Rechnungen</a>
      <a href="{{ url_for('rechnung_tools') }}">Rechnung erstellen</a>
    </nav>
  </header>
  {% with messages = get_flashed_messages() %}
    {% if messages %}
      <div class="flash">{{ messages[0] }}</div>
    {% endif %}
  {% endwith %}
  {{ body|safe }}
</body>
</html>
"""

def page(content: str) -> str:
    return render_template_string(BASE_HTML, body=content)

# --- Dashboard ---
@app.get("/")
def index():
    db = SessionLocal()
    try:
        kunden = db.scalar(select(func.count(Grunddaten.elleid))) or 0
        kurse = db.scalar(select(func.count(Kurs.elleid))) or 0
        rechs = db.scalar(select(func.count(Rechnung.elleid))) or 0
    finally:
        db.close()
    body = f"""
    <div class='grid'>
      <div><h3>Überblick</h3>
        <p><b>Kunden/Einrichtungen:</b> {kunden}</p>
        <p><b>Kurse:</b> {kurse}</p>
        <p><b>Rechnungszeilen:</b> {rechs}</p>
      </div>
    </div>
    """
    return page(body)

# --- CRUD: Grunddaten ---
@app.get("/grunddaten")
def grunddaten_list():
    db = SessionLocal()
    try:
        rows = db.execute(select(Grunddaten).order_by(Grunddaten.elleid.desc())).scalars().all()
    finally:
        db.close()
    body = """
    <div class='row'>
      <h3 style='margin-right:auto'>Grunddaten</h3>
      <a class='btn' href='{{ url_for("grunddaten_new") }}'>Neu</a>
    </div>
    <table>
      <tr><th>ID</th><th>Firma</th><th>Bereich</th><th>Abteilung</th><th>Adresse</th><th>Vergütung1</th><th>Vergütung2</th><th>Aktion</th></tr>
      {% for g in rows %}
        <tr>
          <td>{{ g.elleid }}</td>
          <td>{{ g.firma or '' }}</td>
          <td>{{ g.bereich or '' }}</td>
          <td>{{ g.abteilung or '' }}</td>
          <td>{{ (g.strasse or '') + ', ' + (g.plz or '') + ' ' + (g.ort or '') }}</td>
          <td>{{ g.verguetung1 or '' }}</td>
          <td>{{ g.verguetung2 or '' }}</td>
          <td>
            <a class='btn secondary' href='{{ url_for("grunddaten_edit", id=g.elleid) }}'>Bearbeiten</a>
            <a class='btn danger' href='{{ url_for("grunddaten_delete", id=g.elleid) }}' onclick="return confirm('Wirklich löschen?')">Löschen</a>
          </td>
        </tr>
      {% endfor %}
    </table>
    """
    return page(render_template_string(body, rows=rows))

@app.get("/grunddaten/new")
def grunddaten_new():
    body = """
    <h3>Grunddaten anlegen</h3>
    <form method='post' action='{{ url_for("grunddaten_create") }}'>
      <div class='grid'>
        <div><label>Firma<input name='firma'></label></div>
        <div><label>Bereich<input name='bereich'></label></div>
        <div><label>Abteilung<input name='abteilung'></label></div>
        <div><label>Straße<input name='strasse'></label></div>
        <div><label>PLZ<input name='plz'></label></div>
        <div><label>Ort<input name='ort'></label></div>
        <div><label>Vergütung 1 (€)<input name='verguetung1' type='number' step='0.01'></label></div>
        <div><label>Vergütung 2 (€)<input name='verguetung2' type='number' step='0.01'></label></div>
      </div>
      <p><button class='btn'>Speichern</button></p>
    </form>
    """
    return page(body)

@app.post("/grunddaten")
def grunddaten_create():
    db = SessionLocal()
    try:
        g = Grunddaten(
            firma=request.form.get("firma"),
            bereich=request.form.get("bereich"),
            abteilung=request.form.get("abteilung"),
            strasse=request.form.get("strasse"),
            plz=request.form.get("plz"),
            ort=request.form.get("ort"),
            verguetung1=request.form.get("verguetung1") or None,
            verguetung2=request.form.get("verguetung2") or None,
        )
        db.add(g)
        db.commit()
        flash("Gespeichert.")
    finally:
        db.close()
    return redirect(url_for("grunddaten_list"))

@app.get("/grunddaten/<int:id>")
def grunddaten_edit(id: int):
    db = SessionLocal()
    try:
        g = db.get(Grunddaten, id)
    finally:
        db.close()
    if not g:
        return page("<p>Nicht gefunden.</p>")
    body = render_template_string("""
    <h3>Grunddaten bearbeiten #{{ g.elleid }}</h3>
    <form method='post' action='{{ url_for("grunddaten_update", id=g.elleid) }}'>
      <div class='grid'>
        <div><label>Firma<input name='firma' value='{{ g.firma or "" }}'></label></div>
        <div><label>Bereich<input name='bereich' value='{{ g.bereich or "" }}'></label></div>
        <div><label>Abteilung<input name='abteilung' value='{{ g.abteilung or "" }}'></label></div>
        <div><label>Straße<input name='strasse' value='{{ g.strasse or "" }}'></label></div>
        <div><label>PLZ<input name='plz' value='{{ g.plz or "" }}'></label></div>
        <div><label>Ort<input name='ort' value='{{ g.ort or "" }}'></label></div>
        <div><label>Vergütung 1 (€)<input name='verguetung1' type='number' step='0.01' value='{{ g.verguetung1 or "" }}'></label></div>
        <div><label>Vergütung 2 (€)<input name='verguetung2' type='number' step='0.01' value='{{ g.verguetung2 or "" }}'></label></div>
      </div>
      <p><button class='btn'>Aktualisieren</button></p>
    </form>
    """, g=g)
    return page(body)

@app.post("/grunddaten/<int:id>")
def grunddaten_update(id: int):
    db = SessionLocal()
    try:
        g = db.get(Grunddaten, id)
        if not g:
            return page("<p>Nicht gefunden.</p>")
        for field in ["firma","bereich","abteilung","strasse","plz","ort"]:
            setattr(g, field, request.form.get(field))
        g.verguetung1 = request.form.get("verguetung1") or None
        g.verguetung2 = request.form.get("verguetung2") or None
        db.commit()
        flash("Aktualisiert.")
    finally:
        db.close()
    return redirect(url_for("grunddaten_list"))

@app.get("/grunddaten/<int:id>/delete")
def grunddaten_delete(id: int):
    db = SessionLocal()
    try:
        g = db.get(Grunddaten, id)
        if g:
            db.delete(g)
            db.commit()
            flash("Gelöscht.")
    finally:
        db.close()
    return redirect(url_for("grunddaten_list"))

# --- CRUD: Kurs ---
@app.get("/kurs")
def kurs_list():
    db = SessionLocal()
    try:
        rows = db.execute(select(Kurs).order_by(Kurs.elleid.desc())).scalars().all()
    finally:
        db.close()
    body = render_template_string("""
    <div class='row'>
      <h3 style='margin-right:auto'>Kurse</h3>
      <a class='btn' href='{{ url_for("kurs_new") }}'>Neu</a>
    </div>
    <table>
      <tr><th>ID</th><th>Kurs</th><th>Status</th><th>Bemerkung</th><th>Aktion</th></tr>
      {% for k in rows %}
        <tr>
          <td>{{ k.elleid }}</td>
          <td>{{ k.kurs or '' }}</td>
          <td>{{ k.status or '' }}</td>
          <td>{{ k.bemerkung or '' }}</td>
          <td>
            <a class='btn secondary' href='{{ url_for("kurs_edit", id=k.elleid) }}'>Bearbeiten</a>
            <a class='btn danger' href='{{ url_for("kurs_delete", id=k.elleid) }}' onclick="return confirm('Wirklich löschen?')">Löschen</a>
          </td>
        </tr>
      {% endfor %}
    </table>
    """, rows=rows)
    return page(body)

@app.get("/kurs/new")
def kurs_new():
    body = """
    <h3>Kurs anlegen</h3>
    <form method='post' action='{{ url_for("kurs_create") }}'>
      <div class='grid'>
        <div><label>Kurs<input name='kurs'></label></div>
        <div><label>Status<input name='status'></label></div>
        <div><label>Bemerkung<input name='bemerkung'></label></div>
      </div>
      <p><button class='btn'>Speichern</button></p>
    </form>
    """
    return page(body)

@app.post("/kurs")
def kurs_create():
    db = SessionLocal()
    try:
        k = Kurs(kurs=request.form.get("kurs"), status=request.form.get("status"), bemerkung=request.form.get("bemerkung"))
        db.add(k)
        db.commit()
        flash("Gespeichert.")
    finally:
        db.close()
    return redirect(url_for("kurs_list"))

@app.get("/kurs/<int:id>")
def kurs_edit(id: int):
    db = SessionLocal()
    try:
        k = db.get(Kurs, id)
    finally:
        db.close()
    if not k:
        return page("<p>Nicht gefunden.</p>")
    body = render_template_string("""
    <h3>Kurs bearbeiten #{{ k.elleid }}</h3>
    <form method='post' action='{{ url_for("kurs_update", id=k.elleid) }}'>
      <div class='grid'>
        <div><label>Kurs<input name='kurs' value='{{ k.kurs or "" }}'></label></div>
        <div><label>Status<input name='status' value='{{ k.status or "" }}'></label></div>
        <div><label>Bemerkung<input name='bemerkung' value='{{ k.bemerkung or "" }}'></label></div>
      </div>
      <p><button class='btn'>Aktualisieren</button></p>
    </form>
    """, k=k)
    return page(body)

@app.post("/kurs/<int:id>")
def kurs_update(id: int):
    db = SessionLocal()
    try:
        k = db.get(Kurs, id)
        if not k:
            return page("<p>Nicht gefunden.</p>")
        k.kurs = request.form.get("kurs")
        k.status = request.form.get("status")
        k.bemerkung = request.form.get("bemerkung")
        db.commit()
        flash("Aktualisiert.")
    finally:
        db.close()
    return redirect(url_for("kurs_list"))

@app.get("/kurs/<int:id>/delete")
def kurs_delete(id: int):
    db = SessionLocal()
    try:
        k = db.get(Kurs, id)
        if k:
            db.delete(k)
            db.commit()
            flash("Gelöscht.")
    finally:
        db.close()
    return redirect(url_for("kurs_list"))

# --- CRUD: Rechnungen (Zeiterfassung/Positionen) ---
@app.get("/rechnungen")
def rechnungen_list():
    db = SessionLocal()
    try:
        rows = (
            db.execute(
                select(Rechnung).order_by(Rechnung.datum.desc(), Rechnung.elleid.desc())
            ).scalars().all()
        )
        kunden = {g.elleid: g for g in db.execute(select(Grunddaten)).scalars().all()}
    finally:
        db.close()
    body = render_template_string("""
    <div class='row'>
      <h3 style='margin-right:auto'>Rechnungs-Positionen</h3>
      <a class='btn' href='{{ url_for("rechnung_new") }}'>Neu</a>
    </div>
    <table>
      <tr><th>ID</th><th>Datum</th><th>Von</th><th>Bis</th><th>Stunden</th><th>KM</th><th>Kurs</th><th>Kunde</th><th>Bemerkung</th><th>Aktion</th></tr>
      {% for r in rows %}
        <tr>
          <td>{{ r.elleid }}</td>
          <td>{{ r.datum }}</td>
          <td>{{ r.von }}</td>
          <td>{{ r.bis }}</td>
          <td>{{ r.stunden }}</td>
          <td>{{ r.km or 0 }}</td>
          <td>{{ r.kurs or '' }}</td>
          <td>{{ kunden.get(r.dgid).firma if kunden.get(r.dgid) else r.dgid }}</td>
          <td>{{ r.bemerkung or '' }}</td>
          <td>
            <a class='btn secondary' href='{{ url_for("rechnung_edit", id=r.elleid) }}'>Bearbeiten</a>
            <a class='btn danger' href='{{ url_for("rechnung_delete", id=r.elleid) }}' onclick="return confirm('Wirklich löschen?')">Löschen</a>
          </td>
        </tr>
      {% endfor %}
    </table>
    """, rows=rows, kunden=kunden)
    return page(body)

@app.get("/rechnungen/new")
def rechnung_new():
    db = SessionLocal()
    try:
        kunden = db.execute(select(Grunddaten).order_by(Grunddaten.firma)).scalars().all()
        kurse = db.execute(select(Kurs).order_by(Kurs.kurs)).scalars().all()
    finally:
        db.close()
    body = render_template_string("""
    <h3>Position anlegen</h3>
    <form method='post' action='{{ url_for("rechnung_create") }}'>
      <div class='grid'>
        <div><label>Datum<input type='date' name='datum' value='{{ nowdate }}'></label></div>
        <div><label>Von<input type='time' name='von'></label></div>
        <div><label>Bis<input type='time' name='bis'></label></div>
        <div><label>Stunden (HH:MM)<input type='time' name='stunden' step='60'></label></div>
        <div><label>KM<input type='number' name='km'></label></div>
        <div><label>Kurs<select name='kurs'>
          <option value=''>—</option>
          {% for k in kurse %}<option value='{{ k.kurs }}'>{{ k.kurs }}</option>{% endfor %}
        </select></label></div>
        <div><label>Kunde<select name='dgid'>
          {% for g in kunden %}<option value='{{ g.elleid }}'>{{ g.firma }} ({{ g.ort }})</option>{% endfor %}
        </select></label></div>
        <div style='grid-column: 1 / -1'><label>Bemerkung<input name='bemerkung'></label></div>
      </div>
      <p><button class='btn'>Speichern</button></p>
    </form>
    """, kunden=kunden, kurse=kurse, nowdate=date.today().isoformat())
    return page(body)

@app.post("/rechnungen")
def rechnung_create():
    def parse_time(val: Optional[str]) -> Optional[time]:
        if not val:
            return None
        try:
            hh, mm = map(int, val.split(":"))
            return time(hour=hh, minute=mm)
        except Exception:
            return None

    db = SessionLocal()
    try:
        r = Rechnung(
            datum=datetime.strptime(request.form.get("datum"), "%Y-%m-%d").date() if request.form.get("datum") else None,
            von=parse_time(request.form.get("von")),
            bis=parse_time(request.form.get("bis")),
            stunden=parse_time(request.form.get("stunden")),
            bemerkung=request.form.get("bemerkung"),
            km=int(request.form.get("km")) if request.form.get("km") else None,
            kurs=request.form.get("kurs"),
            dgid=int(request.form.get("dgid")) if request.form.get("dgid") else None,
        )
        db.add(r)
        db.commit()
        flash("Gespeichert.")
    finally:
        db.close()
    return redirect(url_for("rechnungen_list"))

@app.get("/rechnungen/<int:id>")
def rechnung_edit(id: int):
    db = SessionLocal()
    try:
        r = db.get(Rechnung, id)
        kunden = db.execute(select(Grunddaten).order_by(Grunddaten.firma)).scalars().all()
        kurse = db.execute(select(Kurs).order_by(Kurs.kurs)).scalars().all()
    finally:
        db.close()
    if not r:
        return page("<p>Nicht gefunden.</p>")
    body = render_template_string("""
    <h3>Position bearbeiten #{{ r.elleid }}</h3>
    <form method='post' action='{{ url_for("rechnung_update", id=r.elleid) }}'>
      <div class='grid'>
        <div><label>Datum<input type='date' name='datum' value='{{ r.datum }}'></label></div>
        <div><label>Von<input type='time' name='von' value='{{ r.von }}'></label></div>
        <div><label>Bis<input type='time' name='bis' value='{{ r.bis }}'></label></div>
        <div><label>Stunden<input type='time' step='60' name='stunden' value='{{ r.stunden }}'></label></div>
        <div><label>KM<input type='number' name='km' value='{{ r.km or 0 }}'></label></div>
        <div><label>Kurs<select name='kurs'>
          <option value=''>—</option>
          {% for k in kurse %}<option value='{{ k.kurs }}' {% if r.kurs==k.kurs %}selected{% endif %}>{{ k.kurs }}</option>{% endfor %}
        </select></label></div>
        <div><label>Kunde<select name='dgid'>
          {% for g in kunden %}<option value='{{ g.elleid }}' {% if r.dgid==g.elleid %}selected{% endif %}>{{ g.firma }} ({{ g.ort }})</option>{% endfor %}
        </select></label></div>
        <div style='grid-column: 1 / -1'><label>Bemerkung<input name='bemerkung' value='{{ r.bemerkung or "" }}'></label></div>
      </div>
      <p><button class='btn'>Aktualisieren</button></p>
    </form>
    """, r=r, kunden=kunden, kurse=kurse)
    return page(body)

@app.post("/rechnungen/<int:id>")
def rechnung_update(id: int):
    def parse_time(val: Optional[str]) -> Optional[time]:
        if not val:
            return None
        try:
            hh, mm = map(int, val.split(":"))
            return time(hour=hh, minute=mm)
        except Exception:
            return None
    db = SessionLocal()
    try:
        r = db.get(Rechnung, id)
        if not r:
            return page("<p>Nicht gefunden.</p>")
        r.datum = datetime.strptime(request.form.get("datum"), "%Y-%m-%d").date() if request.form.get("datum") else None
        r.von = parse_time(request.form.get("von"))
        r.bis = parse_time(request.form.get("bis"))
        r.stunden = parse_time(request.form.get("stunden"))
        r.km = int(request.form.get("km")) if request.form.get("km") else None
        r.kurs = request.form.get("kurs")
        r.dgid = int(request.form.get("dgid")) if request.form.get("dgid") else None
        r.bemerkung = request.form.get("bemerkung")
        db.commit()
        flash("Aktualisiert.")
    finally:
        db.close()
    return redirect(url_for("rechnungen_list"))

@app.get("/rechnungen/<int:id>/delete")
def rechnung_delete(id: int):
    db = SessionLocal()
    try:
        r = db.get(Rechnung, id)
        if r:
            db.delete(r)
            db.commit()
            flash("Gelöscht.")
    finally:
        db.close()
    return redirect(url_for("rechnungen_list"))

# --- Rechnungs-Tools ---
@app.get("/rechnung-tools")
def rechnung_tools():
    db = SessionLocal()
    try:
        kunden = db.execute(select(Grunddaten).order_by(Grunddaten.firma)).scalars().all()
    finally:
        db.close()
    body = render_template_string("""
    <h3>Rechnung erstellen</h3>
    <form method='get' action='{{ url_for("rechnung_preview") }}'>
      <div class='grid'>
        <div><label>Kunde<select name='dgid'>
          {% for g in kunden %}<option value='{{ g.elleid }}'>{{ g.firma }} ({{ g.ort }})</option>{% endfor %}
        </select></label></div>
        <div><label>Von<input type='date' name='from' value='{{ first_day }}'></label></div>
        <div><label>Bis<input type='date' name='to' value='{{ last_day }}'></label></div>
      </div>
      <p>
        <button class='btn'>Vorschau</button>
      </p>
    </form>
    """, kunden=kunden, first_day=date.today().replace(day=1).isoformat(), last_day=date.today().isoformat())
    return page(body)

@app.get("/rechnung-preview")
def rechnung_preview():
    dgid = int(request.args.get("dgid"))
    dfrom = datetime.strptime(request.args.get("from"), "%Y-%m-%d").date()
    dto = datetime.strptime(request.args.get("to"), "%Y-%m-%d").date()
    db = SessionLocal()
    try:
        kunde = db.get(Grunddaten, dgid)
        items = (
            db.execute(
                select(Rechnung).where(Rechnung.dgid == dgid, Rechnung.datum >= dfrom, Rechnung.datum <= dto).order_by(Rechnung.datum)
            ).scalars().all()
        )
        sum_stunden = sum([i.stunden_decimal() for i in items], Decimal("0"))
        # einfacher Tarif: verguetung1 pro Stunde, km-Pauschale optional (0.35 €/km Beispiel)
        satz = Decimal(kunde.verguetung1 or 0)
        betrag_stunden = (sum_stunden * satz).quantize(Decimal("0.01"))
        sum_km = sum([i.km or 0 for i in items])
        km_satz = Decimal("0.35")
        betrag_km = (Decimal(sum_km) * km_satz).quantize(Decimal("0.01"))
        netto = (betrag_stunden + betrag_km).quantize(Decimal("0.01"))
        mwst_satz = Decimal("0.19")
        mwst = (netto * mwst_satz).quantize(Decimal("0.01"))
        brutto = (netto + mwst).quantize(Decimal("0.01"))
    finally:
        db.close()

    body = render_template_string("""
    <h3>Vorschau Rechnung</h3>
    <p><b>Kunde:</b> {{ kunde.firma }} – {{ kunde.strasse }}, {{ kunde.plz }} {{ kunde.ort }}</p>
    <p><b>Zeitraum:</b> {{ dfrom }} bis {{ dto }}</p>
    <table>
      <tr><th>Datum</th><th>Kurs</th><th>Stunden (dezimal)</th><th>KM</th><th>Bemerkung</th></tr>
      {% for i in items %}
        <tr>
          <td>{{ i.datum }}</td>
          <td>{{ i.kurs or '' }}</td>
          <td>{{ '%.2f' % i.stunden_decimal() }}</td>
          <td>{{ i.km or 0 }}</td>
          <td>{{ i.bemerkung or '' }}</td>
        </tr>
      {% endfor %}
      <tr><th colspan=2 style='text-align:right'>Summe</th><th>{{ '%.2f' % sum_stunden }}</th><th>{{ sum_km }}</th><th></th></tr>
    </table>
    <p>
      Stundensatz: {{ satz }} € | Stundenbetrag: {{ betrag_stunden }} €<br>
      KM-Satz: 0.35 € | KM-Betrag: {{ betrag_km }} €
    </p>
    <h4>Netto: {{ netto }} € | MwSt 19%: {{ mwst }} € | Brutto: {{ brutto }} €</h4>
    <p><a class='btn' href='{{ url_for("rechnung_pdf", dgid=dgid, dfrom=dfrom, dto=dto) }}'>Als PDF erzeugen</a></p>
    """, kunde=kunde, dfrom=dfrom, dto=dto, items=items,
         sum_stunden=sum_stunden, sum_km=sum([i.km or 0 for i in items]),
         satz=satz, betrag_stunden=betrag_stunden, km_satz=Decimal("0.35"), betrag_km=betrag_km,
         netto=netto, mwst=mwst, brutto=brutto, dgid=dgid)
    return page(body)

@app.get("/rechnung-pdf")
def rechnung_pdf():
    dgid = int(request.args.get("dgid"))
    dfrom = datetime.strptime(request.args.get("dfrom"), "%Y-%m-%d").date()
    dto = datetime.strptime(request.args.get("dto"), "%Y-%m-%d").date()

    db = SessionLocal()
    try:
        kunde = db.get(Grunddaten, dgid)
        items = (
            db.execute(
                select(Rechnung).where(Rechnung.dgid == dgid, Rechnung.datum >= dfrom, Rechnung.datum <= dto).order_by(Rechnung.datum)
            ).scalars().all()
        )
        sum_stunden = sum([i.stunden_decimal() for i in items], Decimal("0"))
        satz = Decimal(kunde.verguetung1 or 0)
        betrag_stunden = (sum_stunden * satz).quantize(Decimal("0.01"))
        sum_km = sum([i.km or 0 for i in items])
        km_satz = Decimal("0.35")
        betrag_km = (Decimal(sum_km) * km_satz).quantize(Decimal("0.01"))
        netto = (betrag_stunden + betrag_km).quantize(Decimal("0.01"))
        mwst_satz = Decimal("0.19")
        mwst = (netto * mwst_satz).quantize(Decimal("0.01"))
        brutto = (netto + mwst).quantize(Decimal("0.01"))
    finally:
        db.close()

    # --- PDF generieren ---
    buf = io.BytesIO()
    c = canvas.Canvas(buf, pagesize=A4)
    w, h = A4
    margin = 20 * mm

    def draw_text(x, y, text, max_width=None):
        lines = simpleSplit(text, 'Helvetica', 10, max_width or (w - 2*margin))
        for idx, ln in enumerate(lines):
            c.drawString(x, y - 12*idx, ln)
        return y - 12*len(lines)

    c.setTitle("Rechnung")
    y = h - margin
    c.setFont("Helvetica-Bold", 14)
    c.drawString(margin, y, "Rechnung")
    c.setFont("Helvetica", 10)
    y -= 18
    y = draw_text(margin, y, f"Kunde: {kunde.firma}\n{kunde.strasse}\n{kunde.plz} {kunde.ort}")
    y -= 12
    c.drawString(margin, y, f"Zeitraum: {dfrom.isoformat()} bis {dto.isoformat()}")
    y -= 18

    # Tabelle Kopf
    c.setFont("Helvetica-Bold", 10)
    c.drawString(margin, y, "Datum")
    c.drawString(margin + 80, y, "Kurs")
    c.drawString(margin + 250, y, "Stunden")
    c.drawString(margin + 320, y, "KM")
    c.drawString(margin + 370, y, "Bemerkung")
    y -= 12
    c.setFont("Helvetica", 10)
    for i in items:
        if y < 60:
            c.showPage()
            y = h - margin
        c.drawString(margin, y, i.datum.isoformat())
        c.drawString(margin + 80, y, (i.kurs or "")[:30])
        c.drawRightString(margin + 310, y, f"{i.stunden_decimal():.2f}")
        c.drawRightString(margin + 350, y, str(i.km or 0))
        c.drawString(margin + 370, y, (i.bemerkung or "")[:40])
        y -= 12

    y -= 12
    c.setFont("Helvetica-Bold", 10)
    c.drawRightString(margin + 310, y, f"Summe Stunden: {sum_stunden:.2f}")
    c.drawRightString(margin + 350, y - 12, f"Summe KM: {sum_km}")

    y -= 30
    c.drawString(margin, y, f"Stundensatz: {satz} €  -> Betrag: {betrag_stunden} €")
    y -= 12
    c.drawString(margin, y, f"KM-Satz: 0.35 €       -> Betrag: {betrag_km} €")
    y -= 12
    c.drawString(margin, y, f"Netto: {netto} €  | MwSt 19%: {mwst} €  | Brutto: {brutto} €")

    c.showPage()
    c.save()
    buf.seek(0)

    filename = f"rechnung_{dgid}_{dfrom.isoformat()}_{dto.isoformat()}.pdf"
    return send_file(buf, as_attachment=True, download_name=filename, mimetype="application/pdf")


if __name__ == "__main__":
    app.run(debug=True)
