"""
invoice_schema.py — Pydantic-schema en validatie voor factuurgegevens.
"""

from __future__ import annotations

import re
from datetime import date

from pydantic import BaseModel, Field


class InvoiceLine(BaseModel):
    description: str | None = None
    quantity: float | None = None
    unit_price: float | None = None
    vat_rate: float | None = None
    total: float | None = None


class Invoice(BaseModel):
    supplier: str | None = Field(None, description="Naam van de leverancier.")
    invoice_number: str | None = Field(None, description="Factuurnummer.")
    invoice_date: date | None = Field(None, description="Factuurdatum (YYYY-MM-DD).")
    due_date: date | None = Field(None, description="Vervaldatum (YYYY-MM-DD).")
    kvk: str | None = Field(None, description="KvK-nummer.")
    vat_number: str | None = Field(None, description="Btw-nummer.")
    iban: str | None = Field(None, description="IBAN.")
    currency: str | None = Field(None, description="Valuta, bijv. EUR.")
    subtotal: float | None = Field(None, description="Subtotaal exclusief btw.")
    vat: float | None = Field(None, description="Btw-bedrag.")
    total: float | None = Field(None, description="Totaalbedrag inclusief btw.")
    lines: list[InvoiceLine] = Field(default_factory=list)


def _valid_iban(iban: str) -> bool:
    """Controleer een IBAN met de mod-97-toets."""
    s = re.sub(r"\s+", "", iban).upper()
    if not re.fullmatch(r"[A-Z0-9]{15,34}", s):
        return False
    rearranged = s[4:] + s[:4]
    digits = "".join(str(int(c, 36)) for c in rearranged)
    return int(digits) % 97 == 1


def validate_invoice(inv: Invoice) -> list[str]:
    """Geeft een lijst met problemen terug. Leeg = klaar om te verwerken."""
    problems: list[str] = []

    if not inv.supplier:
        problems.append("Leverancier ontbreekt")
    if not inv.invoice_number:
        problems.append("Factuurnummer ontbreekt")
    if inv.invoice_date is None:
        problems.append("Factuurdatum ontbreekt of is ongeldig")
    if inv.total is None:
        problems.append("Totaalbedrag ontbreekt")

    # Rekenkundige controle: subtotaal + btw ≈ totaal (1 cent speling).
    if inv.subtotal is not None and inv.vat is not None and inv.total is not None:
        if abs((inv.subtotal + inv.vat) - inv.total) > 0.01:
            problems.append(
                f"Bedragen kloppen niet: {inv.subtotal} + {inv.vat} ≠ {inv.total}"
            )

    if inv.due_date and inv.invoice_date and inv.due_date < inv.invoice_date:
        problems.append("Vervaldatum ligt vóór de factuurdatum")

    if inv.iban and not _valid_iban(inv.iban):
        problems.append(f"IBAN lijkt ongeldig: {inv.iban}")

    return problems
