/* eslint-disable react/no-unknown-property */
import {
  Document,
  Image,
  Page,
  StyleSheet,
  Text,
  View,
} from "@react-pdf/renderer";
import React from "react";

import { formatDate, formatMoney, formatQuantity, formatTaxRate } from "../format";
import { getStrings } from "../i18n";
import type { InvoiceLanguage } from "../i18n";
import type { InvoiceViewModel, InvoiceLine, IssuerData, RecipientData } from "../types";

// Brand blue chosen to roughly match the reference invoice. This is not
// pixel-perfect; merchants can tweak via a future setting if needed.
const BRAND_BLUE = "#1E8FCD";
const TEXT_DARK = "#1F2933";
const TEXT_MUTED = "#6B7280";
const TABLE_BORDER = "#E5E7EB";

const styles = StyleSheet.create({
  page: {
    paddingTop: 40,
    paddingBottom: 110, // leaves room for fixed footer
    paddingHorizontal: 40,
    fontSize: 9,
    fontFamily: "Helvetica",
    color: TEXT_DARK,
    lineHeight: 1.4,
  },
  headerRow: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "flex-start",
    marginBottom: 24,
  },
  logo: {
    maxHeight: 50,
    maxWidth: 180,
    objectFit: "contain",
  },
  senderLine: {
    fontSize: 7,
    color: TEXT_MUTED,
    marginBottom: 4,
    textDecoration: "underline",
  },
  recipientBlock: {
    width: "55%",
  },
  recipientName: {
    fontFamily: "Helvetica-Bold",
    fontSize: 10,
  },
  metaBlock: {
    width: "40%",
  },
  metaTable: {
    flexDirection: "column",
  },
  metaRow: {
    flexDirection: "row",
    justifyContent: "space-between",
    marginBottom: 2,
  },
  metaLabel: {
    color: TEXT_MUTED,
  },
  metaValue: {
    fontFamily: "Helvetica-Bold",
  },
  invoiceNumberBig: {
    color: BRAND_BLUE,
    fontFamily: "Helvetica-Bold",
    fontSize: 14,
  },
  title: {
    color: BRAND_BLUE,
    fontFamily: "Helvetica-Bold",
    fontSize: 18,
    marginTop: 20,
    marginBottom: 12,
  },
  paragraph: {
    marginBottom: 6,
  },
  table: {
    marginTop: 10,
    borderTopWidth: 0,
  },
  tableHeader: {
    flexDirection: "row",
    backgroundColor: BRAND_BLUE,
    color: "#FFFFFF",
    fontFamily: "Helvetica-Bold",
    paddingVertical: 6,
    paddingHorizontal: 4,
  },
  tableRow: {
    flexDirection: "row",
    borderBottomWidth: 0.5,
    borderBottomColor: TABLE_BORDER,
    paddingVertical: 6,
    paddingHorizontal: 4,
  },
  colPos: { width: "8%" },
  colDescription: { width: "44%" },
  colQty: { width: "16%", textAlign: "right" },
  colUnit: { width: "16%", textAlign: "right" },
  colTotal: { width: "16%", textAlign: "right" },
  descriptionCell: {
    flexDirection: "row",
    alignItems: "flex-start",
    gap: 6,
  },
  productIcon: {
    width: 28,
    height: 28,
    objectFit: "contain",
    borderWidth: 0.5,
    borderColor: TABLE_BORDER,
    borderRadius: 2,
  },
  productIconPlaceholder: {
    width: 28,
    height: 28,
  },
  descriptionText: {
    flex: 1,
  },
  itemTitle: {
    fontFamily: "Helvetica-Bold",
  },
  itemSku: {
    color: TEXT_MUTED,
    fontSize: 7,
    marginTop: 1,
  },
  totalsBlock: {
    marginTop: 10,
    alignSelf: "flex-end",
    width: "50%",
    // Match the table rows' horizontal padding so the right-aligned amounts
    // line up perfectly with the "Total" column above.
    paddingHorizontal: 4,
  },
  totalRow: {
    flexDirection: "row",
    justifyContent: "space-between",
    paddingVertical: 3,
  },
  totalLabel: {
    color: TEXT_DARK,
  },
  totalLabelBlue: {
    color: BRAND_BLUE,
    fontFamily: "Helvetica-Bold",
  },
  totalValue: {
    textAlign: "right",
  },
  totalValueBoldBlue: {
    textAlign: "right",
    color: BRAND_BLUE,
    fontFamily: "Helvetica-Bold",
  },
  noticeBlock: {
    marginTop: 10,
    padding: 6,
    backgroundColor: "#F3F4F6",
    fontSize: 8,
  },
  giroBlock: {
    marginTop: 20,
    flexDirection: "row",
    alignItems: "flex-start",
    gap: 10,
  },
  giroImage: {
    width: 90,
    height: 90,
  },
  giroCaption: {
    fontFamily: "Helvetica-Bold",
    color: BRAND_BLUE,
    fontSize: 9,
    marginBottom: 4,
  },
  giroDetails: {
    fontSize: 8,
    color: TEXT_DARK,
    lineHeight: 1.4,
  },
  closing: {
    marginTop: 24,
  },
  footer: {
    position: "absolute",
    bottom: 30,
    left: 40,
    right: 40,
    borderTopWidth: 0.5,
    borderTopColor: BRAND_BLUE,
    paddingTop: 6,
    flexDirection: "row",
    justifyContent: "space-between",
    fontSize: 7,
    color: TEXT_DARK,
  },
  footerCol: { width: "23%" },
  footerHeading: {
    fontFamily: "Helvetica-Bold",
    color: BRAND_BLUE,
    fontSize: 7,
    marginBottom: 3,
  },
  pageIndicator: {
    position: "absolute",
    bottom: 12,
    right: 40,
    fontSize: 7,
    color: TEXT_MUTED,
  },
  stornoBanner: {
    backgroundColor: "#B91C1C",
    color: "#FFFFFF",
    fontFamily: "Helvetica-Bold",
    padding: 6,
    marginBottom: 10,
    fontSize: 11,
    textAlign: "center",
  },
});

