import './system-window-dialog.css';

import * as React from 'react';
import { createPortal } from 'react-dom';

import {
  Maximize2,
  Minimize2,
  Minus,
  Square,
  X,
} from 'lucide-react';

import { cn } from '@/lib/utils';
import {
  getFloatingZ,
  getOverlayZ,
  getPanelZ,
  Z_FLOATING_BASE,
} from '@/lib/z-index';
import useAppConfigStore from '@/stores/appConfig';
import {
  type DesktopOS,
  detectDesktopOS,
} from '@/utils/detectDesktopOS';

// --- Size helpers ---

export type CssSize = number | string;

const DEFAULT_WIDTH = 'min(640px, calc(100vw - 2rem))';
const DEFAULT_HEIGHT = 'min(480px, calc(100vh - 2rem))';

const STACK_WINDOW_OFFSET = 24;
const STACK_TAB_LEFT_BASE = 16;
const STACK_TAB_WIDTH = 200;
const STACK_TAB_GAP = 8;
// --- Stack registry (multiple open dialogs) ---

type StackEntry = {
  stackIndex: number;
  open: boolean;
  isMinimized: boolean;
};

const stackRegistry = new Map<string, StackEntry>();
const stackListeners = new Set<() => void>();

function notifyStackListeners() {
  stackListeners.forEach((listener) => listener());
}

function updateStackRegistry(id: string, entry: StackEntry | null) {
  if (entry === null) {
    stackRegistry.delete(id);
  } else {
    stackRegistry.set(id, entry);
  }
  notifyStackListeners();
}

function getTopDialogId(): string | null {
  let topId: string | null = null;
  let topIndex = -1;

  for (const [id, entry] of stackRegistry) {
    if (!entry.open || entry.isMinimized) continue;
    if (entry.stackIndex >= topIndex) {
      topIndex = entry.stackIndex;
      topId = id;
    }
  }

  return topId;
}

function useDialogStackLayer(
  dialogId: string,
  stackIndex: number,
  open: boolean,
  isMinimized: boolean,
) {
  const [, bump] = React.useReducer((n: number) => n + 1, 0);

  React.useEffect(() => {
    const listener = () => bump();
    stackListeners.add(listener);
    return () => {
      stackListeners.delete(listener);
    };
  }, []);

  React.useEffect(() => {
    if (!open) {
      updateStackRegistry(dialogId, null);
      return;
    }

    updateStackRegistry(dialogId, { stackIndex, open, isMinimized });
    return () => updateStackRegistry(dialogId, null);
  }, [dialogId, stackIndex, open, isMinimized]);

  const topId = getTopDialogId();
  const isTop = open && !isMinimized && topId === dialogId;
  const hasHigherDialog = open && !isMinimized && topId != null && topId !== dialogId;

  return { isTop, hasHigherDialog };
}

export function toCssSize(value: CssSize | undefined, fallback: string): string {
  if (value === undefined) return fallback;
  if (typeof value === 'number') return `${value}px`;
  return value;
}

function useWindowSize(
  width: CssSize | undefined,
  height: CssSize | undefined,
  allowFullscreen: boolean,
  stackIndex: number,
) {
  const widthRef = React.useRef(toCssSize(width, DEFAULT_WIDTH));
  const heightRef = React.useRef(toCssSize(height, DEFAULT_HEIGHT));
  const [isFullscreen, setIsFullscreen] = React.useState(false);

  React.useEffect(() => {
    widthRef.current = toCssSize(width, DEFAULT_WIDTH);
    heightRef.current = toCssSize(height, DEFAULT_HEIGHT);
  }, [width, height]);

  const toggleFullscreen = React.useCallback(() => {
    if (!allowFullscreen) return;
    setIsFullscreen((prev) => !prev);
  }, [allowFullscreen]);

  const offset = Math.max(0, stackIndex) * STACK_WINDOW_OFFSET;

  // Offset via top/left (not transform) so zoom-in animation's
  // translate(-50%, -50%) does not fight the stack cascade and jump.
  const windowStyle: React.CSSProperties = isFullscreen
    ? {
      width: '100vw',
      height: '100vh',
      top: 0,
      left: 0,
      transform: 'none',
    }
    : {
      width: widthRef.current,
      height: heightRef.current,
      top: offset ? `calc(50% + ${offset}px)` : '50%',
      left: offset ? `calc(50% + ${offset}px)` : '50%',
      transform: 'translate(-50%, -50%)',
    };

  return {
    isFullscreen,
    toggleFullscreen,
    windowStyle,
    setIsFullscreen,
  };
}

