// @design-system: domain/admin/ApprovalRow

/**
 * ApprovalRow — moderation queue row with preview slot, approve/reject buttons,
 * and an "open in moderation" link.
 *
 * Used in the unified approval inbox (B2.2).
 * RTL: logical props. Actions on end (left in RTL).
 * A11y: buttons are real <button>s; aria-labels include item title.
 *
 * i18n: approval_row namespace — keys: approve, reject, view_full, approving, rejecting.
 *
 * @example
 * ```tsx
 * <ApprovalRow
 *   id={item.id}
 *   title={item.title}
 *   subtitle={item.subtitle}
 *   type="deal"
 *   moderationHref={`/admin/moderation/deals/${item.id}`}
 *   onApprove={() => approveDeal(item.id)}
 *   onReject={() => rejectDeal(item.id)}
 *   preview={<Image src={item.imageUrl} alt={item.title} width={64} height={48} variant="thumb" />}
 * />
 * ```
 */

import { useState, type ReactNode } from 'react';
import { cn } from '@/lib/cn';
import { Icon } from '@/components/ui/icons/Icon';
import { useLocale, useT } from '@/lib/i18n/react';
import { dirForLocale } from '@/lib/i18n';

// ─── Types ────────────────────────────────────────────────────────────────────

export type ApprovalItemType = 'deal' | 'vendor' | 'image' | 'review' | 'report';

export interface ApprovalRowProps {
  /** Entity ID (used as React key by parent). */
  id: string;
  /** Primary display title. */
  title: string;
  /** Secondary/detail line. */
  subtitle?: string;
  /** Entity type badge label. */
  type: ApprovalItemType;
  /** Link to full moderation detail page. */
  moderationHref: string;
  /**
   * If provided, the "Open" action renders a `<button>` calling this handler
   * instead of an `<a href={moderationHref}>`. Use when the entity has no
   * standalone detail route and is previewed in a dialog/modal.
   */
  onOpen?: () => void;
  /** Called when approve button is clicked. */
  onApprove?: () => Promise<void> | void;
  /** Called when reject button is clicked. */
  onReject?: () => Promise<void> | void;
  /**
   * Preview slot — renders a thumbnail, image, or any preview content
   * on the start side of the row.
   */
  preview?: ReactNode;
  /**
   * AI badge slot — rendered under the subtitle.
   * Pass a pre-built ReactNode (e.g. decision pill + score) so the row stays
   * generic and image-specific logic stays in the parent feature.
   */
  aiBadge?: ReactNode;
  /** Additional className on the outer div. */
  className?: string;
}

// ─── Type color map ───────────────────────────────────────────────────────────

const TYPE_COLOR: Record<ApprovalItemType, string> = {
  deal: 'bg-brand-primary-100 text-brand-primary-700',
  vendor: 'bg-success-100 text-success-700',
  image: 'bg-neutral-100 text-neutral-700',
  review: 'bg-warning-100 text-warning-700',
  report: 'bg-danger-100 text-danger-700',
};

// ─── Component ────────────────────────────────────────────────────────────────

export function ApprovalRow({
  id: _id,
  title,
  subtitle,
  type,
  moderationHref,
  onOpen,
  onApprove,
  onReject,
  preview,
  aiBadge,
  className,
}: ApprovalRowProps) {
  const { locale } = useLocale();
  const dir = dirForLocale(locale);
  const tRow = useT('approval_row');
  const [approving, setApproving] = useState(false);
  const [rejecting, setRejecting] = useState(false);

  async function handleApprove() {
    if (!onApprove || approving || rejecting) return;
    setApproving(true);
    try {
      await onApprove();
    } finally {
      setApproving(false);
    }
  }

  async function handleReject() {
    if (!onReject || approving || rejecting) return;
    setRejecting(true);
    try {
      await onReject();
    } finally {
      setRejecting(false);
    }
  }

  const busy = approving || rejecting;

  return (
    <div
      className={cn(
        'flex items-center gap-3 px-4 py-3',
        'border-border-default border-b last:border-0',
        'bg-surface-base hover:bg-surface-raised transition-colors',
        className,
      )}
      dir={dir}
    >
      {/* Preview slot */}
      {preview && (
        <div className="shrink-0" aria-hidden="true">
          {preview}
        </div>
      )}

      {/* Text */}
      <div className="min-w-0 flex-1">
        <div className="flex items-center gap-2">
          <span
            className={cn(
              'inline-flex shrink-0 items-center rounded-full px-1.5 py-0.5 text-xs font-semibold',
              TYPE_COLOR[type],
            )}
          >
            {(tRow('types') as unknown as Record<ApprovalItemType, string>)[type]}
          </span>
          <span className="text-text-primary truncate text-sm font-semibold" data-user-content>
            {title}
          </span>
        </div>
        {subtitle && (
          <p className="text-text-secondary mt-0.5 truncate text-xs" data-user-content>
            {subtitle}
          </p>
        )}
        {aiBadge && <div className="mt-1">{aiBadge}</div>}
      </div>

      {/* Actions */}
      <div className="flex shrink-0 items-center gap-2">
        {/* Approve */}
        {onApprove && (
          <button
            type="button"
            onClick={handleApprove}
            disabled={busy}
            aria-label={`${tRow('approve')}: ${title}`}
            className={cn(
              'flex items-center gap-1 rounded-md px-2.5 py-1',
              'text-success-700 text-xs font-semibold',
              'bg-success-50 hover:bg-success-100',
              'transition-colors',
              'focus-visible:outline-success-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
              'disabled:cursor-not-allowed disabled:opacity-50',
            )}
          >
            <Icon name="Check" size="xs" aria-hidden />
            {approving ? tRow('approving') : tRow('approve')}
          </button>
        )}

        {/* Reject */}
        {onReject && (
          <button
            type="button"
            onClick={handleReject}
            disabled={busy}
            aria-label={`${tRow('reject')}: ${title}`}
            className={cn(
              'flex items-center gap-1 rounded-md px-2.5 py-1',
              'text-danger-700 text-xs font-semibold',
              'bg-danger-50 hover:bg-danger-100',
              'transition-colors',
              'focus-visible:outline-danger-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
              'disabled:cursor-not-allowed disabled:opacity-50',
            )}
          >
            <Icon name="X" size="xs" aria-hidden />
            {rejecting ? tRow('rejecting') : tRow('reject')}
          </button>
        )}

        {/* Open in moderation — button when onOpen is provided, link otherwise */}
        {onOpen ? (
          <button
            type="button"
            onClick={onOpen}
            aria-label={`${tRow('open_aria')}: ${title}`}
            className={cn(
              'flex items-center gap-1 rounded-md px-2.5 py-1',
              'text-text-secondary text-xs font-medium',
              'hover:bg-surface-raised hover:text-text-primary',
              'transition-colors',
              'focus-visible:outline-brand-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
            )}
          >
            <Icon name="Eye" size="xs" aria-hidden />
            <span className="hidden sm:inline">{tRow('open')}</span>
          </button>
        ) : (
          <a
            href={moderationHref}
            aria-label={`${tRow('open_aria')}: ${title}`}
            className={cn(
              'flex items-center gap-1 rounded-md px-2.5 py-1',
              'text-text-secondary text-xs font-medium',
              'hover:bg-surface-raised hover:text-text-primary',
              'transition-colors',
              'focus-visible:outline-brand-primary-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2',
            )}
          >
            <Icon name="Eye" size="xs" aria-hidden />
            <span className="hidden sm:inline">{tRow('open')}</span>
          </a>
        )}
      </div>
    </div>
  );
}
