import path from "path";
import { Document, Page, Text, View, StyleSheet, Font, renderToBuffer } from "@react-pdf/renderer";
import type { ContractDoc } from "@/models/Contract";
import type { ContractTemplateSection } from "@/models/ContractTemplate";
import { formatEUR, formatAddress, formatDateTimeDE } from "@/lib/orderConstants";
import { formatNameWithSalutation } from "@/lib/salutation";

export interface ContractPartyInfo {
  clientName: string;
  // "" (kein Herr/Frau-Präfix) bei "divers" oder noch nicht gepflegter Anrede.
  clientSalutation: string;
  clientEmail: string;
  clientStreet: string;
  clientPostCode: string;
  clientCity: string;
  photographerEmail: string;
  photographerInstagram: string;
  photographerWebsite: string;
}

export interface ContractLetterhead {
  businessName: string;
  legalName: string;
  street: string;
  postCode: string;
  city: string;
  countryCode: string;
}

// Bevorzugt die strukturierten Straße/PLZ/Ort-Felder — fällt bei vor der
// Umstellung angelegten Verträgen auf die alte Freitext-Zeile zurück, damit
// bestehende Vertrags-PDFs weiterhin korrekt anzeigen.
function partyAddress(d: { street?: string; postCode?: string; city?: string; address?: string }): string {
  const structured = formatAddress({ street: d.street, postCode: d.postCode, city: d.city });
  return structured || d.address || "";
}

// Der Markenname "Rakku Photography" allein reicht als Vertragspartei nicht
// — bei einem Einzelunternehmen unterschreibt die reale Person (Nutzer-
// Wunsch 15.09.2026: "ich muss ja auch als Till Kuhlmann unterschreiben"),
// daher immer den bürgerlichen Namen mit ausweisen, falls gepflegt.
function photographerDisplayName(letterhead: ContractLetterhead): string {
  if (letterhead.legalName && letterhead.legalName !== letterhead.businessName) {
    return `${letterhead.businessName} (${letterhead.legalName})`;
  }
  return letterhead.businessName;
}

// Gleiche Wortmarken-Schrift wie im Dokumenten-Briefkopf (documentPdf.tsx) —
// beide Generatoren registrieren sie unabhängig voneinander, doppeltes
// Registrieren mit demselben Namen ist bei react-pdf unproblematisch.
Font.register({
  family: "Quantify",
  src: path.join(process.cwd(), "src/app/fonts/Quantify.ttf"),
});

const styles = StyleSheet.create({
  page: { padding: 48, paddingBottom: 72, fontSize: 10, fontFamily: "Helvetica", color: "#1a1a1a" },
  // Briefkopf — bewusst identisch zu documentPdf.tsx aufgebaut (Wortmarke,
  // Rechtsname, Adresse, Trennlinie, Eyebrow), damit Verträge optisch wie
  // die übrigen generierten Dokumente aussehen. Ohne die Empfänger-Spalte
  // aus documentPdf.tsx — die Vertragsparteien stehen weiter unten ohnehin
  // ausführlich im "Vertragsparteien"-Block.
  wordmark: { fontFamily: "Quantify", fontSize: 20, letterSpacing: 2, marginBottom: 4 },
  legalName: { fontSize: 9, color: "#555", marginBottom: 2 },
  address: { fontSize: 9, color: "#555" },
  rule: { borderBottom: "1px solid #e5e5e5", marginTop: 10, marginBottom: 10 },
  eyebrow: { fontSize: 8, color: "#777", textTransform: "uppercase", letterSpacing: 1.5 },
  title: { fontSize: 16, fontFamily: "Helvetica-Bold", marginTop: 14, marginBottom: 18 },
  h2: { fontSize: 11, fontFamily: "Helvetica-Bold", marginTop: 14, marginBottom: 4 },
  p: { marginBottom: 6, lineHeight: 1.5 },
  row: { flexDirection: "row", marginBottom: 3 },
  label: { width: 140, color: "#555" },
  value: { flex: 1 },
  sigBlock: { marginTop: 10, borderTop: "1px solid #ccc", paddingTop: 6 },
  sigRow: { flexDirection: "row", justifyContent: "space-between", marginTop: 18 },
  sigCol: { width: "45%" },
  sigLine: { borderTop: "1px solid #999", marginTop: 24, paddingTop: 3, fontSize: 8, color: "#555" },
  // Gleiche Fußzeile wie documentPdf.tsx (Position/Abstände identisch), für
  // optisch einheitliches Erscheinungsbild aller generierten PDFs.
  footerMeta: {
    position: "absolute",
    bottom: 24,
    left: 48,
    right: 48,
    fontSize: 8,
    color: "#999",
    textAlign: "center",
    borderTop: "1px solid #eee",
    paddingTop: 8,
    flexDirection: "row",
    justifyContent: "space-between",
  },
});

