'use client';

import Link from 'next/link';
import type { Route } from 'next';
import { type ReactNode } from 'react';

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

interface ListCardProps {
  /** Detail-page URL the card navigates to when tapped. Omit to render a
   *  non-navigating card (audit log entries, read-only rows). */
  href?: string;
  /**
   * Optional Tailwind background class painted on a 3px vertical strip on the
   * left edge - used to encode pipeline stage / status / category at a glance.
   * Pass `undefined` for entities with no status to surface (clients, etc.).
   */
  accentClassName?: string;
  /**
   * Top-right action slot - typically a `<DropdownMenu>` for edit/archive.
   * Rendered absolutely-positioned outside the navigation Link so its clicks
   * don't trigger detail navigation.
   */
  actions?: ReactNode;
  ariaLabel: string;
  className?: string;
  children: ReactNode;
}

/**
 * Shared shell for every mobile list card. Wraps the body in a Link to the
 * detail page, paints an optional status accent bar on the left edge, and
 * exposes a top-right slot for an actions menu. Touch/hover feedback comes
 * from a soft brand-blue tint via `hover:bg-accent/40` + `active:bg-accent`,
 * no shadow shifts (which feel jittery on mobile).
 */
export function ListCard({
  href,
  accentClassName,
  actions,
  ariaLabel,
  className,
  children,
}: ListCardProps) {
  const innerClassName = cn(
    'block p-3',
    accentClassName && 'pl-4',
    'rounded-lg focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
  );

  return (
    <article
      className={cn(
        'group relative overflow-hidden rounded-lg border bg-card shadow-xs',
        'transition-colors hover:bg-accent/40 active:bg-accent',
        className,
      )}
    >
      {accentClassName ? (
        <span aria-hidden className={cn('absolute inset-y-0 left-0 w-1', accentClassName)} />
      ) : null}
      {href ? (
        <Link href={href as Route} aria-label={ariaLabel} className={innerClassName}>
          {children}
        </Link>
      ) : (
        <div aria-label={ariaLabel} className={innerClassName}>
          {children}
        </div>
      )}
      {actions ? <div className="absolute right-1.5 top-1.5">{actions}</div> : null}
    </article>
  );
}

interface ListCardAvatarProps {
  /** Two-letter initials (or one for single-word names). Caller derives. */
  initials?: string;
  /** Domain icon (Lucide). Used when the entity isn't a person - yacht, berth, company. */
  icon?: ReactNode;
  className?: string;
}

/**
 * 40px lead-slot avatar. Pass `initials` for people-shaped entities, or
 * `icon` for non-person entities (yachts, berths, companies, expenses).
 * Uses the brand-soft background so it reads as part of the marina aesthetic
 * rather than a generic Material avatar.
 */
export function ListCardAvatar({ initials, icon, className }: ListCardAvatarProps) {
  return (
    <div
      className={cn(
        'flex h-10 w-10 shrink-0 items-center justify-center rounded-full',
        'bg-brand-50 text-sm font-semibold tracking-tight text-brand',
        className,
      )}
    >
      {icon ?? initials ?? '?'}
    </div>
  );
}

interface ListCardMetaProps {
  /** Optional Lucide icon, rendered at 12px next to the text. */
  icon?: ReactNode;
  children: ReactNode;
  className?: string;
}

/**
 * Single inline meta segment: tiny icon (optional) + muted text. Compose
 * multiple segments inside a `<div className="flex flex-wrap items-center
 * gap-x-2 gap-y-0.5 text-xs text-muted-foreground">` to build the meta line.
 */
export function ListCardMeta({ icon, children, className }: ListCardMetaProps) {
  return (
    <span className={cn('inline-flex items-center gap-1', className)}>
      {icon ? <span className="shrink-0 text-muted-foreground/80">{icon}</span> : null}
      <span className="truncate">{children}</span>
    </span>
  );
}

/**
 * Derive 1–2 letter initials from a name, ignoring purely-numeric tokens
 * (so "Recovery Test 1777" → "RT", not "R1"). Returns "?" only for empty
 * input. Centralised here so every list card uses the same logic.
 */
export function deriveInitials(name: string): string {
  const alphaParts = name
    .trim()
    .split(/\s+/)
    .filter((p) => /^[A-Za-z]/.test(p));
  if (alphaParts.length === 0) return name.trim().slice(0, 1).toUpperCase() || '?';
  if (alphaParts.length === 1) return (alphaParts[0]?.[0] ?? '?').toUpperCase();
  return ((alphaParts[0]?.[0] ?? '') + (alphaParts[1]?.[0] ?? '')).toUpperCase();
}
