import * as React from "react";

import { cn } from "@/lib/utils";

/**
 * Field descriptor for a {@link MobileCardRow}.
 *
 * The consuming page decides which fields to show and in what order; this
 * primitive does not pick them. Exactly one field should set `primary: true` —
 * it renders as the card title (bold, larger). The rest render as a key/value
 * stack below the title.
 */
export interface MobileCardField<T> {
	key: string;
	label: string;
	render: (row: T) => React.ReactNode;
	/** When true, render as the card title (bold, larger). One per card. */
	primary?: boolean;
}

export interface MobileCardRowProps<T> {
	rows: T[];
	fields: MobileCardField<T>[];
	/** Stable per-row identity; falls back to the row index when omitted. */
	getRowId?: (row: T) => string;
	/** When set, the whole card becomes a button (44px min height). */
	onRowClick?: (row: T) => void;
	/** Optional right-aligned action slot (edit/delete icon buttons). */
	actions?: (row: T) => React.ReactNode;
	/** Optional className for the outer list container. */
	className?: string;
}

/**
 * Stacked card list for wide tables below the `md:` breakpoint.
 *
 * Each row renders as a card: the `primary` field as the title and the
 * remaining fields as a key/value stack. When `onRowClick` is provided the
 * whole card is a button with a 44px minimum touch target (spec R6.1). An
 * optional `actions` slot renders right-aligned controls.
 *
 * This is the mobile counterpart to {@link DataTable}; pages branch on
 * `useIsMobile()`. See OpenSpec change `mobile-responsive-parity`, design
 * §`MobileCardRow`.
 */
export function MobileCardRow<T>({
	rows,
	fields,
	getRowId,
	onRowClick,
	actions,
	className,
}: MobileCardRowProps<T>) {
		const primary = fields.find((f) => f.primary);
		const rest = fields.filter((f) => !f.primary);

		return (
			<div className={cn("flex flex-col gap-2", className)}>
				{rows.map((row, index) => {
					const rowKey = getRowId?.(row) ?? String(index);
					const body = (
					<div className="flex items-start justify-between gap-3">
						<div className="flex min-w-0 flex-col gap-1">
							{primary ? (
								<div className="truncate text-sm font-medium text-foreground">
									{primary.render(row)}
								</div>
							) : null}
							{rest.length > 0 ? (
								<dl className="grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 text-xs text-muted-foreground">
									{rest.map((field) => (
										<React.Fragment key={field.key}>
											<dt className="font-medium text-muted-foreground">
												{field.label}
											</dt>
											<dd className="truncate text-foreground">
												{field.render(row)}
											</dd>
										</React.Fragment>
									))}
								</dl>
							) : null}
						</div>
						{actions ? (
							<div className="flex shrink-0 items-center gap-1">
								{actions(row)}
							</div>
						) : null}
					</div>
				);

				if (onRowClick) {
					return (
						<div
							key={rowKey}
							role="button"
							tabIndex={0}
							onClick={() => onRowClick(row)}
							onKeyDown={(e) => {
								if (e.key === "Enter" || e.key === " ") {
									e.preventDefault();
									onRowClick(row);
								}
							}}
							className="mobile-touch-target min-h-11 w-full cursor-pointer rounded-lg border border-border bg-card p-3 text-left transition-colors hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
						>
							{body}
						</div>
					);
				}

				return (
					<div
						key={rowKey}
						className="min-h-11 rounded-lg border border-border bg-card p-3"
					>
						{body}
					</div>
				);
			})}
		</div>
	);
}