function Letterhead({ letterhead, eyebrow }: { letterhead: ContractLetterhead; eyebrow: string }) {
  return (
    <View>
      <Text style={styles.wordmark}>{letterhead.businessName.toUpperCase()}</Text>
      {letterhead.legalName && letterhead.legalName !== letterhead.businessName && (
        <Text style={styles.legalName}>{letterhead.legalName}</Text>
      )}
      <Text style={styles.address}>
        {formatAddress({ street: letterhead.street, postCode: letterhead.postCode, city: letterhead.city, countryCode: letterhead.countryCode })}
      </Text>
      <View style={styles.rule} />
      <Text style={styles.eyebrow}>{eyebrow}</Text>
    </View>
  );
}

function FooterMeta({ documentName }: { documentName: string }) {
  return (
    <View style={styles.footerMeta} fixed>
      <Text>{documentName}</Text>
      <Text render={({ pageNumber, totalPages }) => `Seite ${pageNumber} von ${totalPages}`} />
    </View>
  );
}

function Field({ label, value }: { label: string; value?: string }) {
  if (!value) return null;
  return (
    <View style={styles.row}>
      <Text style={styles.label}>{label}</Text>
      <Text style={styles.value}>{value}</Text>
    </View>
  );
}

// Rendert die in der Vorlagen-Verwaltung (admin/contract-templates) frei
// bearbeitbaren Vertragsabschnitte — das ist der eigentliche Rechtstext.
// Rein datengetriebene Angaben (Preis, Termin, Nutzungsrechte-Auswahl usw.)
// stehen bewusst nicht hier, sondern im "Angaben zum Auftrag"-Block darüber.
//
// Überschrift + erster Absatz stecken zusammen in einer wrap={false}-View,
// damit react-pdf die Überschrift nie allein am Seitenende stehen lässt,
// während der zugehörige Text erst auf der Folgeseite weitergeht (Waisen-
// Effekt). Weitere Absätze bleiben normal umbrechbar, sonst müsste z. B. die
// gesamte AGB als ein einziger unteilbarer Block auf eine Seite passen.
function TemplateSections({ sections }: { sections: ContractTemplateSection[] }) {
  return (
    <>
      {sections
        .filter((s) => !s.appendix)
        .map((s, i) => {
          const [first, ...rest] = s.body.split(/\n\n+/);
          return (
            <View key={i}>
              <View wrap={false}>
                <Text style={styles.h2}>{s.heading}</Text>
                {first && <Text style={styles.p}>{first}</Text>}
              </View>
              {rest.map((para, j) => (
                <Text key={j} style={styles.p}>
                  {para}
                </Text>
              ))}
            </View>
          );
        })}
    </>
  );
}

// Anhang-Abschnitte (AGB) — beginnen auf einer eigenen Seite NACH dem
// Unterschriftenblock, statt zwischen den Vertragsklauseln zu stehen.
function AppendixPage({ letterhead, sections, documentName }: { letterhead: ContractLetterhead; sections: ContractTemplateSection[]; documentName: string }) {
  const appendixSections = sections.filter((s) => s.appendix);
  if (appendixSections.length === 0) return null;
  return (
    <Page size="A4" style={styles.page}>
      <Letterhead letterhead={letterhead} eyebrow="Anlage" />
      {appendixSections.map((s, i) => {
        const [first, ...rest] = s.body.split(/\n\n+/);
        return (
          <View key={i}>
            <View wrap={false}>
              <Text style={styles.h2}>{s.heading}</Text>
              {first && <Text style={styles.p}>{first}</Text>}
            </View>
            {rest.map((para, j) => (
              <Text key={j} style={styles.p}>
                {para}
              </Text>
            ))}
          </View>
        );
      })}
      <FooterMeta documentName={documentName} />
    </Page>
  );
}

