import * as React from 'react';
import { clsx } from 'clsx';
import { Menu, X } from 'lucide-react';

type ShellStyle = React.CSSProperties & {
  '--bl-app-sidebar-width'?: string;
};

export interface AppShellProps extends React.HTMLAttributes<HTMLDivElement> {
  sidebarWidth?: number;
}

export function AppShell({
  sidebarWidth = 280,
  className,
  style,
  children,
  ...props
}: AppShellProps) {
  const shellStyle: ShellStyle = {
    '--bl-app-sidebar-width': `${sidebarWidth}px`,
    ...style,
  };

  return (
    <div
      className={clsx(
        'bl-app-shell min-h-screen bg-[var(--bl-bg-canvas)] text-[var(--bl-text-primary)]',
        className
      )}
      style={shellStyle}
      {...props}
    >
      <style>
        {`
          .bl-app-shell-mobile-toggle {
            display: inline-flex;
          }

          .bl-app-shell-overlay {
            display: none;
          }

          .bl-app-shell-overlay[data-open="true"] {
            display: block;
          }

          .bl-app-shell-sidebar {
            transform: translateX(-100%);
            transition: transform 200ms ease-out;
          }

          .bl-app-shell-sidebar[data-open="true"] {
            transform: translateX(0);
          }

          .bl-app-shell-main {
            padding: 4rem 1.25rem 1.25rem;
          }

          @media (min-width: 1024px) {
            .bl-app-shell-mobile-toggle,
            .bl-app-shell-overlay {
              display: none !important;
            }

            .bl-app-shell-sidebar {
              transform: translateX(0);
            }

            .bl-app-shell-main {
              padding: 2rem 2rem 2rem calc(var(--bl-app-sidebar-width, 280px) + 2rem);
            }
          }
        `}
      </style>
      {children}
    </div>
  );
}

export interface AppShellSkipLinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
  label?: string;
}

export function AppShellSkipLink({
  href = '#main-content',
  label = 'Skip to main content',
  className,
  children,
  ...props
}: AppShellSkipLinkProps) {
  return (
    <a
      href={href}
      className={clsx(
        'sr-only focus:not-sr-only focus:fixed focus:left-3 focus:top-3 focus:z-50',
        'focus:rounded-md focus:border focus:border-[var(--bl-accent)]',
        'focus:bg-[var(--bl-bg-elevated)] focus:px-4 focus:py-3 focus:text-sm',
        'focus:font-semibold focus:text-[var(--bl-accent)]',
        className
      )}
      {...props}
    >
      {children ?? label}
    </a>
  );
}

export interface AppShellMobileToggleProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  open: boolean;
  openLabel?: string;
  closeLabel?: string;
}

export function AppShellMobileToggle({
  open,
  openLabel = 'Open menu',
  closeLabel = 'Close menu',
  className,
  children,
  ...props
}: AppShellMobileToggleProps) {
  return (
    <button
      type="button"
      aria-label={open ? closeLabel : openLabel}
      className={clsx(
        'bl-app-shell-mobile-toggle fixed left-3 top-3 z-[38] h-10 w-10 items-center justify-center',
        'rounded-md border border-[var(--bl-border)] bg-[var(--bl-bg-elevated)]',
        'text-[var(--bl-text-primary)] shadow-sm transition-colors',
        'hover:bg-[var(--bl-surface-muted)] focus-visible:outline-none',
        'focus-visible:ring-2 focus-visible:ring-[var(--bl-accent)] lg:hidden',
        className
      )}
      {...props}
    >
      {children ??
        (open ? <X size={20} aria-hidden="true" /> : <Menu size={20} aria-hidden="true" />)}
    </button>
  );
}

export interface AppShellOverlayProps extends React.HTMLAttributes<HTMLDivElement> {
  open: boolean;
}

export function AppShellOverlay({ open, className, ...props }: AppShellOverlayProps) {
  return (
    <div
      aria-hidden="true"
      data-open={open ? 'true' : 'false'}
      className={clsx(
        'bl-app-shell-overlay fixed inset-0 z-[39] bg-[var(--bl-overlay-scrim,rgba(0,0,0,0.5))]',
        className
      )}
      {...props}
    />
  );
}

