import type { LucideIcon } from 'lucide-react';
import type { ReactNode } from 'react';
import { Loader2, TriangleAlert } from 'lucide-react';
import { cn } from 'helpers/cn';

// Loading, failed, empty. See docs/design-language-interface.md § 6.
//
// These are the states a new user meets FIRST — before a single record exists, before a token is
// pasted, when something is misconfigured. Treating them as filler is how an app ends up saying "No
// results" to someone who cannot tell whether that means "nothing here" or "it is broken".
//
// One implementation, so all three agree on size, spacing and centring across every app. They fill
// their container rather than sitting at the top, because a half-empty pane with a line of grey text
// stuck to the ceiling reads as a rendering bug.

const Shell = ({ children, className }: { children: ReactNode; className?: string }) => (
  <div className={cn('flex h-full flex-col items-center justify-center gap-2 p-6 text-center', className)}>
    {children}
  </div>
);

export const LoadingBlock = ({ label = 'Loading…' }: { label?: string }) => (
  <Shell>
    <Loader2 className="h-5 w-5 animate-spin text-muted-foreground" />
    <p className="text-sm text-muted-foreground">{label}</p>
  </Shell>
);

/**
 * The real message is shown, not a friendly substitute for it. On a self-hosted platform the person
 * reading an error is almost always the person who can fix it, and "Something went wrong" costs them
 * the one clue they needed.
 */
export const ErrorBlock = ({ title, message, action }: { title: string; message?: ReactNode; action?: ReactNode }) => (
  <Shell>
    <TriangleAlert className="h-5 w-5 text-warning" />
    <div className="flex flex-col gap-1">
      <p className="text-base font-semibold">{title}</p>
      {message && <p className="max-w-sm text-sm text-muted-foreground">{message}</p>}
    </div>
    {action}
  </Shell>
);

/**
 * `hint` is not decoration — it is where the state says what WOULD be here and why it is not, which
 * is the difference between an empty state and a shrug.
 */
export const EmptyBlock = ({
  icon: Icon,
  title,
  hint,
  action,
}: {
  icon?: LucideIcon;
  title: string;
  hint?: ReactNode;
  action?: ReactNode;
}) => (
  <Shell>
    {Icon && (
      <div className="mb-1 flex h-10 w-10 items-center justify-center rounded-full bg-muted text-muted-foreground">
        <Icon className="h-5 w-5" />
      </div>
    )}
    <div className="flex flex-col gap-1">
      <p className="text-base font-semibold">{title}</p>
      {hint && <p className="max-w-sm text-sm text-muted-foreground">{hint}</p>}
    </div>
    {action}
  </Shell>
);
