import * as React from "react";
import { cn } from "@/lib/utils";
import { formatDateShort } from "@/lib/format-date";

/**
 * Statement document primitives - WealthX DS (L1 Atoms)
 *
 * Atomic building blocks for a generated statement document (the PDF a broker
 * downloads from Reports & Statements). Compose upward:
 *
 *   Atom     → StatementPage, StatementDocumentHeader, StatementField …
 *   Organism → StatementTransactionTable
 *   Template → StatementDocument
 *
 * A statement is a printed artefact, so these render on fixed white paper with
 * fixed ink colours rather than the themed app surface - see
 * `component-descriptions/bank-statement-document.md`. Tenant branding enters
 * through the `companyLogo` slot on `StatementDocumentHeader`.
 *
 * Reference: `Sample_Open_Banking_statement_<type>.pdf` on COMPANY-501 -
 * missing values print as "Not available", exactly as the samples do.
 */

const NO_DATA = "Not available";

/** Ink colours for the printed page - deliberately not theme-reactive. */
export const STATEMENT_INK = "text-[#040d13]";
export const STATEMENT_INK_MUTED = "text-[#686e71]";
export const STATEMENT_RULE = "border-[#e0e0e0]";
export const STATEMENT_RULE_LIGHT = "border-[#f0f0f0]";

// ---------------------------------------------------------------------------
// StatementPage
// ---------------------------------------------------------------------------

export interface StatementPageProps {
  children: React.ReactNode;
  /**
   * Render at A4 aspect ratio (210:297). Off by default so a long ledger can
   * grow past one page in Storybook instead of clipping.
   */
  fixedHeight?: boolean;
  className?: string;
}

/** White A4-proportioned paper the statement is laid out on. */
export function StatementPage({
  children,
  fixedHeight = false,
  className,
}: StatementPageProps) {
  return (
    <div
      data-slot="statement-page"
      className={cn(
        "mx-auto flex w-full max-w-[794px] flex-col bg-white p-8 shadow-sm md:p-10",
        fixedHeight && "aspect-[210/297] overflow-hidden",
        STATEMENT_INK,
        className,
      )}
    >
      {children}
    </div>
  );
}

// ---------------------------------------------------------------------------
// StatementDocumentHeader
// ---------------------------------------------------------------------------

export interface StatementDocumentHeaderProps {
  /** Eyebrow above the title, e.g. "Open Banking". */
  overline?: string;
  /** Document title, e.g. "Account statement". */
  title?: string;
  institutionName?: string;
  /** Institution logo URL - shown beside the institution name. */
  institutionLogo?: string;
  /** Tenant / company logo URL - shown top-right. White-label slot. */
  companyLogo?: string;
  companyName?: string;
  /** CDR accreditation line, e.g. "Under CDR principal: ADRBNK000208". */
  cdrLine?: string;
  className?: string;
}