function PartiesBlock({
  info,
  letterhead,
  clientLabel,
  shortNames,
  extra,
}: {
  info: ContractPartyInfo;
  letterhead: ContractLetterhead;
  clientLabel: string;
  // Definiert die Kurzbezeichnungen, mit denen die Vertragsparteien im
  // restlichen Dokumenttext angesprochen werden (z. B. "Fotograf"/"Model"
  // im TFP-Vertrag, "Auftragnehmer"/"Auftraggeber/in" im Standardvertrag) —
  // muss zu den tatsächlich im Fließtext verwendeten Begriffen passen.
  shortNames: { photographer: string; client: string };
  extra?: { label: string; value?: string }[];
}) {
  return (
    <>
      <Text style={styles.h2}>Vertragsparteien</Text>
      <View style={{ flexDirection: "row", marginBottom: 6 }}>
        <View style={{ flex: 1 }}>
          <Text style={{ fontFamily: "Helvetica-Bold", marginBottom: 3 }}>Fotograf/in</Text>
          <Field label="Name" value={photographerDisplayName(letterhead)} />
          <Field label="E-Mail" value={info.photographerEmail} />
          <Field label="Instagram" value={info.photographerInstagram} />
          <Field label="Webseite" value={info.photographerWebsite} />
        </View>
        <View style={{ flex: 1 }}>
          <Text style={{ fontFamily: "Helvetica-Bold", marginBottom: 3 }}>{clientLabel}</Text>
          <Field label="Name" value={formatNameWithSalutation(info.clientSalutation, info.clientName)} />
          <Field label="E-Mail" value={info.clientEmail} />
          {extra?.map((f) => <Field key={f.label} label={f.label} value={f.value} />)}
        </View>
      </View>
      <Text style={{ fontSize: 8, color: "#777", marginBottom: 10 }}>
        Im Folgenden werden die Vertragsparteien als „{shortNames.photographer}" und „{shortNames.client}" bezeichnet.
      </Text>
    </>
  );
}

function SignatureBlock({
  label,
  sig,
}: {
  label: string;
  sig?: { name: string; signedAt: Date };
}) {
  return (
    <View style={styles.sigCol}>
      <Text style={{ fontFamily: "Helvetica-Bold", marginBottom: 4 }}>{label}</Text>
      {sig ? (
        <>
          <Text>{sig.name}</Text>
          <Text style={{ color: "#555", fontSize: 8 }}>
            digital unterschrieben am {formatDateTimeDE(new Date(sig.signedAt))}
          </Text>
        </>
      ) : (
        <View style={styles.sigLine}>
          <Text>noch nicht unterschrieben</Text>
        </View>
      )}
    </View>
  );
}

