import React from "react";
import { Document, Page, View, Text, StyleSheet, renderToBuffer } from "@react-pdf/renderer";
import { formatDate } from "./format";

// Frontend port of the Payload backend's src/lib/correctionInvoicePdf.tsx
// — the *real* Stornorechnung/Gutschrift is generated and emailed from
// Payload's own Orders.ts afterChange hook (that's where the status
// transition and the correction invoice NUMBER are actually assigned).
// This copy exists only so a customer can re-download the same document
// later from /konto/bestellungen/[orderNumber] without it having been
// stored as a file anywhere — same "deterministic regeneration, not file
// storage" approach already used for the original invoice (see
// invoicePdf.tsx): correctionInvoiceNumber/correctionInvoiceIssuedAt are
// immutable once set, so re-rendering from the order's own stored data
// always reproduces the identical document.
const BRAND = "#f6a701";
const TEXT_MUTED = "#6b6b69";
const BORDER = "#e5e0d8";
const BG_MUTED = "#f8f5f1";

const styles = StyleSheet.create({
  page: { padding: 0, fontSize: 10, fontFamily: "Helvetica", color: "#1a1a18" },
  // A rule, not a filled band — a bold brand-colored line rather than a
  // plain 1pt gray divider.
  headerBand: {
    padding: 32,
    paddingBottom: 24,
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    borderBottomWidth: 3,
    borderBottomColor: BRAND,
  },
  wordmark: { fontFamily: "Helvetica-Bold", fontSize: 14 },
  kindLabel: { fontFamily: "Helvetica-Bold", fontSize: 22, color: BRAND, letterSpacing: 1 },
  body: { padding: 32, paddingBottom: 90 },
  refLine: { fontSize: 10, color: TEXT_MUTED, marginBottom: 24 },
  addressRow: { flexDirection: "row", justifyContent: "space-between", marginBottom: 24 },
  addressBlock: { width: "45%" },
  addressLabel: { fontSize: 8, color: TEXT_MUTED, marginBottom: 4, textTransform: "uppercase" },
  addressLine: { fontSize: 10, lineHeight: 1.5 },
  metaRow: { flexDirection: "row", gap: 10, marginBottom: 24 },
  metaBox: { borderWidth: 1, borderColor: BORDER, borderRadius: 6, paddingVertical: 8, paddingHorizontal: 12 },
  metaLabel: { fontSize: 7, color: TEXT_MUTED, textTransform: "uppercase", marginBottom: 2 },
  metaValue: { fontSize: 10, fontFamily: "Helvetica-Bold" },
  table: { borderRadius: 6, overflow: "hidden", borderWidth: 1, borderColor: BORDER, marginBottom: 16 },
  tableHeader: { flexDirection: "row", backgroundColor: BG_MUTED, paddingVertical: 8, paddingHorizontal: 10 },
  tableRow: { flexDirection: "row", paddingVertical: 8, paddingHorizontal: 10, borderTopWidth: 1, borderTopColor: BORDER },
  tableRowAlt: { backgroundColor: BG_MUTED },
  colName: { flex: 3 },
  colQty: { flex: 1, textAlign: "right" },
  colPrice: { flex: 1, textAlign: "right" },
  colTotal: { flex: 1, textAlign: "right" },
  headerCell: { fontSize: 8, color: TEXT_MUTED, textTransform: "uppercase" },
  bundleLine: { fontSize: 8, color: TEXT_MUTED, marginTop: 2 },
  summary: { alignItems: "flex-end", marginBottom: 24 },
  summaryBox: { width: 240, backgroundColor: BG_MUTED, borderRadius: 6, padding: 14 },
  summaryRow: { flexDirection: "row", justifyContent: "space-between", paddingVertical: 2 },
  summaryLabel: { fontSize: 10, color: TEXT_MUTED },
  summaryValue: { fontSize: 10 },
  grandTotalRow: { flexDirection: "row", justifyContent: "space-between", paddingTop: 8, marginTop: 6, borderTopWidth: 1, borderTopColor: BORDER },
  grandTotalLabel: { fontSize: 12, fontFamily: "Helvetica-Bold" },
  grandTotalValue: { fontSize: 12, fontFamily: "Helvetica-Bold" },
  footer: {
    position: "absolute",
    bottom: 32,
    left: 32,
    right: 32,
    borderTopWidth: 1,
    borderTopColor: BORDER,
    paddingTop: 12,
    fontSize: 8,
    color: TEXT_MUTED,
  },
});

function formatPrice(amount: number): string {
  return new Intl.NumberFormat("de-DE", { style: "currency", currency: "EUR" }).format(amount);
}