// --- Context ---

type SystemWindowDialogContextValue = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  titleId: string;
  dialogId: string;
  isTop: boolean;
  hasHigherDialog: boolean;
  panelZIndex: number;
  floatingZIndex: number;
};

const SystemWindowDialogContext =
  React.createContext<SystemWindowDialogContextValue | null>(null);

export function useFloatingZIndex(): number {
  const ctx = React.useContext(SystemWindowDialogContext);
  return ctx?.floatingZIndex ?? Z_FLOATING_BASE;
}

function useSystemWindowDialogContext() {
  const ctx = React.useContext(SystemWindowDialogContext);
  if (!ctx) {
    throw new Error(
      'SystemWindowDialog components must be used within SystemWindowDialog',
    );
  }
  return ctx;
}

// --- Root ---

export type SystemWindowOsProp = 'mac' | 'win' | 'auto';

type SystemWindowDialogProps = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  children: React.ReactNode;
  className?: string;
  bodyClassName?: string;
  title?: string;
  footer?: React.ReactNode;
  width?: CssSize;
  height?: CssSize;
  allowFullscreen?: boolean;
  os?: SystemWindowOsProp;
  closeOnOverlayClick?: boolean;
  showCloseButton?: boolean;
  stackIndex?: number;
  allowMinimize?: boolean;
};

// Implementation moved below (wraps SystemWindowDialogContent)

// --- Title bars ---

type TitleBarProps = {
  title?: React.ReactNode;
  os: DesktopOS;
  isMobile: boolean;
  allowFullscreen: boolean;
  allowMinimize: boolean;
  isFullscreen: boolean;
  showCloseButton: boolean;
  onClose: () => void;
  onMinimize: () => void;
  onToggleFullscreen: () => void;
  titleId: string;
};

function MacTitleBar({
  title,
  allowFullscreen,
  allowMinimize,
  isFullscreen,
  showCloseButton,
  onClose,
  onMinimize,
  onToggleFullscreen,
  titleId,
}: Omit<TitleBarProps, 'os' | 'isMobile'>) {
  return (
    <div
      data-slot="system-window-titlebar"
      className="system-window-titlebar--mac relative flex h-7 shrink-0 items-center px-3 select-none"
    >
      <div className="flex items-center gap-2">
        {showCloseButton && (
          <button
            type="button"
            aria-label="Закрыть"
            className="system-window-traffic-light system-window-traffic-light--close system-window-traffic-light--active"
            onClick={onClose}
          />
        )}
        <button
          type="button"
          aria-label="Свернуть"
          disabled={!allowMinimize}
          className={cn(
            'system-window-traffic-light system-window-traffic-light--minimize',
            allowMinimize && 'system-window-traffic-light--active',
          )}
          onClick={allowMinimize ? onMinimize : undefined}
        />
        {allowFullscreen ? (
          <button
            type="button"
            aria-label={isFullscreen ? 'Восстановить размер' : 'На весь экран'}
            className="system-window-traffic-light system-window-traffic-light--maximize system-window-traffic-light--active"
            onClick={onToggleFullscreen}
          />
        ) : (
          <button
            type="button"
            aria-label="Развернуть"
            disabled
            className="system-window-traffic-light system-window-traffic-light--maximize"
          />
        )}
      </div>
      {title != null && (
        <div
          id={titleId}
          className="pointer-events-none absolute inset-0 flex items-center justify-center px-20 text-xs font-medium truncate text-foreground/80"
        >
          {title}
        </div>
      )}
    </div>
  );
}