interface DocProps {
  invoice: InvoiceViewModel;
}

export function InvoiceDocument({ invoice }: DocProps) {
  const t = getStrings(invoice.language);
  const cur = invoice.currency;

  return (
    <Document
      title={`${t.invoice} ${invoice.number}`}
      author={invoice.issuer.companyName}
      creator="LinumIQ Invoice"
    >
      <Page size="A4" style={styles.page}>
        {invoice.kind === "storno" && (
          <Text style={styles.stornoBanner}>
            {t.stornoInvoice}
            {invoice.cancelsNumber ? ` — ${t.stornoReference(invoice.cancelsNumber)}` : ""}
          </Text>
        )}

        <Header issuer={invoice.issuer} />

        <View style={styles.headerRow}>
          <View style={styles.recipientBlock}>
            <Text style={styles.senderLine}>{senderInline(invoice.issuer)}</Text>
            <Recipient recipient={invoice.recipient} />
          </View>
          <View style={styles.metaBlock}>
            <View style={styles.metaTable}>
              <View style={styles.metaRow}>
                <Text style={styles.metaLabel}>{t.invoiceNumber}</Text>
                <Text style={styles.invoiceNumberBig}>{invoice.number}</Text>
              </View>
              <View style={styles.metaRow}>
                <Text style={styles.metaLabel}>{t.invoiceDate}</Text>
                <Text style={styles.metaValue}>{formatDate(invoice.invoiceDate, invoice.language)}</Text>
              </View>
              <View style={styles.metaRow}>
                <Text style={styles.metaLabel}>{t.deliveryDate}</Text>
                <Text style={styles.metaValue}>{formatDate(invoice.deliveryDate, invoice.language)}</Text>
              </View>
              {invoice.recipientVatId ? (
                <View style={styles.metaRow}>
                  <Text style={styles.metaLabel}>{t.customerVatId}</Text>
                  <Text style={styles.metaValue}>{invoice.recipientVatId}</Text>
                </View>
              ) : null}
            </View>
          </View>
        </View>

        <Text style={styles.title}>
          {invoice.kind === "storno" ? t.stornoInvoice : t.invoice} Nr. {invoice.number}
        </Text>

        <Text style={styles.paragraph}>{t.salutationGeneric}</Text>
        <Text style={styles.paragraph}>{t.thankYouLine}</Text>

        <View style={styles.table}>
          <View style={styles.tableHeader}>
            <Text style={styles.colPos}>{t.position}</Text>
            <Text style={styles.colDescription}>{t.description}</Text>
            <Text style={styles.colQty}>{t.quantity}</Text>
            <Text style={styles.colUnit}>{t.unitPrice}</Text>
            <Text style={styles.colTotal}>{t.totalPrice}</Text>
          </View>
          {invoice.lines.map((line) => (
            <LineRow key={line.position} line={line} language={invoice.language} currency={cur} />
          ))}
        </View>

        <View style={styles.totalsBlock}>
          <View style={styles.totalRow}>
            <Text style={styles.totalLabelBlue}>{t.netTotal}</Text>
            <Text style={[styles.totalValue, { color: BRAND_BLUE, fontFamily: "Helvetica-Bold" }]}>
              {formatMoney(invoice.totals.net, cur, invoice.language)}
            </Text>
          </View>
          {invoice.totals.vatBreakdown.map((v) => (
            <View key={`vat-${v.ratePct}`} style={styles.totalRow}>
              <Text style={styles.totalLabel}>{t.vatLine(formatTaxRate(v.ratePct, invoice.language))}</Text>
              <Text style={styles.totalValue}>{formatMoney(v.tax, cur, invoice.language)}</Text>
            </View>
          ))}
          <View style={[styles.totalRow, { borderTopWidth: 0.5, borderTopColor: TABLE_BORDER, marginTop: 4, paddingTop: 4 }]}>
            <Text style={styles.totalLabelBlue}>{t.grossTotal}</Text>
            <Text style={styles.totalValueBoldBlue}>
              {formatMoney(invoice.totals.gross, cur, invoice.language)}
            </Text>
          </View>
        </View>

        {invoice.notices.length > 0 && (
          <View style={styles.noticeBlock}>
            {invoice.notices.map((n) => (
              <Text key={n.kind}>
                {n.kind === "reverseCharge" && t.reverseChargeNotice}
                {n.kind === "export" && t.exportNotice}
                {n.kind === "kleinunternehmer" && t.kleinunternehmerNotice}
              </Text>
            ))}
          </View>
        )}

        <Text style={[styles.paragraph, { marginTop: 16 }]}>
          {invoice.dueDate
            ? t.paymentTerms(
                Math.max(0, Math.round((invoice.dueDate.getTime() - invoice.invoiceDate.getTime()) / 86400000)),
                formatDate(invoice.dueDate, invoice.language),
              )
            : t.paymentTermsImmediate}
        </Text>

        {invoice.giroCodePngDataUrl && !invoice.paid && (
          <View style={styles.giroBlock}>
            <Image src={invoice.giroCodePngDataUrl} style={styles.giroImage} />
            <View>
              <Text style={styles.giroCaption}>{t.giroCodeCaption}</Text>
              <Text style={styles.giroDetails}>{invoice.issuer.bankName}</Text>
              <Text style={styles.giroDetails}>{t.ibanLabel}: {invoice.issuer.iban}</Text>
              {invoice.issuer.bic ? (
                <Text style={styles.giroDetails}>{t.bicLabel}: {invoice.issuer.bic}</Text>
              ) : null}
              <Text style={styles.giroDetails}>
                {formatMoney(invoice.totals.gross, cur, invoice.language)}
              </Text>
            </View>
          </View>
        )}

        <View style={styles.closing}>
          <Text>{t.closing}</Text>
        </View>

        <Footer issuer={invoice.issuer} language={invoice.language} />

        <Text
          style={styles.pageIndicator}
          render={({ pageNumber, totalPages }) => `${pageNumber}/${totalPages}`}
          fixed
        />
      </Page>
    </Document>
  );
}