/** Document title + institution left, tenant branding + CDR line right. */
export function StatementDocumentHeader({
  overline = "Open Banking",
  title = "Account statement",
  institutionName,
  institutionLogo,
  companyLogo,
  companyName = "WealthX Pty Ltd",
  cdrLine = "Under CDR principal: ADRBNK000208",
  className,
}: StatementDocumentHeaderProps) {
  return (
    <div
      data-slot="statement-document-header"
      className={cn("flex items-start justify-between gap-6", className)}
    >
      <div className="flex min-w-0 flex-col gap-1">
        {overline && <span className="text-overline">{overline}</span>}
        <span className="text-h3 uppercase">{title}</span>
        {institutionLogo && (
          <img
            src={institutionLogo}
            alt=""
            className="mt-2 h-10 w-auto max-w-[160px] self-start object-contain object-left"
          />
        )}
        <span className={cn("mt-1 text-body-small", STATEMENT_INK_MUTED)}>
          {institutionName || NO_DATA}
        </span>
      </div>

      <div className="flex flex-col items-end gap-2 text-right">
        {companyLogo && (
          <img
            src={companyLogo}
            alt={companyName}
            className="h-10 w-auto max-w-[189px] object-contain object-right"
          />
        )}
        <span className={cn("text-body-small", STATEMENT_INK_MUTED)}>
          {companyName}
        </span>
        {cdrLine && (
          <span className={cn("text-caption", STATEMENT_INK_MUTED)}>
            {cdrLine}
          </span>
        )}
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// StatementHolderBlock
// ---------------------------------------------------------------------------

export interface StatementHolderBusinessFields {
  legalName?: string;
  agentName?: string;
  abn?: string;
}

export interface StatementHolderBlockProps {
  holderName?: string;
  /** Multi-line postal address. */
  address?: string;
  /** Legal name / agent name / ABN rows for business accounts. */
  business?: StatementHolderBusinessFields;
  className?: string;
}

/** Who the statement is addressed to. */
export function StatementHolderBlock({
  holderName,
  address,
  business,
  className,
}: StatementHolderBlockProps) {
  return (
    <div
      data-slot="statement-holder-block"
      className={cn("flex min-w-0 flex-col gap-1", className)}
    >
      <span className="text-label-medium">{holderName || "Account holder"}</span>
      {address
        ?.split("\n")
        .filter(Boolean)
        .map((line) => (
          <span
            key={line}
            className={cn("text-body-small", STATEMENT_INK_MUTED)}
          >
            {line}
          </span>
        ))}
      {business && (
        <div className="mt-4 flex flex-col gap-1">
          <StatementField label="Legal name" value={business.legalName} />
          <StatementField label="Agent name" value={business.agentName} />
          <StatementField label="ABN" value={business.abn} />
        </div>
      )}
    </div>
  );
}

// ---------------------------------------------------------------------------
// StatementPageFooter
// ---------------------------------------------------------------------------

export interface StatementPageFooterProps {
  /** Left-hand reference line, e.g. "Jordan Whitfield - Everyday Access 5678". */
  reference?: string;
  /** ISO date the statement was generated. */
  generatedOn?: string;
  /** Right-hand page label. */
  pageLabel?: string;
  className?: string;
}

/** Ruled page footer - reference and generated-on left, page number right. */
export function StatementPageFooter({
  reference,
  generatedOn,
  pageLabel = "Page 1 of 1",
  className,
}: StatementPageFooterProps) {
  return (
    <div
      data-slot="statement-page-footer"
      className={cn(
        "flex items-end justify-between gap-6 border-t pt-3",
        STATEMENT_RULE,
        className,
      )}
    >
      <div className={cn("flex flex-col gap-0.5 text-caption", STATEMENT_INK_MUTED)}>
        {reference && <span>{reference}</span>}
        {generatedOn && <span>Generated on: {formatDateShort(generatedOn)}</span>}
      </div>
      <span className={cn("text-caption", STATEMENT_INK_MUTED)}>
        {pageLabel}
      </span>
    </div>
  );
}

// ---------------------------------------------------------------------------
// StatementLink
// ---------------------------------------------------------------------------

export interface StatementLinkProps {
  href: string;
  children: React.ReactNode;
  className?: string;
}

/**
 * A link on printed paper: underlined in the document's own ink rather than a
 * theme colour, so it survives being printed in black and white while still
 * resolving when the PDF is read on screen.
 */
export function StatementLink({ href, children, className }: StatementLinkProps) {
  return (
    <a
      href={href}
      target="_blank"
      rel="noreferrer"
      className={cn("underline underline-offset-2", STATEMENT_INK, className)}
    >
      {children}
    </a>
  );
}

// ---------------------------------------------------------------------------
// StatementComplianceFooter
// ---------------------------------------------------------------------------

export interface StatementComplianceParty {
  name?: string;
  abn?: string;
}

export interface StatementComplianceInfo {
  /** Pre-formatted date and time the data was current, e.g. "01 Aug 2026, 09:12". */
  dataCurrentAsAt?: string;
  consentProvidedBy?: string;
  dataHolder?: StatementComplianceParty;
  dataRecipient?: StatementComplianceParty;
  serviceProvider?: StatementComplianceParty;
  verificationReference?: string;
  /** Accreditation line, e.g. "Produced by ... CDR accreditation ADRBNK000208". */
  producedByLine?: string;
  /**
   * Public page where a recipient checks the verification reference, printed
   * without a scheme so it stays readable on paper (e.g. "wealthx.au/verify").
   */
  verifyUrl?: string;
  /**
   * Scannable code for `verifyUrl` plus the reference. Supplied by the
   * consumer so the design system carries no QR dependency, matching the
   * `qrCodeNode` slot on `TwoFASetupForm`.
   */
  verifyQrNode?: React.ReactNode;
  /** Issuer's website, printed without a scheme (e.g. "wealthx.au"). */
  websiteUrl?: string;
}

export interface StatementComplianceFooterProps extends StatementComplianceInfo {
  className?: string;
}

function ComplianceCell({
  label,
  children,
}: {
  label: string;
  children: React.ReactNode;
}) {
  return (
    <div
      className={cn("flex flex-col gap-1 border-t p-3", STATEMENT_RULE_LIGHT)}
    >
      <span className="text-caption font-semibold">{label}</span>
      <span className={cn("text-caption break-words", STATEMENT_INK_MUTED)}>
        {children}
      </span>
    </div>
  );
}

const partyLines = (party?: StatementComplianceParty) => (
  <>
    {party?.name || NO_DATA}
    {party?.abn && (
      <>
        <br />
        ABN: {party.abn}
      </>
    )}
  </>
);

/** The Consumer Data Right provenance block printed at the foot of a statement. */
export function StatementComplianceFooter({
  dataCurrentAsAt,
  consentProvidedBy,
  dataHolder,
  dataRecipient,
  serviceProvider,
  verificationReference,
  producedByLine,
  verifyUrl,
  verifyQrNode,
  websiteUrl,
  className,
}: StatementComplianceFooterProps) {
  return (
    <div
      data-slot="statement-compliance-footer"
      className={cn("flex flex-col border", STATEMENT_RULE, className)}
    >
      <div className="grid grid-cols-1 md:grid-cols-[1.5fr_1fr_1fr]">
        <div
          className={cn(
            "flex flex-col gap-2 border-t p-3 md:row-span-3 md:border-t-0",
            STATEMENT_RULE_LIGHT,
          )}
        >
          <span className="text-caption font-semibold">
            Consumer Data Right
          </span>
          <p className={cn("text-caption", STATEMENT_INK_MUTED)}>
            This statement has been generated using verified data obtained via
            the Consumer Data Right, an Australian Government regulated scheme.
          </p>
          <p className={cn("text-caption", STATEMENT_INK_MUTED)}>
            Data in this document is provided by {dataHolder?.name || NO_DATA}{" "}
            on behalf of {consentProvidedBy || NO_DATA}.
          </p>
          {producedByLine && (
            <p className={cn("text-caption", STATEMENT_INK_MUTED)}>
              {producedByLine}
            </p>
          )}
        </div>
        <ComplianceCell label="Data current as at">
          {dataCurrentAsAt || NO_DATA}
        </ComplianceCell>
        <ComplianceCell label="Consumer Data Right consent provided by">
          {consentProvidedBy || NO_DATA}
        </ComplianceCell>
        <ComplianceCell label="Accredited Data Holder">
          {partyLines(dataHolder)}
        </ComplianceCell>
        <ComplianceCell label="Accredited Data Recipient">
          {partyLines(dataRecipient)}
        </ComplianceCell>
        <ComplianceCell label="Service provider">
          {partyLines(serviceProvider)}
        </ComplianceCell>
        <ComplianceCell label="Verification reference">
          {verificationReference || NO_DATA}
        </ComplianceCell>
      </div>

      {verifyUrl && (
        <div
          className={cn(
            "flex items-center gap-4 border-t p-3",
            STATEMENT_RULE,
          )}
        >
          {verifyQrNode && <div className="shrink-0">{verifyQrNode}</div>}
          <div className="flex min-w-0 flex-col gap-1">
            <span className="text-caption font-semibold">
              Check this statement is genuine
            </span>
            <p className={cn("text-caption", STATEMENT_INK_MUTED)}>
              Scan the code, or visit{" "}
              <StatementLink href={`https://${verifyUrl}`}>
                {verifyUrl}
              </StatementLink>{" "}
              and enter the verification reference above. The check confirms who
              issued this document and that it has not been altered since. It
              does not show balances or transactions.
            </p>
          </div>
        </div>
      )}

      <div
        className={cn(
          "flex flex-col gap-2 border-t bg-[#f7f7f7] p-3",
          STATEMENT_RULE,
        )}
      >
        <p className={cn("text-caption", STATEMENT_INK_MUTED)}>
          This document has been generated using data provided under the terms
          of the Australian Consumer Data Right (CDR) by the specified financial
          institution. It may vary from their online banking portal or supplied
          documents in presentation, date range, sequence of transactions or
          specific data elements shown.
        </p>
        <div className="flex flex-wrap items-baseline justify-between gap-x-6 gap-y-1">
          <p className={cn("text-caption", STATEMENT_INK_MUTED)}>
            If you notice any errors or unauthorised transactions, please report
            them to your financial institution immediately.
          </p>
          {websiteUrl && (
            <StatementLink
              href={`https://${websiteUrl}`}
              className="ml-auto shrink-0"
            >
              {websiteUrl}
            </StatementLink>
          )}
        </div>
      </div>
    </div>
  );
}

// ---------------------------------------------------------------------------
// StatementField
// ---------------------------------------------------------------------------

export interface StatementFieldProps {
  label: string;
  /** Falsy values render as "Not available" so the row keeps its rhythm. */
  value?: React.ReactNode;
  /** Emphasise the value - used for balances the reader is looking for. */
  emphasis?: boolean;
  className?: string;
}

/** One label-left / value-right row inside a statement field group. */
export function StatementField({
  label,
  value,
  emphasis = false,
  className,
}: StatementFieldProps) {
  const isEmpty = value === undefined || value === null || value === "";

  return (
    <div
      data-slot="statement-field"
      className={cn("flex items-baseline justify-between gap-4", className)}
    >
      <span className="text-label-small shrink-0">{label}</span>
      <span
        className={cn(
          "min-w-0 break-words text-right",
          emphasis ? "text-label-medium" : "text-body-small",
          isEmpty && STATEMENT_INK_MUTED,
        )}
      >
        {isEmpty ? NO_DATA : value}
      </span>
    </div>
  );
}

// ---------------------------------------------------------------------------
// StatementFieldGroup
// ---------------------------------------------------------------------------

export interface StatementFieldGroupProps {
  /** Optional heading above the grid. */
  title?: string;
  children: React.ReactNode;
  /** One column instead of two - used inside the two-column page sections. */
  singleColumn?: boolean;
  className?: string;
}

/** Titled grid of `StatementField` rows. */
export function StatementFieldGroup({
  title,
  children,
  singleColumn = false,
  className,
}: StatementFieldGroupProps) {
  return (
    <div
      data-slot="statement-field-group"
      className={cn("flex flex-col gap-3", className)}
    >
      {title && <span className="text-label-medium">{title}</span>}
      <div
        className={cn(
          "grid gap-x-10 gap-y-2",
          singleColumn ? "grid-cols-1" : "grid-cols-1 md:grid-cols-2",
        )}
      >
        {children}
      </div>
    </div>
  );
}
