import { and, eq } from "drizzle-orm"
import type { FastifyInstance } from "fastify"
import { vendors } from "../../../db/schema"
import type { ParsedElectronicInvoice } from "./types"

const normalizeIdentifier = (value: unknown) => String(value || "").replace(/[^A-Za-z0-9]/g, "").toUpperCase()
const normalizeName = (value: unknown) => String(value || "").normalize("NFKD").replace(/[^A-Za-z0-9]/g, "").toUpperCase()

const paymentTypeByCode: Record<string, string> = {
    "10": "Bar",
    "30": "Überweisung",
    "48": "Kreditkarte",
    "49": "Lastschrift",
    "57": "Sonstiges",
    "58": "Überweisung",
    "59": "Lastschrift",
}

export const findElectronicInvoiceVendor = async (
    server: FastifyInstance,
    tenantId: number,
    invoice: ParsedElectronicInvoice,
) => {
    const candidates = await server.db.select().from(vendors).where(and(
        eq(vendors.tenant, tenantId),
        eq(vendors.archived, false),
    ))

    const vatId = normalizeIdentifier(invoice.seller.vatId)
    if (vatId) {
        const vatMatches = candidates.filter((vendor: any) => normalizeIdentifier(vendor.infoData?.ustid) === vatId)
        if (vatMatches.length === 1) return vatMatches[0]
    }

    const sellerName = normalizeName(invoice.seller.name)
    if (sellerName) {
        const nameMatches = candidates.filter((vendor) => normalizeName(vendor.name) === sellerName)
        if (nameMatches.length === 1) return nameMatches[0]
    }

    return null
}

export const mapElectronicInvoiceToIncomingInvoice = (
    invoice: ParsedElectronicInvoice,
    tenantId: number,
    vendorId: number | null,
    container: "pdf" | "xml",
    attachmentName: string | null,
) => {
    const warnings = [...invoice.validation.warnings]
    if (!vendorId) warnings.push("Rechnungssteller konnte keinem Lieferanten eindeutig zugeordnet werden.")

    const state = invoice.validation.errors.length > 0 || !vendorId ? "Prüfung erforderlich" : "Vorbereitet"
    const descriptionParts = [
        invoice.buyerReference ? `Käuferreferenz: ${invoice.buyerReference}` : null,
        ...invoice.items.map((item) => item.description),
    ].filter(Boolean)

    return {
        tenant: tenantId,
        state,
        vendor: vendorId,
        reference: invoice.invoiceNumber,
        date: invoice.invoiceDate,
        dueDate: invoice.dueDate,
        paymentType: paymentTypeByCode[invoice.paymentMeansCode || ""] || "Sonstiges",
        description: descriptionParts.join("\n"),
        accounts: invoice.items.map((item) => ({
            account: null,
            description: item.description,
            amountNet: item.netAmount,
            amountTax: item.taxAmount,
            taxType: item.taxCategory === "AE" ? "13B" : item.taxRate === 0 ? "null" : String(item.taxRate),
            amountGross: item.grossAmount,
            costCentre: null,
            quantity: item.quantity,
            unitCode: item.unitCode,
        })),
        preparationSource: "e-invoice",
        eInvoiceSyntax: invoice.syntax,
        eInvoiceProfile: invoice.profileId,
        eInvoiceValidation: {
            errors: invoice.validation.errors,
            warnings,
            totals: invoice.totals,
            seller: invoice.seller,
            invoiceType: invoice.invoiceType,
            container,
            attachmentName,
        },
    }
}