function WinTitleBar({
  title,
  allowFullscreen,
  allowMinimize,
  isFullscreen,
  showCloseButton,
  onClose,
  onMinimize,
  onToggleFullscreen,
  titleId,
}: Omit<TitleBarProps, 'os' | 'isMobile'>) {
  return (
    <div
      data-slot="system-window-titlebar"
      className="system-window-titlebar--win flex h-7 shrink-0 items-center justify-between select-none"
    >
      <div
        id={titleId}
        className="flex min-w-0 flex-1 items-center gap-2 px-3 text-xs font-normal truncate"
      >
        {title}
      </div>
      <div className="flex shrink-0">
        <button
          type="button"
          aria-label="Свернуть"
          disabled={!allowMinimize}
          className={cn(
            'system-window-win-btn',
            allowMinimize && 'system-window-win-btn--active',
          )}
          onClick={allowMinimize ? onMinimize : undefined}
        >
          <Minus className="size-3.5" strokeWidth={1.5} />
        </button>
        {allowFullscreen ? (
          <button
            type="button"
            aria-label={isFullscreen ? 'Восстановить размер' : 'На весь экран'}
            className="system-window-win-btn system-window-win-btn--active"
            onClick={onToggleFullscreen}
          >
            {isFullscreen ? (
              <Minimize2 className="size-3" strokeWidth={1.5} />
            ) : (
              <Square className="size-2.5" strokeWidth={1.5} />
            )}
          </button>
        ) : (
          <button
            type="button"
            aria-label="Развернуть"
            disabled
            className="system-window-win-btn"
          >
            <Square className="size-2.5" strokeWidth={1.5} />
          </button>
        )}
        {showCloseButton && (
          <button
            type="button"
            aria-label="Закрыть"
            className="system-window-win-btn system-window-win-btn--close system-window-win-btn--active"
            onClick={onClose}
          >
            <X className="size-3.5" strokeWidth={1.5} />
          </button>
        )}
      </div>
    </div>
  );
}

function PlainTitleBar({
  title,
  allowFullscreen,
  allowMinimize,
  isFullscreen,
  showCloseButton,
  onClose,
  onMinimize,
  onToggleFullscreen,
  titleId,
}: Omit<TitleBarProps, 'os' | 'isMobile'>) {
  return (
    <div
      data-slot="system-window-titlebar"
      className="flex h-10 shrink-0 items-center justify-between border-b bg-muted/40 px-3 select-none"
    >
      <div
        id={titleId}
        className="min-w-0 flex-1 text-sm font-medium truncate pr-2"
      >
        {title}
      </div>
      <div className="flex shrink-0 items-center gap-1">
        {allowMinimize && (
          <button
            type="button"
            aria-label="Свернуть"
            className="inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
            onClick={onMinimize}
          >
            <Minus className="size-4" />
          </button>
        )}
        {allowFullscreen && (
          <button
            type="button"
            aria-label={isFullscreen ? 'Восстановить размер' : 'На весь экран'}
            className="inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
            onClick={onToggleFullscreen}
          >
            {isFullscreen ? (
              <Minimize2 className="size-4" />
            ) : (
              <Maximize2 className="size-4" />
            )}
          </button>
        )}
        {showCloseButton && (
          <button
            type="button"
            aria-label="Закрыть"
            className="inline-flex size-8 items-center justify-center rounded-md text-muted-foreground hover:bg-accent hover:text-foreground"
            onClick={onClose}
          >
            <X className="size-4" />
          </button>
        )}
      </div>
    </div>
  );
}

function SystemWindowTitleBar(props: TitleBarProps) {
  const { isMobile, os } = props;

  if (isMobile) {
    return <PlainTitleBar {...props} />;
  }

  if (os === 'mac') {
    return <MacTitleBar {...props} />;
  }

  if (os === 'win') {
    return <WinTitleBar {...props} />;
  }

  return <PlainTitleBar {...props} />;
}

// --- Minimized tab ---

type SystemWindowMinimizedTabProps = {
  title?: React.ReactNode;
  os: DesktopOS;
  isMobile: boolean;
  stackIndex: number;
  showCloseButton: boolean;
  onRestore: () => void;
  onClose: () => void;
};

