import * as React from "react";
import Link from "next/link";
import { ExternalLink } from "lucide-react";
import { formatDateTime, formatNumber, truncateLink } from "@/lib/format";
import { cn } from "@/lib/utils";

/**
 * Server-rendered cell building blocks for <AdminTable>.
 *
 * These are plain (non-client) components: build them inside your server page
 * while mapping DB rows to `AdminRow.cells`. They already apply the dense admin
 * look — main value on top, muted secondary value underneath.
 */

const ALIGN: Record<string, string> = {
  left: "text-left",
  right: "text-right",
  center: "text-center",
};

/** The admin signature cell: primary value with a faded secondary line. */
export function Stacked({
  main,
  sub,
  align = "left",
  mono,
  className,
}: {
  main: React.ReactNode;
  sub?: React.ReactNode;
  align?: "left" | "right" | "center";
  mono?: boolean;
  className?: string;
}) {
  return (
    <div className={cn("leading-tight", ALIGN[align], className)}>
      <div className={cn("text-sm", mono && "font-mono tabular-nums")}>{main}</div>
      {sub === null || sub === undefined || sub === "" ? null : (
        <div
          className={cn(
            "mt-0.5 text-xs text-muted-foreground",
            mono && "font-mono tabular-nums",
          )}
        >
          {sub}
        </div>
      )}
    </div>
  );
}

/** Monospace inline value — IDs, amounts, keys. */
export function Mono({
  children,
  className,
}: {
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <span className={cn("font-mono text-sm tabular-nums", className)}>{children}</span>
  );
}

export function Muted({
  children,
  className,
}: {
  children: React.ReactNode;
  className?: string;
}) {
  return <span className={cn("text-xs text-muted-foreground", className)}>{children}</span>;
}

/** Em dash placeholder for empty values. */
export function Dash() {
  return <span className="text-muted-foreground">—</span>;
}

/** Numeric public id with an optional provider id underneath. */
export function IdCell({
  id,
  sub,
  href,
}: {
  id: React.ReactNode;
  sub?: React.ReactNode;
  href?: string;
}) {
  const main = href ? (
    <Link href={href} className="font-mono text-sm font-medium hover:underline">
      {id}
    </Link>
  ) : (
    <Mono className="font-medium">{id}</Mono>
  );
  return <Stacked main={main} sub={sub} />;
}

/** Pre-formatted money string (use `money()` from lib/serialize) + optional cost line. */
export function MoneyCell({
  value,
  sub,
  tone,
}: {
  value: string;
  sub?: React.ReactNode;
  tone?: "positive" | "negative" | "muted";
}) {
  return (
    <Stacked
      align="right"
      mono
      main={
        <span
          className={cn(
            "font-medium",
            tone === "positive" && "text-emerald-600 dark:text-emerald-400",
            tone === "negative" && "text-rose-600 dark:text-rose-400",
            tone === "muted" && "text-muted-foreground",
          )}
        >
          {value}
        </span>
      }
      sub={sub}
    />
  );
}

/** Right-aligned integer with thousands separators. */
export function NumberCell({
  value,
  sub,
  digits = 0,
}: {
  value: number | string | null | undefined;
  sub?: React.ReactNode;
  digits?: number;
}) {
  return <Stacked align="right" mono main={formatNumber(value, digits)} sub={sub} />;
}

/** ISO string in, "24 Aug 2026" + time underneath out. */
export function DateCell({
  value,
  sub,
}: {
  value: string | Date | null | undefined;
  sub?: React.ReactNode;
}) {
  if (!value) return <Dash />;
  const text = formatDateTime(value);
  const [day, time] = text.split(", ");
  return <Stacked main={<span className="text-sm">{day}</span>} sub={sub ?? time} />;
}

/** Order/service target link, shortened, opens in a new tab. */
export function LinkCell({
  href,
  label,
  max = 38,
}: {
  href: string | null | undefined;
  label?: string;
  max?: number;
}) {
  if (!href) return <Dash />;
  return (
    <a
      href={href}
      target="_blank"
      rel="noopener noreferrer nofollow"
      title={href}
      className="inline-flex max-w-[22rem] items-center gap-1 truncate text-sm text-blue-600 hover:underline dark:text-blue-400"
    >
      <span className="truncate">{label ?? truncateLink(href, max)}</span>
      <ExternalLink className="size-3 shrink-0 opacity-60" />
    </a>
  );
}

/** Username with email underneath, linking to the admin user page. */
export function UserCell({
  username,
  sub,
  href,
}: {
  username: string;
  sub?: React.ReactNode;
  href?: string;
}) {
  return (
    <Stacked
      main={
        href ? (
          <Link href={href} className="text-sm font-medium hover:underline">
            {username}
          </Link>
        ) : (
          <span className="text-sm font-medium">{username}</span>
        )
      }
      sub={sub}
    />
  );
}

/** Service badge: numeric id chip + name, provider underneath. */
export function ServiceCell({
  id,
  name,
  sub,
  href,
}: {
  id: number | string;
  name: string;
  sub?: React.ReactNode;
  href?: string;
}) {
  const body = (
    <span className="inline-flex max-w-[24rem] items-center gap-1.5">
      <span className="shrink-0 rounded bg-muted px-1.5 py-px font-mono text-[11px] text-muted-foreground tabular-nums">
        {id}
      </span>
      <span className="truncate text-sm">{name}</span>
    </span>
  );
  return (
    <Stacked
      main={
        href ? (
          <Link href={href} className="hover:underline">
            {body}
          </Link>
        ) : (
          body
        )
      }
      sub={sub}
    />
  );
}

/** Neutral chip for enum-ish values that are not statuses (mode, method, type). */
export function Chip({
  children,
  className,
}: {
  children: React.ReactNode;
  className?: string;
}) {
  return (
    <span
      className={cn(
        "inline-flex items-center rounded-md bg-muted px-1.5 py-0.5 text-[11px] font-medium whitespace-nowrap text-muted-foreground",
        className,
      )}
    >
      {children}
    </span>
  );
}

/** "3 / 10" progress pair used by drip-feed runs and subscription posts. */
export function RatioCell({
  done,
  total,
  sub,
}: {
  done: number;
  total: number;
  sub?: React.ReactNode;
}) {
  return (
    <Stacked
      mono
      align="right"
      main={
        <span>
          {formatNumber(done, 0)}
          <span className="text-muted-foreground"> / {formatNumber(total, 0)}</span>
        </span>
      }
      sub={sub}
    />
  );
}

export function BoolCell({ value }: { value: boolean }) {
  return value ? (
    <span className="text-sm text-emerald-600 dark:text-emerald-400">Yes</span>
  ) : (
    <span className="text-sm text-muted-foreground">No</span>
  );
}

/** Long free text (fail reasons, memos) clamped to one line with a tooltip. */
export function TextCell({
  value,
  max = 60,
}: {
  value: string | null | undefined;
  max?: number;
}) {
  if (!value) return <Dash />;
  const text = value.length > max ? `${value.slice(0, max - 1)}…` : value;
  return (
    <span title={value} className="text-sm">
      {text}
    </span>
  );
}
