import type { ReactNode } from "react";
import "./breadcrumbs.css";

export type BreadcrumbSeparator = "slash" | "chevron";
export type BreadcrumbStyle = "default" | "raised";

export type BreadcrumbItem = {
  label: string;
  href?: string;
  icon?: ReactNode;
  current?: boolean;
};

export type BreadcrumbsProps = {
  "aria-label"?: string;
  dir?: "ltr" | "rtl" | "auto";
  iconOnly?: boolean;
  items: BreadcrumbItem[];
  maxItems?: number;
  overflowLabel?: string;
  separator?: BreadcrumbSeparator;
  style?: BreadcrumbStyle;
};

type VisibleBreadcrumbItem = BreadcrumbItem & { overflow?: boolean };

function cx(...classes: Array<string | false | undefined>) {
  return classes.filter(Boolean).join(" ");
}

function visibleItems(
  items: BreadcrumbItem[],
  maxItems?: number,
  overflowLabel?: string,
): VisibleBreadcrumbItem[] {
  if (!maxItems || maxItems < 3 || items.length <= maxItems) {
    return items;
  }

  const tailCount = maxItems - 2;
  return [items[0], { label: overflowLabel ?? "", overflow: true }, ...items.slice(-tailCount)];
}

export function Breadcrumbs({
  "aria-label": ariaLabel,
  dir = "ltr",
  iconOnly = false,
  items,
  maxItems,
  overflowLabel,
  separator = "slash",
  style: surfaceStyle = "default",
}: BreadcrumbsProps) {
  const renderedItems = visibleItems(items, maxItems, overflowLabel);

  return (
    <nav
      aria-label={ariaLabel}
      className={cx(
        "ds-breadcrumbs",
        `ds-breadcrumbs--${surfaceStyle}`,
        `ds-breadcrumbs--${separator}`,
        iconOnly && "ds-breadcrumbs--icon-only",
      )}
      dir={dir}
    >
      <ol>
        {renderedItems.map((item, index) => {
          const isLast = index === renderedItems.length - 1;
          const isCurrent = item.current || isLast;
          const content = (
            <>
              <span className="ds-breadcrumbs__icon" aria-hidden={item.icon ? "true" : undefined}>
                {item.overflow ? <OverflowIcon /> : item.icon}
              </span>
              <span className={cx("ds-breadcrumbs__label", iconOnly && "ds-breadcrumbs__label--hidden")}>
                {item.label}
              </span>
            </>
          );

          return (
            <li key={`${item.label}-${index}`}>
              {index > 0 && <Separator separator={separator} />}
              {item.href && !isCurrent && !item.overflow ? (
                <a href={item.href}>{content}</a>
              ) : (
                <span aria-current={isCurrent ? "page" : undefined} className={isCurrent ? "is-current" : undefined}>
                  {content}
                </span>
              )}
            </li>
          );
        })}
      </ol>
    </nav>
  );
}

function Separator({ separator }: { separator: BreadcrumbSeparator }) {
  return (
    <span aria-hidden="true" className="ds-breadcrumbs__separator">
      {separator === "slash" ? "/" : <ChevronIcon />}
    </span>
  );
}

export function BreadcrumbHomeIcon() {
  return (
    <svg aria-hidden="true" viewBox="0 0 20 20">
      <path
        d="M3.5 8.7 10 3.4l6.5 5.3v7.1a.9.9 0 0 1-.9.9h-3.2v-4.9H7.6v4.9H4.4a.9.9 0 0 1-.9-.9V8.7Z"
        fill="none"
        stroke="currentColor"
        strokeLinejoin="round"
        strokeWidth="1.7"
      />
    </svg>
  );
}

export function BreadcrumbFolderIcon() {
  return (
    <svg aria-hidden="true" viewBox="0 0 20 20">
      <path
        d="M2.8 5.7c0-.9.7-1.6 1.6-1.6h3.8l1.5 1.8h5.9c.9 0 1.6.7 1.6 1.6v6.8c0 .9-.7 1.6-1.6 1.6H4.4c-.9 0-1.6-.7-1.6-1.6V5.7Z"
        fill="none"
        stroke="currentColor"
        strokeLinejoin="round"
        strokeWidth="1.7"
      />
    </svg>
  );
}

function ChevronIcon() {
  return (
    <svg aria-hidden="true" viewBox="0 0 16 16">
      <path d="m6 3.5 4 4.5-4 4.5" fill="none" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="1.6" />
    </svg>
  );
}

function OverflowIcon() {
  return (
    <svg aria-hidden="true" viewBox="0 0 20 20">
      <path
        d="M5.2 10h.1M10 10h.1M14.8 10h.1"
        fill="none"
        stroke="currentColor"
        strokeLinecap="round"
        strokeWidth="2.4"
      />
    </svg>
  );
}