export interface AppShellSidebarProps extends React.HTMLAttributes<HTMLElement> {
  open: boolean;
  width?: number;
  label?: string;
}

export function AppShellSidebar({
  open,
  width = 280,
  label = 'Primary',
  className,
  style,
  children,
  ...props
}: AppShellSidebarProps) {
  return (
    <aside
      aria-label={label}
      data-open={open ? 'true' : 'false'}
      className={clsx(
        'bl-app-shell-sidebar fixed left-0 top-0 z-40 flex h-screen flex-col overflow-y-auto',
        'border-r border-[var(--bl-border)] bg-[var(--bl-surface-sidebar,var(--bl-bg-elevated))]',
        'transition-transform duration-200 ease-out lg:translate-x-0',
        className
      )}
      style={{
        width,
        minWidth: width,
        ...style,
      }}
      {...props}
    >
      {children}
    </aside>
  );
}

export interface AppShellMainProps extends React.HTMLAttributes<HTMLElement> {
  labelledBy?: string;
}

export function AppShellMain({
  id = 'main-content',
  labelledBy,
  className,
  style,
  children,
  ...props
}: AppShellMainProps) {
  return (
    <main
      id={id}
      tabIndex={-1}
      aria-labelledby={labelledBy}
      className={clsx('bl-app-shell-main min-h-screen min-w-0', className)}
      style={style}
      {...props}
    >
      <div className="grid gap-6">{children}</div>
    </main>
  );
}

export interface AppShellPageHeaderProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {
  title: React.ReactNode;
  description?: React.ReactNode;
  actions?: React.ReactNode;
  titleId?: string;
}

export function AppShellPageHeader({
  title,
  description,
  actions,
  titleId = 'page-title',
  className,
  children,
  ...props
}: AppShellPageHeaderProps) {
  return (
    <header className={className} {...props}>
      <div className="flex flex-wrap items-start justify-between gap-4 rounded-lg border border-[var(--bl-border)] bg-[var(--bl-surface-card)] p-6 shadow-sm">
        <div className="grid max-w-3xl gap-2">
          <h1
            id={titleId}
            className="m-0 font-[var(--bl-font-display,var(--font-display,inherit))] text-2xl font-bold"
          >
            {title}
          </h1>
          {description ? (
            <div className="text-sm leading-6 text-[var(--bl-text-secondary)]">{description}</div>
          ) : null}
          {children}
        </div>
        {actions ? <div aria-label="Page actions">{actions}</div> : null}
      </div>
    </header>
  );
}

export interface AppShellNavProps extends React.HTMLAttributes<HTMLElement> {
  label?: string;
}

export function AppShellNav({
  label = 'Primary navigation',
  className,
  children,
  ...props
}: AppShellNavProps) {
  return (
    <nav aria-label={label} className={clsx('grid gap-2', className)} {...props}>
      {children}
    </nav>
  );
}

export interface AppShellNavItemProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
  active?: boolean;
  icon?: React.ReactNode;
}

export function AppShellNavItem({
  active,
  icon,
  className,
  children,
  ...props
}: AppShellNavItemProps) {
  return (
    <a
      aria-current={active ? 'page' : undefined}
      className={clsx(
        'flex items-center gap-3 rounded-md border px-3.5 py-3 text-sm no-underline',
        'transition-colors focus-visible:outline-none focus-visible:ring-2',
        'focus-visible:ring-[var(--bl-accent)]',
        active
          ? 'border-[var(--bl-accent)] bg-[var(--bl-accent-muted)] text-[var(--bl-text-primary)]'
          : 'border-[var(--bl-border)] bg-[var(--bl-surface-muted)] text-[var(--bl-text-secondary)] hover:text-[var(--bl-text-primary)]',
        className
      )}
      {...props}
    >
      {icon ? (
        <span className="shrink-0" aria-hidden="true">
          {icon}
        </span>
      ) : null}
      <span>{children}</span>
    </a>
  );
}
