"use client";

import * as React from "react";
import Link from "next/link";
import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon, type LucideIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLinkItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { cn } from "@/lib/utils";

/* ----------------------------------- Breadcrumbs ----------------------------------- */

/** A crumb with no href is a menu name (menus have no page of their own) and renders as plain text. */
export type Crumb = { label: string; href?: string };

/**
 * Breadcrumbs (spec 03 §5). The last crumb is the current page. Five or more crumbs keep the first and the
 * last two, with a "…" menu for the rest. `compact` (narrow screens) shows only a back link to the parent.
 */
export function Breadcrumbs({ items, compact = false }: { items: Crumb[]; compact?: boolean }) {
  const current = items[items.length - 1];
  const parents = items.slice(0, -1);

  if (compact) {
    const back = [...parents].reverse().find((c) => c.href);
    if (!back) return null;
    return (
      <nav aria-label="Breadcrumb">
        <Link href={back.href!} className="inline-flex items-center gap-1 text-[13px] leading-[18px] text-[var(--color-fg-secondary-strong,var(--muted-foreground))] underline-offset-2 hover:underline">
          <ChevronLeftIcon className="size-3.5" aria-hidden />
          {back.label}
        </Link>
      </nav>
    );
  }

  const truncate = items.length >= 5;
  const hidden = truncate ? parents.slice(1, -1) : [];
  const shown: (Crumb | "more")[] = truncate ? [parents[0], "more", parents[parents.length - 1]] : parents;

  return (
    <nav aria-label="Breadcrumb">
      <ol className="flex flex-wrap items-center gap-1 text-[13px] leading-[18px] text-[var(--color-fg-secondary-strong,var(--muted-foreground))]">
        {shown.map((c, i) => (
          <li key={i} className="inline-flex items-center gap-1">
            {c === "more" ? (
              <DropdownMenu>
                <DropdownMenuTrigger render={<Button variant="ghost" size="icon-xs" aria-label={`Show ${hidden.length} more breadcrumbs`} className="h-5 w-6" />}>
                  <MoreHorizontalIcon />
                </DropdownMenuTrigger>
                <DropdownMenuContent align="start">
                  <DropdownMenuGroup>
                    {hidden.map((h) =>
                      h.href ? (
                        <DropdownMenuLinkItem key={h.label} render={<Link href={h.href} />}>
                          {h.label}
                        </DropdownMenuLinkItem>
                      ) : (
                        <DropdownMenuItem key={h.label} disabled>
                          {h.label}
                        </DropdownMenuItem>
                      ),
                    )}
                  </DropdownMenuGroup>
                </DropdownMenuContent>
              </DropdownMenu>
            ) : c.href ? (
              <Link href={c.href} className="rounded-sm underline-offset-2 outline-none hover:underline focus-visible:ring-2 focus-visible:ring-ring">
                {c.label}
              </Link>
            ) : (
              <span>{c.label}</span>
            )}
            <ChevronRightIcon className="size-3.5 text-muted-foreground" aria-hidden />
          </li>
        ))}
        <li className="min-w-0">
          <span aria-current="page" className="block max-w-[32ch] truncate text-foreground">
            {current.label}
          </span>
        </li>
      </ol>
    </nav>
  );
}

/* ----------------------------------- Page header ----------------------------------- */

export type HeaderAction = {
  label: string;
  icon?: LucideIcon;
  href?: string;
  onSelect?: () => void;
  /** Only in the More menu: grouped last, in red. */
  destructive?: boolean;
  disabled?: boolean;
};

export type PageHeaderVariant = "standard" | "record" | "dashboard" | "wizard" | "compact";

function ActionButton({ action, variant }: { action: HeaderAction; variant: "default" | "outline" }) {
  const Icon = action.icon;
  const content = (
    <>
      {Icon ? <Icon data-icon="inline-start" /> : null}
      {action.label}
    </>
  );
  if (action.href) {
    return (
      <Button variant={variant} disabled={action.disabled} render={<Link href={action.href} />} nativeButton={false}>
        {content}
      </Button>
    );
  }
  return (
    <Button variant={variant} disabled={action.disabled} onClick={action.onSelect}>
      {content}
    </Button>
  );
}

function MoreMenu({ actions, title }: { actions: HeaderAction[]; title: string }) {
  const safe = actions.filter((a) => !a.destructive);
  const danger = actions.filter((a) => a.destructive);
  const item = (a: HeaderAction) => {
    const Icon = a.icon;
    const content = (
      <>
        {Icon ? <Icon /> : null}
        {a.label}
      </>
    );
    return a.href && !a.disabled ? (
      <DropdownMenuLinkItem key={a.label} render={<Link href={a.href} />}>
        {content}
      </DropdownMenuLinkItem>
    ) : (
      <DropdownMenuItem key={a.label} onClick={a.onSelect} disabled={a.disabled} variant={a.destructive ? "destructive" : "default"}>
        {content}
      </DropdownMenuItem>
    );
  };
  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="outline" aria-label={`More actions for ${title}`} />}>
        <MoreHorizontalIcon data-icon="inline-start" />
        More
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end" className="min-w-48">
        {safe.length ? <DropdownMenuGroup>{safe.map(item)}</DropdownMenuGroup> : null}
        {safe.length && danger.length ? <DropdownMenuSeparator /> : null}
        {danger.length ? <DropdownMenuGroup>{danger.map(item)}</DropdownMenuGroup> : null}
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