function SystemWindowMinimizedTab({
  title,
  os,
  isMobile,
  stackIndex,
  showCloseButton,
  onRestore,
  onClose,
}: SystemWindowMinimizedTabProps) {
  const tabOs = isMobile ? 'plain' : os === 'mac' ? 'mac' : os === 'win' ? 'win' : 'plain';
  const left =
    STACK_TAB_LEFT_BASE +
    Math.max(0, stackIndex) * (STACK_TAB_WIDTH + STACK_TAB_GAP);

  return (
    <div
      data-slot="system-window-minimized-tab"
      className={cn(
        'system-window-minimized-tab',
        `system-window-minimized-tab--${tabOs}`,
      )}
      style={{
        left,
        width: STACK_TAB_WIDTH,
        zIndex: getPanelZ(stackIndex),
      }}
    >
      <button
        type="button"
        className="system-window-minimized-tab__restore"
        onClick={onRestore}
        aria-label="Развернуть окно"
      >
        <span className="truncate">{title ?? 'Окно'}</span>
      </button>
      {showCloseButton && (
        <button
          type="button"
          className="system-window-minimized-tab__close"
          aria-label="Закрыть"
          onClick={(e) => {
            e.stopPropagation();
            onClose();
          }}
        >
          <X className="size-3.5" strokeWidth={1.5} />
        </button>
      )}
    </div>
  );
}

// --- Compound parts ---

function SystemWindowDialogHeader({
  className,
  ...props
}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="system-window-header"
      className={cn('shrink-0', className)}
      {...props}
    />
  );
}

function SystemWindowDialogBody({
  className,
  ...props
}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="system-window-body"
      className={cn('flex-1 overflow-auto p-4', className)}
      {...props}
    />
  );
}

function SystemWindowDialogFooter({
  className,
  ...props
}: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="system-window-footer"
      className={cn(
        'flex shrink-0 flex-col-reverse gap-2 border-t px-4 py-3 sm:flex-row sm:justify-end',
        className,
      )}
      {...props}
    />
  );
}

// --- Content ---

type SystemWindowDialogContentProps = {
  children: React.ReactNode;
  className?: string;
  bodyClassName?: string;
  title?: React.ReactNode;
  footer?: React.ReactNode;
  width?: CssSize;
  height?: CssSize;
  allowFullscreen?: boolean;
  os?: SystemWindowOsProp;
  closeOnOverlayClick?: boolean;
  showCloseButton?: boolean;
  stackIndex?: number;
  allowMinimize?: boolean;
  isMinimized: boolean;
  setIsMinimized: (value: boolean) => void;
};

function resolveOs(osProp: SystemWindowOsProp, isMobile: boolean): DesktopOS {
  if (isMobile) return 'other';
  if (osProp === 'auto') return detectDesktopOS();
  return osProp;
}

function SystemWindowDialogContent({
  children,
  className,
  bodyClassName,
  title,
  footer,
  width,
  height,
  allowFullscreen = false,
  os: osProp = 'auto',
  closeOnOverlayClick = true,
  showCloseButton = true,
  stackIndex = 0,
  allowMinimize = false,
  isMinimized,
  setIsMinimized,
}: SystemWindowDialogContentProps) {
  const { onOpenChange, titleId, hasHigherDialog } =
    useSystemWindowDialogContext();
  const { isMobile } = useAppConfigStore();
  const panelRef = React.useRef<HTMLDivElement>(null);

  const os = resolveOs(osProp, isMobile);
  const { isFullscreen, toggleFullscreen, windowStyle, setIsFullscreen } =
    useWindowSize(width, height, allowFullscreen, stackIndex);

  const onClose = React.useCallback(() => {
    onOpenChange(false);
  }, [onOpenChange]);

  const onMinimize = React.useCallback(() => {
    if (!allowMinimize) return;
    setIsFullscreen(false);
    setIsMinimized(true);
  }, [allowMinimize, setIsFullscreen, setIsMinimized]);

  const onRestore = React.useCallback(() => {
    setIsMinimized(false);
  }, [setIsMinimized]);

  React.useEffect(() => {
    if (!isMinimized) {
      panelRef.current?.focus();
    }
  }, [isMinimized]);

  const roundedClass = isFullscreen
    ? 'rounded-none'
    : os === 'mac'
      ? 'rounded-xl'
      : 'rounded-lg';

  const panel = (
    <div
      ref={panelRef}
      role="dialog"
      aria-modal="true"
      aria-labelledby={title != null ? titleId : undefined}
      tabIndex={-1}
      data-slot="system-window-content"
      style={{
        ...windowStyle,
        zIndex: getPanelZ(stackIndex),
        display: isMinimized ? 'none' : undefined,
      }}
      className={cn(
        'system-window-dialog-panel bg-background fixed z-50 flex flex-col overflow-hidden border shadow-2xl outline-none',
        isFullscreen
          ? 'system-window-dialog-panel--fullscreen border-0'
          : 'border-black/10 dark:border-white/10',
        hasHigherDialog && 'system-window-dialog-panel--behind',
        roundedClass,
        className,
      )}
      onClick={(e) => e.stopPropagation()}
    >
      {hasHigherDialog && (
        <div
          className="system-window-dialog-panel__blocker"
          aria-hidden="true"
        />
      )}
      {(title != null || showCloseButton) && (
        <SystemWindowDialogHeader>
          <SystemWindowTitleBar
            title={title}
            os={os}
            isMobile={isMobile}
            allowFullscreen={allowFullscreen}
            allowMinimize={allowMinimize}
            isFullscreen={isFullscreen}
            showCloseButton={showCloseButton}
            onClose={onClose}
            onMinimize={onMinimize}
            onToggleFullscreen={toggleFullscreen}
            titleId={titleId}
          />
        </SystemWindowDialogHeader>
      )}

      <SystemWindowDialogBody className={bodyClassName}>{children}</SystemWindowDialogBody>

      {footer != null && (
        <SystemWindowDialogFooter>{footer}</SystemWindowDialogFooter>
      )}
    </div>
  );

  return createPortal(
    <div data-slot="system-window-portal">
      {!isMinimized && (
        <div
          data-slot="system-window-overlay"
          className="system-window-dialog-overlay fixed inset-0 bg-black/50 dark:bg-black/60 backdrop-blur-xs"
          style={{ zIndex: getOverlayZ(stackIndex) }}
          onClick={closeOnOverlayClick ? onClose : undefined}
          aria-hidden="true"
        />
      )}
      {panel}
      {isMinimized && allowMinimize && (
        <SystemWindowMinimizedTab
          title={title}
          os={os}
          isMobile={isMobile}
          stackIndex={stackIndex}
          showCloseButton={showCloseButton}
          onRestore={onRestore}
          onClose={onClose}
        />
      )}
    </div>,
    document.body,
  );
}

