import type { InboxClaimRow, InboxCandidateRow, ScoreBreakdown } from "@/lib/inbox-api";
import { cn } from "@/lib/utils";

export type Accent = "oxblood" | "amber" | "ink-blue" | "muted";

const ACCENT_VAR: Record<Accent, string> = {
  oxblood: "var(--tt-oxblood)",
  amber: "var(--tt-amber)",
  "ink-blue": "var(--tt-ink-blue)",
  muted: "var(--tt-muted)",
};

const REJECT_CODES = new Set(["R", "E", "X"]);

function fmtMoney(n: number | null | undefined): string {
  if (n == null) return "—";
  return n.toLocaleString("en-US", { style: "currency", currency: "USD" });
}

function fmtAgo(iso: string | null | undefined): string {
  if (!iso) return "";
  const ms = Date.now() - new Date(iso).getTime();
  if (Number.isNaN(ms)) return "";
  const mins = Math.round(ms / 60_000);
  if (mins < 60) return `${mins}m`;
  const hrs = Math.round(mins / 60);
  if (hrs < 24) return `${hrs}h`;
  const days = Math.round(hrs / 24);
  return `${days}d`;
}

function Sparkline({ breakdown }: { breakdown: ScoreBreakdown | null }) {
  if (!breakdown) return null;
  const fields: Array<keyof ScoreBreakdown> = ["patient", "date", "amount", "provider"];
  return (
    <span className="inline-flex items-end gap-[2px] align-middle h-3.5">
      {fields.map((k) => {
        const v = breakdown[k] as number;
        const h = Math.max(3, Math.round(v * 14));
        return (
          <span
            key={k}
            title={`${k}: ${v.toFixed(2)}`}
            className={cn(
              "inline-block w-[3px] rounded-[1px] transition-all",
              v >= 0.7
                ? "bg-[color:var(--tt-amber)] shadow-[0_0_4px_-1px_var(--tt-amber)]"
                : v >= 0.5
                  ? "bg-[color:var(--tt-amber)]/70"
                  : "bg-[color:var(--tt-muted)]"
            )}
            style={{ height: `${h}px` }}
          />
        );
      })}
    </span>
  );
}

// ---------------------------------------------------------------------------
// SP29: per-AK2 chip (compact evidence row for the rejected-lane drill)
// ---------------------------------------------------------------------------
function AckCodeChip({
  setControlNumber,
  code,
}: {
  setControlNumber: string;
  code: string;
}) {
  const isReject = REJECT_CODES.has(code);
  return (
    <span
      className="inline-flex items-center gap-1 rounded-sm border px-1.5 py-0.5 mono tabular-nums"
      style={{
        fontSize: 9.5,
        letterSpacing: "0.04em",
        color: isReject ? "var(--tt-oxblood)" : "var(--tt-muted)",
        backgroundColor: isReject
          ? "rgba(229, 72, 77, 0.08)"
          : "rgba(220, 220, 230, 0.06)",
        borderColor: isReject
          ? "rgba(229, 72, 77, 0.28)"
          : "rgba(220, 220, 230, 0.20)",
        fontWeight: 600,
      }}
      title={`ST02 ${setControlNumber} · AK5 ${code}${isReject ? " (rejected)" : " (accepted)"}`}
    >
      <span style={{ opacity: 0.7 }}>{setControlNumber}</span>
      <span>·</span>
      <span style={{ fontWeight: 700 }}>{code || "—"}</span>
    </span>
  );
}

type Props = {
  row: InboxClaimRow | InboxCandidateRow;
  accent: Accent;
  onClick: () => void;
  /** SP29: per-row Resubmit gesture. Only meaningful for rejected
   *  claim rows; the component no-ops on remit rows or other states. */
  onResubmitOne?: (claimId: string) => void;
};