function StandardContractPdf({
  contract,
  info,
  letterhead,
  sections,
}: {
  contract: ContractDoc;
  info: ContractPartyInfo;
  letterhead: ContractLetterhead;
  sections: ContractTemplateSection[];
}) {
  const d = contract.standardData!;
  const photographerSig = contract.signatures.find((s) => s.role === "photographer");
  const modelSig = contract.signatures.find((s) => s.role === "model");

  return (
    <>
    <Page size="A4" style={styles.page}>
      <Letterhead letterhead={letterhead} eyebrow="Vertrag" />
      <Text style={styles.title}>Fotografie-Dienstleistungsvertrag</Text>

      <PartiesBlock
        info={info}
        letterhead={letterhead}
        clientLabel="Auftraggeber/in"
        shortNames={{ photographer: "Auftragnehmer", client: "Auftraggeber/in" }}
        extra={[{ label: "Anschrift", value: formatAddress({ street: info.clientStreet, postCode: info.clientPostCode, city: info.clientCity }) }]}
      />

      <Text style={styles.h2}>Angaben zum Auftrag</Text>
      <Field label="Charakter / Idee" value={d.characterOrConcept} />
      <Field label="Art des Shootings" value={d.shootingType} />
      <Field label="Ort / Event" value={d.eventLocation} />
      <Field label="Zeitraum" value={d.datePeriod} />
      <Field label="Vereinbarter Preis" value={`${formatEUR(d.amount)} (brutto)`} />
      <Text style={styles.p}>
        Der Auftraggeber erhält nach vollständiger Bezahlung ein einfaches, nicht exklusives Nutzungsrecht an den
        final bearbeiteten Bildern für private, nicht-kommerzielle Zwecke. Der Auftragnehmer bleibt Urheber.{" "}
        {d.usageRights === "no"
          ? "Der Auftragnehmer nutzt die Bilder nicht für eigene Portfolio- oder Eigenwerbungszwecke."
          : d.usageRights === "anonymized"
            ? "Der Auftragnehmer darf die Bilder nur in anonymisierter Form (z. B. ohne erkennbares Gesicht) für eigene Portfolio- und Eigenwerbungszwecke nutzen (Website, Social Media, Google-Unternehmensprofil, Print-Portfolio)."
            : "Der Auftragnehmer darf die Bilder für eigene Portfolio- und Eigenwerbungszwecke nutzen (Website, Social Media, Google-Unternehmensprofil, Print-Portfolio), sofern nicht ausdrücklich anders vereinbart."}
      </Text>

      <TemplateSections sections={sections} />

      <View style={styles.sigBlock}>
        <Text style={{ fontFamily: "Helvetica-Bold" }}>Unterschriften</Text>
        <View style={styles.sigRow}>
          <SignatureBlock label="Auftragnehmer" sig={photographerSig} />
          <SignatureBlock label="Auftraggeber/in" sig={modelSig} />
        </View>
      </View>
      <FooterMeta documentName="Fotografie-Dienstleistungsvertrag" />
    </Page>
    <AppendixPage letterhead={letterhead} sections={sections} documentName="Fotografie-Dienstleistungsvertrag" />
    </>
  );
}