function SystemWindowDialog({
  open,
  onOpenChange,
  children,
  className,
  bodyClassName,
  title,
  footer,
  width,
  height,
  allowFullscreen = false,
  os = 'auto',
  closeOnOverlayClick = true,
  showCloseButton = true,
  stackIndex = 0,
  allowMinimize = false,
}: SystemWindowDialogProps) {
  const titleId = React.useId();
  const dialogId = React.useId();
  const [isMinimized, setIsMinimized] = React.useState(false);
  const { isTop, hasHigherDialog } = useDialogStackLayer(
    dialogId,
    stackIndex,
    open,
    isMinimized,
  );

  React.useEffect(() => {
    if (!open) {
      setIsMinimized(false);
    }
  }, [open]);

  React.useEffect(() => {
    if (!open || !isTop) return;

    const onKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        onOpenChange(false);
      }
    };

    document.addEventListener('keydown', onKeyDown);
    return () => document.removeEventListener('keydown', onKeyDown);
  }, [open, isTop, onOpenChange]);

  React.useEffect(() => {
    if (!open || isMinimized || !isTop) return;

    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      document.body.style.overflow = prevOverflow;
    };
  }, [open, isMinimized, isTop]);

  if (!open) return null;

  const panelZIndex = getPanelZ(stackIndex);
  const floatingZIndex = getFloatingZ(panelZIndex);

  return (
    <SystemWindowDialogContext.Provider
      value={{
        open,
        onOpenChange,
        titleId,
        dialogId,
        isTop,
        hasHigherDialog,
        panelZIndex,
        floatingZIndex,
      }}
    >
      <SystemWindowDialogContent
        className={className}
        bodyClassName={bodyClassName}
        title={title}
        footer={footer}
        width={width}
        height={height}
        allowFullscreen={allowFullscreen}
        allowMinimize={allowMinimize}
        os={os}
        closeOnOverlayClick={closeOnOverlayClick}
        showCloseButton={showCloseButton}
        stackIndex={stackIndex}
        isMinimized={isMinimized}
        setIsMinimized={setIsMinimized}
      >
        {children}
      </SystemWindowDialogContent>
    </SystemWindowDialogContext.Provider>
  );
}

export {
  SystemWindowDialog,
  SystemWindowDialogBody,
  SystemWindowDialogContent,
  SystemWindowDialogFooter,
  SystemWindowDialogHeader,
};
