"use client";

import * as React from "react";
import { ArrowRightIcon, CircleXIcon, RotateCcwIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";

import { TONE_BOX } from "./tones";

/**
 * One changed field. Values are already formatted for people (KES 12.00, 20 Oct 2026, supplier names, not
 * ids). `sensitive` (passwords, credentials) shows "Changed" in both columns and never the values.
 * `long` text is stacked Before above After instead of side by side.
 */
export type FieldChange = { field: string; before?: string; after?: string; sensitive?: boolean; long?: boolean; line?: string };

export type DiffKind = "updated" | "created" | "deactivated";

/**
 * Diff view (spec 02 §9): what a change did, as Before → After, from an activity-log entry (ST-15, IN-08,
 * IN-18). Only changed fields are listed. Not coloured red/green: old and new aren't bad and good. Rows the
 * role can't see aren't rendered, and `hiddenCount` makes the list say so, so it isn't read as complete.
 */
export function DiffView({
  action,
  record,
  who,
  where,
  module,
  at,
  kind = "updated",
  changes,
  hiddenCount = 0,
  state = "ready",
  onRetry,
}: {
  action: string;
  record: string;
  who: string;
  where: string;
  module: string;
  at: string;
  kind?: DiffKind;
  changes: FieldChange[];
  hiddenCount?: number;
  state?: "ready" | "loading" | "error";
  onRetry?: () => void;
}) {
  const lines = changes.some((c) => c.line);
  const oneColumn = kind !== "updated";
  const valueHead = kind === "created" ? "Value" : kind === "deactivated" ? "Last value" : null;

  const empty = (
    <>
      <span aria-hidden>—</span>
      <span className="sr-only">None</span>
    </>
  );
  const after = (c: FieldChange) =>
    c.sensitive ? (
      "Changed"
    ) : c.after ? (
      <span className="inline-flex items-baseline gap-1.5 font-medium text-foreground">
        {!oneColumn ? <ArrowRightIcon className="size-3.5 shrink-0 self-center text-muted-foreground" aria-hidden /> : null}
        {c.after}
      </span>
    ) : (
      empty
    );
  const before = (c: FieldChange) => (c.sensitive ? "Changed" : c.before ? c.before : empty);

  return (
    <section className="space-y-3" aria-label={`${action}, ${record}`}>
      <header className="space-y-1">
        <h3 className="flex flex-wrap items-center gap-2 text-base font-semibold">
          {action} · {record}
          {kind === "created" ? <span className={cn("rounded-full border px-2 py-0.5 text-xs font-medium", TONE_BOX.info)}>Created</span> : null}
          {kind === "deactivated" ? <span className="rounded-full border border-border bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground">Deactivated</span> : null}
        </h3>
        <p className="text-[13px] text-muted-foreground">
          {who} · {where} · {module} · {at}
        </p>
      </header>

      {state === "error" ? (
        <div role="alert" className="flex flex-col items-center gap-2 rounded-lg border border-border py-6 text-center text-sm">
          <CircleXIcon className="size-5 text-status-error-text" aria-hidden />
          <p className="font-medium">We couldn&apos;t load the changes</p>
          <Button size="sm" variant="outline" onClick={onRetry}>
            <RotateCcwIcon data-icon="inline-start" />
            Try again
          </Button>
        </div>
      ) : state === "ready" && changes.length === 0 ? (
        <p className="rounded-lg border border-border px-3 py-4 text-sm text-muted-foreground">This action didn&apos;t change any fields.</p>
      ) : (
        <div className="overflow-hidden rounded-lg border border-[var(--color-border-panel)] bg-card">
          <table className="w-full border-collapse text-sm tabular-nums">
            <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
              <tr>
                {lines ? (
                  <th scope="col" className="px-3 py-2 font-medium">
                    Line
                  </th>
                ) : null}
                <th scope="col" className="px-3 py-2 font-medium">
                  Field
                </th>
                {oneColumn ? (
                  <th scope="col" className="px-3 py-2 font-medium">
                    {valueHead}
                  </th>
                ) : (
                  <>
                    <th scope="col" className="px-3 py-2 font-medium">
                      Before
                    </th>
                    <th scope="col" className="px-3 py-2 font-medium">
                      After
                    </th>
                  </>
                )}
              </tr>
            </thead>
            <tbody className="divide-y divide-[var(--color-border-subtle)]">
              {state === "loading"
                ? [0, 1, 2].map((i) => (
                    <tr key={i}>
                      {Array.from({ length: (lines ? 1 : 0) + (oneColumn ? 2 : 3) }, (_, j) => (
                        <td key={j} className="px-3 py-2.5">
                          <span className="block h-3.5 w-24 animate-pulse rounded-sm bg-muted" />
                        </td>
                      ))}
                    </tr>
                  ))
                : changes.map((c, i) =>
                    c.long && !oneColumn ? (
                      <tr key={i} className="align-top">
                        {lines ? <td className="px-3 py-2 text-muted-foreground">{c.line}</td> : null}
                        <th scope="row" className="px-3 py-2 text-left font-medium">
                          {c.field}
                        </th>
                        <td colSpan={2} className="space-y-1.5 px-3 py-2">
                          <p className="text-muted-foreground">
                            <span className="mr-1 text-xs font-medium">Before</span> {before(c)}
                          </p>
                          <p>
                            <span className="mr-1 text-xs font-medium text-muted-foreground">After</span>{" "}
                            {c.sensitive ? "Changed" : c.after ? <span className="font-medium text-foreground">{c.after}</span> : empty}
                          </p>
                        </td>
                      </tr>
                    ) : (
                      <tr key={i} className="align-top">
                        {lines ? <td className="px-3 py-2 text-muted-foreground">{c.line}</td> : null}
                        <th scope="row" className="px-3 py-2 text-left font-medium">
                          {c.field}
                        </th>
                        {kind === "created" ? (
                          <td className="px-3 py-2">{after(c)}</td>
                        ) : kind === "deactivated" ? (
                          <td className={cn("px-3 py-2 text-muted-foreground")}>{before(c)}</td>
                        ) : (
                          <>
                            <td className="px-3 py-2 text-muted-foreground">{before(c)}</td>
                            <td className="px-3 py-2">{after(c)}</td>
                          </>
                        )}
                      </tr>
                    ),
                  )}
            </tbody>
          </table>
        </div>
      )}
      {hiddenCount > 0 ? <p className="text-xs text-muted-foreground">Some changes are hidden because of your role.</p> : null}
    </section>
  );
}
