import type { RemitDetail } from "@/hooks/useRemitDetail";

type PartiesGridProps = {
  parties: NonNullable<RemitDetail["payer"]> | RemitDetail;
  /**
   * When true, render the remittance `payerName`/`claimId`-based party
   * identity even if the dedicated `payer`/`payee` blocks are absent
   * (the current backend `getRemittance` doesn't populate them). The
   * fallback is intentional: the spec asks for payer/payee cards but
   * the data path is still being built out, and we'd rather show a
   * partial card than omit the section.
   */
  fallbackName?: string;
};

/**
 * Loose address shape — the dedicated `payer.address` / `payee.address`
 * fields on `RemitDetail` are optional and may have any subset of the
 * 5-tuple populated, so we treat them as a record.
 */
type AddressLike = {
  line1?: string | null;
  line2?: string | null;
  city?: string | null;
  state?: string | null;
  zip?: string | null;
} | null | undefined;

/**
 * Address can come back as a populated record, `null`, or `undefined`.
 * Treat all three as "no address" so we don't render an empty card.
 */
function isEmptyAddress(addr: AddressLike): boolean {
  if (!addr) return true;
  return !addr.line1 && !addr.city && !addr.state && !addr.zip;
}

function AddressBlock({ address }: { address: NonNullable<AddressLike> }) {
  return (
    <div
      className="mt-1 border-t border-dashed border-[color:var(--m-border-heavy)]/30 pt-2 text-xs leading-relaxed text-[color:var(--m-ink-secondary)]"
      data-testid="party-address"
    >
      {address.line1 ? <div>{address.line1}</div> : null}
      {address.line2 ? <div>{address.line2}</div> : null}
      {(address.city || address.state || address.zip) ? (
        <div>
          {address.city ? `${address.city}, ` : ""}
          {address.state ?? ""} {address.zip ?? ""}
        </div>
      ) : null}
    </div>
  );
}

/**
 * Single party card: eyebrow label, name, identity mono line(s), and
 * an optional address block. Same visual idiom as
 * `ClaimDrawer.PartiesGrid`'s `PartyCard` so the two drawers feel like
 * one component family.
 */
function PartyCard({
  testId,
  label,
  name,
  identity,
  address,
}: {
  testId: string;
  label: string;
  name: React.ReactNode;
  identity: React.ReactNode;
  address?: AddressLike;
}) {
  return (
    <div
      data-testid={testId}
      className="flex flex-col gap-2 rounded-lg border border-[color:var(--m-border-heavy)]/30 bg-[color:var(--m-surface)]/60 px-4 py-3 transition-colors hover:border-[color:var(--m-border-heavy)]/50"
    >
      <span className="eyebrow text-[color:var(--m-ink-tertiary)]">
        {label}
      </span>
      <div className="display text-lg text-[color:var(--m-ink-primary)]">
        {name}
      </div>
      <div
        className="mono text-[12.5px] text-[color:var(--m-ink-secondary)] tabular-nums"
      >
        {identity}
      </div>
      {address && !isEmptyAddress(address) ? (
        <AddressBlock address={address as NonNullable<AddressLike>} />
      ) : null}
    </div>
  );
}

/**
 * Parties section of the remittance detail drawer.
 *
 * Two stacked cards on mobile (`grid-cols-1`), 2-up grid on desktop
 * (`md:grid-cols-2`). The payer card carries name + id + address; the
 * payee card carries name + NPI + address.
 *
 * The payer/payee blocks on `RemitDetail` are optional (the backend
 * `getRemittance` doesn't populate them yet), so when absent we fall
 * back to rendering a minimal card with the remittance's `payerName` /
 * `payerClaimControlNumber` / `claimId` so the section is never blank.
 * A follow-up backend change that wires `payer` / `payee` into the
 * detail endpoint will light up the full cards automatically — no
 * frontend changes required.
 */
export function PartiesGrid({ parties, fallbackName }: PartiesGridProps) {
  const payerBlock = "payer" in parties ? parties.payer : null;
  const payeeBlock = "payee" in parties ? parties.payee : null;

  // The "payer" identity lines. When the dedicated payer block exists,
  // surface the payer's id; otherwise show the PCN/claim id so the
  // user can still connect the remit to the underlying claim.
  const payerName = payerBlock?.name ?? fallbackName ?? "—";
  const payerIdentityLines: React.ReactNode[] = [];
  if (payerBlock?.id) {
    payerIdentityLines.push(<div key="id">ID {payerBlock.id}</div>);
  }
  if (
    "payerClaimControlNumber" in parties &&
    typeof parties.payerClaimControlNumber === "string" &&
    parties.payerClaimControlNumber
  ) {
    payerIdentityLines.push(
      <div key="pcn">PCN {parties.payerClaimControlNumber}</div>
    );
  }
  if (
    "claimId" in parties &&
    typeof parties.claimId === "string" &&
    parties.claimId
  ) {
    payerIdentityLines.push(<div key="claim">Claim {parties.claimId}</div>);
  }

  // The "payee" identity lines — NPI is the canonical identifier.
  const payeeName = payeeBlock?.name ?? "Provider";
  const payeeIdentityLines: React.ReactNode[] = [];
  if (payeeBlock?.npi) {
    payeeIdentityLines.push(<div key="npi">NPI {payeeBlock.npi}</div>);
  }

  return (
    <section
      className="flex flex-col gap-3 px-6 py-4"
      data-testid="parties-grid"
    >
      <h3
        data-testid="section-label"
        className="eyebrow text-[color:var(--m-ink-tertiary)]"
      >
        Parties
      </h3>

      <div
        data-testid="parties-grid-inner"
        className="grid grid-cols-1 md:grid-cols-2 gap-3"
      >
        <PartyCard
          testId="party-payer"
          label="Payer"
          name={payerName}
          identity={
            payerIdentityLines.length > 0 ? (
              <>{payerIdentityLines}</>
            ) : (
              <div className="text-[color:var(--m-ink-tertiary)]">
                No payer identity
              </div>
            )
          }
          address={payerBlock?.address ?? null}
        />

        <PartyCard
          testId="party-payee"
          label="Payee"
          name={payeeName}
          identity={
            payeeIdentityLines.length > 0 ? (
              <>{payeeIdentityLines}</>
            ) : (
              <div className="text-[color:var(--m-ink-tertiary)]">
                No NPI on file
              </div>
            )
          }
          address={payeeBlock?.address ?? null}
        />
      </div>
    </section>
  );
}