export function InboxRow({ row, accent, onClick, onResubmitOne }: Props) {
  const isCandidate = row.kind === "remit";
  const isRejected =
    !isCandidate && (row as InboxClaimRow).state === "rejected";
  const id = isCandidate ? (row as InboxCandidateRow).payer_claim_control_number : row.id;
  const payer = (isCandidate ? (row as InboxCandidateRow).payer_id : (row as InboxClaimRow).payer_id) ?? "";
  const charge = fmtMoney(row.charge_amount);
  const reason = !isCandidate ? (row as InboxClaimRow).rejection_reason : null;
  const rejectedAt = !isCandidate ? (row as InboxClaimRow).rejected_at : null;
  const topScore = isCandidate && row.candidates.length > 0 ? row.candidates[0].score : null;
  const filled = isCandidate && row.candidates.length > 0 ? row.candidates[0].breakdown : null;
  const claimAcks = !isCandidate ? (row as InboxClaimRow).claim_acks : null;

  return (
    <tr
      onClick={onClick}
      className="cursor-pointer transition-colors group"
    >
      <td
        aria-hidden
        style={{
          width: 4,
          background: ACCENT_VAR[accent],
          padding: 0,
          boxShadow: `inset 0 0 0 1px ${ACCENT_VAR[accent]}40`,
        }}
      />
      <td
        className="py-2.5 pl-3 mono font-semibold"
        style={{ color: "var(--tt-ink)", fontSize: 12, letterSpacing: "-0.005em" }}
      >
        {id}
      </td>
      <td
        className="py-2.5 mono"
        style={{ color: reason ? "var(--tt-oxblood)" : "var(--tt-amber)", fontSize: 11 }}
      >
        <div className="flex flex-col gap-1">
          <span>{reason ?? (topScore != null ? `score ${topScore}` : "")}</span>
          {/* SP29: rejected-lane AK2 chip evidence (newest 3 + overflow). */}
          {isRejected && claimAcks && claimAcks.items.length > 0 && (
            <span className="inline-flex items-center gap-1 flex-wrap">
              {claimAcks.items.slice(0, 3).map((it) => (
                <AckCodeChip
                  key={`${it.ack_id}-${it.ak2_index}`}
                  setControlNumber={it.set_control_number}
                  code={it.set_accept_reject_code}
                />
              ))}
              {claimAcks.total > 3 && (
                <span
                  className="inline-flex items-center rounded-sm border px-1.5 py-0.5 mono tabular-nums"
                  style={{
                    fontSize: 9.5,
                    letterSpacing: "0.04em",
                    color: "var(--tt-muted)",
                    borderColor: "rgba(220, 220, 230, 0.20)",
                    backgroundColor: "rgba(220, 220, 230, 0.04)",
                    fontWeight: 600,
                  }}
                  title={`${claimAcks.total - 3} more AK2 set-response(s) on the ClaimDrawer`}
                >
                  +{claimAcks.total - 3} more
                </span>
              )}
            </span>
          )}
          {/* SP29: rejected claim but no linked 999 acks (orphan). */}
          {isRejected && (!claimAcks || claimAcks.items.length === 0) && (
            <span
              className="mono italic"
              style={{ fontSize: 10, color: "var(--tt-muted)", opacity: 0.75 }}
              title="No 999 AK2 set-responses are linked to this claim. The set_control_number on the 999 ack had no matching ST02 batch. Use the Inbox ack-orphans lane to manually match."
            >
              999 not linked
            </span>
          )}
        </div>
      </td>
      <td
        className="py-2.5 mono tabular-nums"
        style={{ color: "var(--tt-ink-dim)", fontSize: 11 }}
      >
        {fmtAgo(rejectedAt)}
      </td>
      <td
        className="py-2.5 text-right mono tabular-nums font-semibold"
        style={{ color: "var(--tt-ink)", fontSize: 12 }}
      >
        {charge}
      </td>
      <td
        className="py-2.5 pl-4 mono uppercase"
        style={{ color: "var(--tt-ink-dim)", fontSize: 10, letterSpacing: "0.14em" }}
      >
        {payer}
      </td>
      <td className="py-2.5 pr-3">
        <Sparkline breakdown={filled} />
      </td>
      {/* SP29: per-row Resubmit button (rejected-lane only). */}
      {isRejected && onResubmitOne ? (
        <td
          className="py-2.5 pr-3 text-right"
          onClick={(e) => e.stopPropagation()}
        >
          <button
            type="button"
            className="mono uppercase tracking-[0.12em] px-2 py-1 rounded-sm transition-colors hover:bg-[color:var(--tt-amber)]/10 focus-visible:outline-none focus-visible:bg-[color:var(--tt-amber)]/10"
            style={{
              color: "var(--tt-amber)",
              border: "1px solid rgba(229, 154, 50, 0.40)",
              backgroundColor: "transparent",
              fontSize: 10,
              fontWeight: 700,
            }}
            data-testid={`resubmit-${id}`}
            onClick={(e) => {
              e.stopPropagation();
              onResubmitOne(id);
            }}
            title="Download the corrected 837 for this single claim"
          >
            Resubmit
          </button>
        </td>
      ) : (
        <td className="py-2.5 pr-3" aria-hidden />
      )}
    </tr>
  );
}