export type CorrectionInvoiceKind = "storno" | "gutschrift";

export type CorrectionInvoiceItem = {
  productName: string;
  quantity: number;
  unitPrice: number;
  taxRatePercent: number;
  bundleContents?: string | null;
  returnQuantity?: number;
};

export type CorrectionInvoiceOrder = {
  orderNumber: string;
  invoiceNumber: string;
  invoiceIssuedAt: string;
  correctionInvoiceNumber: string;
  correctionInvoiceIssuedAt: string;
  customerFirstName: string;
  customerLastName: string;
  deliveryMethod: "address" | "packstation";
  street?: string | null;
  packstationNumber?: string | null;
  postNumber?: string | null;
  zip: string;
  city: string;
  country: string;
  items: CorrectionInvoiceItem[];
  subtotal: number;
  shippingCost: number;
  discountAmount: number;
  total: number;
};

export type InvoiceSeller = {
  sellerName: string;
  sellerStreet: string;
  sellerZip: string;
  sellerCity: string;
  sellerCountry: string;
  sellerEmail: string;
  vatId: string;
  taxRatePercent: number;
  bankDetails?: string | null;
};

// Stornorechnung: every item at its full ordered quantity (nothing
// shipped, undo everything). Gutschrift: only items with a nonzero
// returnQuantity, at that returned quantity — see this file's port source
// (backend src/lib/correctionInvoicePdf.tsx) for the full policy
// reasoning (no shipping refund, no discount reproration on a Gutschrift).
function resolveLineItems(kind: CorrectionInvoiceKind, items: CorrectionInvoiceItem[]): { item: CorrectionInvoiceItem; effectiveQuantity: number }[] {
  if (kind === "storno") return items.map((item) => ({ item, effectiveQuantity: item.quantity }));
  return items
    .filter((item) => (item.returnQuantity ?? 0) > 0)
    .map((item) => ({ item, effectiveQuantity: item.returnQuantity as number }));
}

function groupByTaxRate(
  kind: CorrectionInvoiceKind,
  lines: { item: CorrectionInvoiceItem; effectiveQuantity: number }[],
  order: CorrectionInvoiceOrder,
  defaultRate: number,
): { rate: number; net: number; tax: number; gross: number }[] {
  const groups = new Map<number, number>();
  for (const { item, effectiveQuantity } of lines) {
    const rate = item.taxRatePercent ?? defaultRate;
    const lineGross = effectiveQuantity * item.unitPrice;
    groups.set(rate, (groups.get(rate) ?? 0) + lineGross);
  }
  const scale = kind === "storno" && order.subtotal > 0 ? (order.subtotal - order.discountAmount + order.shippingCost) / order.subtotal : 1;
  return Array.from(groups.entries())
    .map(([rate, lineGross]) => {
      const gross = lineGross * scale;
      const net = gross / (1 + rate / 100);
      return { rate, net, tax: gross - net, gross };
    })
    .sort((a, b) => b.rate - a.rate);
}

