import { cn } from '@documenso/ui/lib/utils';
import { ChevronDownIcon } from 'lucide-react';
import { createContext, type ReactNode, useContext, useEffect, useId, useState } from 'react';

type EnvelopeEditorPanelProps = {
  children: ReactNode;
  title: ReactNode;
  side: 'left' | 'right';
  compact?: boolean;
  revealKey?: string | number;
  testId: string;
};

const PanelContext = createContext<{
  openPanel: string | null;
  setOpenPanel: (id: string | null) => void;
} | null>(null);

export const EnvelopeEditorPanelProvider = ({ children }: { children: ReactNode }) => {
  const [openPanel, setOpenPanel] = useState<string | null>(null);
  return <PanelContext.Provider value={{ openPanel, setOpenPanel }}>{children}</PanelContext.Provider>;
};

/** Keep tools in document flow on small screens, with full sidebars on desktop. */
export const EnvelopeEditorPanel = ({
  children,
  title,
  side,
  compact,
  revealKey,
  testId,
}: EnvelopeEditorPanelProps) => {
  const panels = useContext(PanelContext);
  if (!panels) {
    throw new Error('EnvelopeEditorPanel requires EnvelopeEditorPanelProvider');
  }
  const { openPanel, setOpenPanel } = panels;
  const open = openPanel === testId;
  const contentId = useId();

  useEffect(() => {
    if (revealKey !== undefined) {
      setOpenPanel(testId);
    }
  }, [revealKey, testId, setOpenPanel]);

  return (
    <aside
      data-testid={testId}
      className={cn(
        'flex w-full min-w-0 shrink-0 flex-col border-border border-b bg-background lg:h-full lg:w-80 lg:border-b-0',
        side === 'left' ? 'lg:border-r' : 'order-first lg:order-last lg:border-l',
        compact && 'lg:w-14',
      )}
    >
      <button
        type="button"
        aria-expanded={open}
        aria-controls={contentId}
        data-testid={`${testId}-toggle`}
        onClick={() => setOpenPanel(open ? null : testId)}
        className="flex min-h-11 w-full items-center justify-between gap-3 px-4 py-2 text-left font-medium text-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-primary lg:hidden"
      >
        {title}
        <ChevronDownIcon aria-hidden className={cn('size-4 shrink-0', open && 'rotate-180')} />
      </button>
      <div
        id={contentId}
        className={cn('max-h-[35dvh] min-h-0 overflow-y-auto lg:h-full lg:max-h-none', !open && 'hidden lg:block')}
      >
        {children}
      </div>
    </aside>
  );
};