/**
 * Page header (spec 03 §6): the top of every page's content. Title, one-sentence description, a meta row
 * (branch · period · "As at" · status), at most one primary action (rightmost), up to two secondary
 * actions, and a More menu for the rest. Actions the role can't use are not passed in, and a secondary is
 * never promoted to primary when the primary is hidden (P3).
 *
 * Layout follows the header's own width (container queries, so it works inside a split pane or drawer and
 * never jumps on first paint): wide, actions sit right of the title; middling, secondary
 * actions fold into More rather than wrap; narrow, actions wrap below the title and breadcrumbs become a
 * back link.
 */
export function MedoraPageHeader({
  title,
  description,
  meta = [],
  metaLoading = false,
  status,
  breadcrumbs,
  primary,
  primaryNote,
  secondary = [],
  more = [],
  variant = "standard",
  className,
}: {
  title: string;
  description?: string;
  /** Meta items, separated by "·": branch, period, "As at 14:32", identifiers. */
  meta?: React.ReactNode[];
  /** "As at" isn't known yet: the meta row shows a skeleton after the known items. */
  metaLoading?: boolean;
  /** Record status badge (word + icon), shown first in the meta row. */
  status?: React.ReactNode;
  /** Level 3 and deeper pages only. */
  breadcrumbs?: Crumb[];
  primary?: HeaderAction;
  /** Said before the user starts, e.g. "Needs approval by an Admin". */
  primaryNote?: string;
  secondary?: HeaderAction[];
  more?: HeaderAction[];
  variant?: PageHeaderVariant;
  className?: string;
}) {
  const compact = variant === "compact";
  const wizard = variant === "wizard";

  // Widths come from container queries on the header (@2xl ≈ 672 px: actions beside the title;
  // @4xl ≈ 896 px: two secondaries fit inline). A single secondary always fits, so it never folds.
  // The More menu renders in a portal outside the container, so there are two triggers: one that includes
  // the folded secondaries (shown below @4xl) and one that doesn't.
  const secondaries = wizard ? [] : secondary.slice(0, 2);
  const foldable = secondaries.length === 2 ? secondaries : [];
  const inline = secondaries.length === 1 ? secondaries : [];
  const rest = wizard ? [] : [...secondary.slice(2), ...more];
  const folded = [...foldable, ...rest];
  const hasActions = !wizard && (!!primary || secondaries.length > 0 || rest.length > 0);
  const metaItems = [...(status ? [status] : []), ...meta];

  const actions = hasActions ? (
    <div className="flex shrink-0 flex-col items-start gap-1 @2xl:items-end">
      {/* Reading order: primary first when wrapped below the title; rightmost when beside it. */}
      <div className="flex flex-row-reverse flex-wrap items-center justify-end gap-2 @2xl:flex-row">
        {foldable.map((a) => (
          <span key={a.label} className="hidden @4xl:contents">
            <ActionButton action={a} variant="outline" />
          </span>
        ))}
        {inline.map((a) => (
          <ActionButton key={a.label} action={a} variant="outline" />
        ))}
        {/* Spec order (page header anatomy): secondaries, then More, then the primary */}
        {folded.length ? (
          <span className={cn("contents", foldable.length && "@4xl:hidden")}>
            <MoreMenu actions={folded} title={title} />
          </span>
        ) : null}
        {foldable.length && rest.length ? (
          <span className="hidden @4xl:contents">
            <MoreMenu actions={rest} title={title} />
          </span>
        ) : null}
        {primary ? <ActionButton action={primary} variant="default" /> : null}
      </div>
      {primary && primaryNote ? <p className="text-xs text-muted-foreground">{primaryNote}</p> : null}
    </div>
  ) : null;

  return (
    <header className={cn("@container space-y-2", className)}>
      {breadcrumbs?.length ? (
        <>
          <div className="hidden @2xl:block">
            <Breadcrumbs items={breadcrumbs} />
          </div>
          <div className="@2xl:hidden">
            <Breadcrumbs items={breadcrumbs} compact />
          </div>
        </>
      ) : null}
      <div className="flex flex-col gap-x-6 gap-y-3 @2xl:flex-row @2xl:items-start @2xl:justify-between">
        <div className="min-w-0 space-y-2">
          <h1
            className={cn(
              "text-foreground",
              compact ? "text-lg leading-6 font-semibold" : variant === "dashboard" ? "font-display text-display" : "font-display text-page-title",
            )}
          >
            {title}
          </h1>
          {description && !compact ? <p className="max-w-[720px] text-base text-[var(--color-fg-secondary-strong,var(--muted-foreground))]">{description}</p> : null}
          {metaItems.length || metaLoading ? (
            <div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-[13px] leading-[18px] text-muted-foreground tabular-nums">
              {metaItems.map((m, i) => (
                <React.Fragment key={i}>
                  {i > 0 ? <span aria-hidden>·</span> : null}
                  <span className="inline-flex items-center gap-1">{m}</span>
                </React.Fragment>
              ))}
              {metaLoading ? (
                <>
                  {metaItems.length ? <span aria-hidden>·</span> : null}
                  <span className="inline-block h-3.5 w-24 animate-pulse rounded-sm bg-muted" aria-label="Loading" />
                </>
              ) : null}
            </div>
          ) : null}
        </div>
        {actions}
      </div>
    </header>
  );
}