function senderInline(issuer: IssuerData): string {
  return [
    [issuer.companyName, issuer.legalForm].filter(Boolean).join(" "),
    issuer.addressLine1,
    [issuer.postalCode, issuer.city].filter(Boolean).join(" "),
  ]
    .filter(Boolean)
    .join(" - ");
}

function Header({ issuer }: { issuer: IssuerData }) {
  return (
    <View style={styles.headerRow}>
      <View>{/* spacer; logo is right-aligned */}</View>
      {issuer.logoDataUrl ? <Image src={issuer.logoDataUrl} style={styles.logo} /> : <View />}
    </View>
  );
}

function Recipient({ recipient }: { recipient: RecipientData }) {
  const lines: string[] = [];
  if (recipient.company) lines.push(recipient.company);
  if (recipient.name && recipient.name !== recipient.company) lines.push(recipient.name);
  if (recipient.addressLine1) lines.push(recipient.addressLine1);
  if (recipient.addressLine2) lines.push(recipient.addressLine2);
  const cityLine = [recipient.postalCode, recipient.city].filter(Boolean).join(" ");
  if (cityLine) lines.push(cityLine);
  if (recipient.countryCode) lines.push(recipient.countryCode);

  return (
    <View>
      {lines.map((l, i) => (
        <Text key={i} style={i === 0 ? styles.recipientName : undefined}>
          {l}
        </Text>
      ))}
    </View>
  );
}