function TfpContractPdf({
  contract,
  info,
  letterhead,
  sections,
}: {
  contract: ContractDoc;
  info: ContractPartyInfo;
  letterhead: ContractLetterhead;
  sections: ContractTemplateSection[];
}) {
  const d = contract.tfpData!;
  const photographerSig = contract.signatures.find((s) => s.role === "photographer");
  const modelSig = contract.signatures.find((s) => s.role === "model");
  const guardian1Sig = contract.signatures.find((s) => s.role === "guardian1");
  const guardian2Sig = contract.signatures.find((s) => s.role === "guardian2");

  const creditLabel =
    d.creditPreference === "nennen"
      ? "Nennen/Verlinken gewünscht"
      : d.creditPreference === "nicht_nennen"
        ? "Nicht nennen/verlinken"
        : "Je nach Bild/Plattform nach Absprache";

  return (
    <>
    <Page size="A4" style={styles.page}>
      <Letterhead letterhead={letterhead} eyebrow="TFP-Vertrag" />
      <Text style={styles.title}>TFP-Shooting-Vertrag</Text>
      <Text style={{ ...styles.p, color: "#555" }}>
        Model Release für Portrait-, Cosplay- und Convention-Fotografie · {letterhead.businessName}
      </Text>

      <PartiesBlock
        info={info}
        letterhead={letterhead}
        clientLabel="Model / teilnehmende Person"
        shortNames={{ photographer: "Fotograf", client: "Model" }}
        extra={[
          { label: "Geburtsdatum", value: d.modelBirthdate },
          { label: "Anschrift", value: partyAddress({ street: d.modelStreet, postCode: d.modelPostCode, city: d.modelCity, address: d.modelAddress }) },
          { label: "Instagram", value: d.modelInstagram },
        ]}
      />

      <Text style={styles.h2}>Angaben zum Shooting</Text>
      <Field label="Charakter / Thema" value={d.shootingTheme} />
      <Field label="Ort / Event" value={d.shootingLocation} />
      <Field label="Datum / Zeitraum" value={d.shootingDate} />
      <Field label="Art" value={d.shootingKinds.join(", ")} />
      <Field label="Bildauswahl" value={d.finalImageCount} />
      <Field label="Nutzungsrechte Fotograf" value={d.photographerUsage.join(", ") || "—"} />
      <Field label="Veröffentlichung — Kanäle" value={d.publicationChannels.join(", ") || "—"} />
      <Field label="Einschränkungen" value={d.publicationRestrictions} />
      <Field label="Credit-Wunsch" value={`${creditLabel}${d.creditHandle ? " — " + d.creditHandle : ""}`} />
      <Text style={styles.p}>
        {d.photographerCreditRequired
          ? `Bei eigener Veröffentlichung durch das Model ist ${letterhead.businessName} als Fotograf zu nennen bzw. zu verlinken, soweit dies auf der jeweiligen Plattform möglich ist.`
          : `Eine Nennung oder Verlinkung von ${letterhead.businessName} bei eigener Veröffentlichung durch das Model ist nicht erforderlich.`}
      </Text>
      <Field label="Begleitperson erlaubt" value={d.companionAllowed ? "Ja" : "Nein"} />

      {d.stylist && (
        <>
          <Text style={{ fontFamily: "Helvetica-Bold", marginTop: 8, marginBottom: 3 }}>Stylist/in</Text>
          <Field label="Name" value={d.stylist.name} />
          <Field label="Anschrift" value={partyAddress(d.stylist)} />
          <Field label="Instagram" value={d.stylist.instagram} />
          <Field label="Nutzung erlaubt" value={d.stylist.usage.join(", ")} />
          <Field label="Credit" value={d.stylist.credit} />
        </>
      )}

      {d.isMinor && (
        <>
          <Text style={{ fontFamily: "Helvetica-Bold", marginTop: 8, marginBottom: 3 }}>
            Minderjährig — gesetzliche Vertretung
          </Text>
          {d.guardians.map((g, i) => (
            <View key={i} style={{ marginBottom: 4 }}>
              <Field label={`Vertreter/in ${i + 1}`} value={`${g.name} — ${partyAddress(g)} — ${g.contact}`} />
            </View>
          ))}
        </>
      )}

      {d.specialAgreements && (
        <>
          <Text style={styles.h2}>Besondere Vereinbarungen</Text>
          <Text style={styles.p}>{d.specialAgreements}</Text>
        </>
      )}

      <TemplateSections sections={sections} />

      <View style={styles.sigBlock}>
        <Text style={{ fontFamily: "Helvetica-Bold" }}>Unterschriften</Text>
        <View style={styles.sigRow}>
          <SignatureBlock label="Fotograf/in" sig={photographerSig} />
          <SignatureBlock label="Model" sig={modelSig} />
        </View>
        {d.isMinor && (
          <View style={styles.sigRow}>
            <SignatureBlock label="Gesetzl. Vertreter/in 1" sig={guardian1Sig} />
            <SignatureBlock label="Gesetzl. Vertreter/in 2" sig={guardian2Sig} />
          </View>
        )}
      </View>
      <FooterMeta documentName="TFP-Shooting-Vertrag" />
    </Page>
    <AppendixPage letterhead={letterhead} sections={sections} documentName="TFP-Shooting-Vertrag" />
    </>
  );
}

export async function renderContractPdf(
  contract: ContractDoc,
  info: ContractPartyInfo,
  letterhead: ContractLetterhead,
  sections: ContractTemplateSection[]
): Promise<Buffer> {
  const doc = (
    <Document>
      {contract.type === "standard" ? (
        <StandardContractPdf contract={contract} info={info} letterhead={letterhead} sections={sections} />
      ) : (
        <TfpContractPdf contract={contract} info={info} letterhead={letterhead} sections={sections} />
      )}
    </Document>
  );
  return renderToBuffer(doc);
}