function CorrectionInvoiceDocument({ kind, order, seller }: { kind: CorrectionInvoiceKind; order: CorrectionInvoiceOrder; seller: InvoiceSeller }) {
  const kindLabel = kind === "storno" ? "Stornorechnung" : "Gutschrift";
  const lines = resolveLineItems(kind, order.items);
  const rateGroups = groupByTaxRate(kind, lines, order, seller.taxRatePercent);
  const grandTotal = rateGroups.reduce((sum, g) => sum + g.gross, 0);
  const refNote =
    kind === "storno"
      ? "vollständige Stornierung des ursprünglichen Rechnungsbetrags (inkl. Versand)."
      : "Gutschrift für die zurückgesendeten Artikel — ohne Versandkosten, der ursprüngliche Rabatt bleibt unverändert bei den behaltenen Artikeln.";
  const deliveryLine =
    order.deliveryMethod === "address" ? order.street : `Packstation ${order.packstationNumber} · Postnummer ${order.postNumber}`;

  return (
    <Document>
      <Page size="A4" style={styles.page}>
        <View style={styles.headerBand}>
          <Text style={styles.wordmark}>einfach produktiv.</Text>
          <Text style={styles.kindLabel}>{kindLabel.toUpperCase()}</Text>
        </View>

        <View style={styles.body}>
          <Text style={styles.refLine}>
            {kindLabel} zu Rechnung Nr. {order.invoiceNumber} vom {formatDate(order.invoiceIssuedAt)} (Bestellung {order.orderNumber}) — {refNote}
          </Text>

          <View style={styles.addressRow}>
            <View style={styles.addressBlock}>
              <Text style={styles.addressLabel}>Von</Text>
              <Text style={styles.addressLine}>{seller.sellerName}</Text>
              <Text style={styles.addressLine}>{seller.sellerStreet}</Text>
              <Text style={styles.addressLine}>
                {seller.sellerZip} {seller.sellerCity}
              </Text>
              <Text style={styles.addressLine}>{seller.sellerCountry}</Text>
            </View>
            <View style={styles.addressBlock}>
              <Text style={styles.addressLabel}>An</Text>
              <Text style={styles.addressLine}>
                {order.customerFirstName} {order.customerLastName}
              </Text>
              <Text style={styles.addressLine}>{deliveryLine}</Text>
              <Text style={styles.addressLine}>
                {order.zip} {order.city}
              </Text>
              <Text style={styles.addressLine}>{order.country}</Text>
            </View>
          </View>

          <View style={styles.metaRow}>
            <View style={styles.metaBox}>
              <Text style={styles.metaLabel}>{kindLabel === "Gutschrift" ? "Gutschrift-Nr." : "Storno-Nr."}</Text>
              <Text style={styles.metaValue}>{order.correctionInvoiceNumber}</Text>
            </View>
            <View style={styles.metaBox}>
              <Text style={styles.metaLabel}>Datum</Text>
              <Text style={styles.metaValue}>{formatDate(order.correctionInvoiceIssuedAt)}</Text>
            </View>
            <View style={styles.metaBox}>
              <Text style={styles.metaLabel}>USt-IdNr.</Text>
              <Text style={styles.metaValue}>{seller.vatId}</Text>
            </View>
          </View>

          <View style={styles.table}>
            <View style={styles.tableHeader}>
              <Text style={[styles.colName, styles.headerCell]}>Artikel</Text>
              <Text style={[styles.colQty, styles.headerCell]}>Menge</Text>
              <Text style={[styles.colPrice, styles.headerCell]}>Einzelpreis</Text>
              <Text style={[styles.colTotal, styles.headerCell]}>Betrag</Text>
            </View>
            {lines.map(({ item, effectiveQuantity }, i) => (
              <View style={[styles.tableRow, i % 2 === 1 ? styles.tableRowAlt : {}]} key={i}>
                <View style={styles.colName}>
                  <Text>{item.productName}</Text>
                  {item.bundleContents ? <Text style={styles.bundleLine}>{item.bundleContents}</Text> : null}
                </View>
                <Text style={styles.colQty}>{effectiveQuantity}</Text>
                <Text style={styles.colPrice}>{formatPrice(item.unitPrice)}</Text>
                <Text style={styles.colTotal}>-{formatPrice(effectiveQuantity * item.unitPrice)}</Text>
              </View>
            ))}
          </View>

          <View style={styles.summary}>
            <View style={styles.summaryBox}>
              {rateGroups.map((g) => (
                <React.Fragment key={g.rate}>
                  <View style={styles.summaryRow}>
                    <Text style={styles.summaryLabel}>Netto ({g.rate}%)</Text>
                    <Text style={styles.summaryValue}>-{formatPrice(g.net)}</Text>
                  </View>
                  <View style={styles.summaryRow}>
                    <Text style={styles.summaryLabel}>zzgl. {g.rate}% MwSt.</Text>
                    <Text style={styles.summaryValue}>-{formatPrice(g.tax)}</Text>
                  </View>
                </React.Fragment>
              ))}
              <View style={styles.grandTotalRow}>
                <Text style={styles.grandTotalLabel}>Gesamt</Text>
                <Text style={styles.grandTotalValue}>-{formatPrice(grandTotal)}</Text>
              </View>
            </View>
          </View>
        </View>

        <View style={styles.footer} fixed>
          <Text>
            {seller.sellerName} · {seller.sellerStreet}, {seller.sellerZip} {seller.sellerCity} · {seller.sellerEmail} · USt-IdNr.{" "}
            {seller.vatId}
          </Text>
          {seller.bankDetails ? <Text style={{ marginTop: 4 }}>Bankverbindung (für Überweisung): {seller.bankDetails}</Text> : null}
        </View>
      </Page>
    </Document>
  );
}

export async function renderCorrectionInvoicePdf(kind: CorrectionInvoiceKind, order: CorrectionInvoiceOrder, seller: InvoiceSeller): Promise<Buffer> {
  return renderToBuffer(<CorrectionInvoiceDocument kind={kind} order={order} seller={seller} />);
}

// Exported for unit testing (see app/lib/__tests__/correctionInvoicePdf.test.ts)
// — the actual money math, independent of the PDF rendering.
export const __testables = { resolveLineItems, groupByTaxRate };