function LineRow({
  line,
  language,
  currency,
}: {
  line: InvoiceLine;
  language: InvoiceLanguage;
  currency: string;
}) {
  const t = getStrings(language);
  return (
    <View style={styles.tableRow}>
      <Text style={styles.colPos}>{line.position}</Text>
      <View style={[styles.colDescription, styles.descriptionCell]}>
        {line.imageDataUrl ? (
          <Image src={line.imageDataUrl} style={styles.productIcon} />
        ) : (
          <View style={styles.productIconPlaceholder} />
        )}
        <View style={styles.descriptionText}>
          <Text style={styles.itemTitle}>{line.title}</Text>
          {line.sku ? <Text style={styles.itemSku}>SKU: {line.sku}</Text> : null}
        </View>
      </View>
      <Text style={styles.colQty}>{formatQuantity(line.quantity, t.pieceUnit, language)}</Text>
      <Text style={styles.colUnit}>{formatMoney(line.unitPriceNet, currency, language)}</Text>
      <Text style={styles.colTotal}>{formatMoney(line.totalNet, currency, language)}</Text>
    </View>
  );
}

function Footer({ issuer, language }: { issuer: IssuerData; language: InvoiceLanguage }) {
  const t = getStrings(language);
  return (
    <View style={styles.footer} fixed>
      <View style={styles.footerCol}>
        <Text style={styles.footerHeading}>{t.addressHeading}</Text>
        <Text>{[issuer.companyName, issuer.legalForm].filter(Boolean).join(" ")}</Text>
        {issuer.addressLine1 ? <Text>{issuer.addressLine1}</Text> : null}
        {issuer.addressLine2 ? <Text>{issuer.addressLine2}</Text> : null}
        <Text>{[issuer.postalCode, issuer.city].filter(Boolean).join(" ")}</Text>
        {issuer.countryCode ? <Text>{issuer.countryCode}</Text> : null}
      </View>
      <View style={styles.footerCol}>
        <Text style={styles.footerHeading}>{t.contactHeading}</Text>
        {issuer.phone ? <Text>{t.phoneLabel}: {issuer.phone}</Text> : null}
        {issuer.email ? <Text>{t.emailLabel}: {issuer.email}</Text> : null}
        {issuer.website ? <Text>{t.webLabel}: {issuer.website}</Text> : null}
      </View>
      <View style={styles.footerCol}>
        <Text style={styles.footerHeading}>{t.legalHeading}</Text>
        {issuer.registrationCourt ? (
          <Text>{t.legalCourtLabel}: {issuer.registrationCourt}</Text>
        ) : null}
        {issuer.registrationNo ? <Text>{t.fnLabel}: {issuer.registrationNo}</Text> : null}
        {issuer.vatId ? <Text>{t.vatIdLabel}: {issuer.vatId}</Text> : null}
        {issuer.taxNumber ? <Text>{t.taxNumberLabel}: {issuer.taxNumber}</Text> : null}
        {issuer.ownerName ? <Text>{t.ownerLabel}: {issuer.ownerName}</Text> : null}
      </View>
      <View style={styles.footerCol}>
        <Text style={styles.footerHeading}>{t.bankHeading}</Text>
        {issuer.bankName ? <Text>{t.bankLabel}: {issuer.bankName}</Text> : null}
        {issuer.iban ? <Text>{t.ibanLabel}: {issuer.iban}</Text> : null}
        {issuer.bic ? <Text>{t.bicLabel}: {issuer.bic}</Text> : null}
        {pickFooterNote(issuer, language) ? <Text>{pickFooterNote(issuer, language)}</Text> : null}
      </View>
    </View>
  );
}

/**
 * Picks the footer note for the rendered language. English falls back to the
 * German `footerNote` when `footerNoteEn` is empty (so existing single-language
 * setups keep working). German always uses `footerNote`.
 */
function pickFooterNote(issuer: { footerNote: string; footerNoteEn: string }, language: InvoiceLanguage): string {
  if (language === "en") {
    return issuer.footerNoteEn?.trim() || issuer.footerNote || "";
  }
  return issuer.footerNote || "";
}
