import { ArrowLeftOutlined, CloseOutlined } from '@ant-design/icons';
import { Button, Card, Empty, Flex, Space, Typography } from 'antd';
import { createPortal } from 'react-dom';
import { useEffect, useState, type ReactNode } from 'react';

const { Title } = Typography;

type PlanListDetailLayoutProps = {
  listTitle: ReactNode;
  listExtra?: ReactNode;
  listContent: ReactNode;
  classNamePrefix?: string;
  desktopLayout?: 'split' | 'stacked';
  mobileLayoutMode?: 'overlay' | 'detail-only';
  desktopDetailOpen: boolean;
  mobileDetailOpen: boolean;
  detailTitle: ReactNode;
  detailActions?: ReactNode;
  detailContent: ReactNode;
  onCloseDetail: () => void;
  closeLabel?: string;
  showDesktopClose?: boolean;
  emptyDetailTitle?: ReactNode;
  emptyDetailContent?: ReactNode;
};

function useBodyScrollLock(locked: boolean) {
  useEffect(() => {
    if (typeof document === 'undefined' || !locked) {
      return;
    }

    const scrollY = window.scrollY;
    const previousBodyOverflow = document.body.style.overflow;
    const previousBodyTouchAction = document.body.style.touchAction;
    const previousBodyPosition = document.body.style.position;
    const previousBodyTop = document.body.style.top;
    const previousBodyWidth = document.body.style.width;
    const previousHtmlOverflow = document.documentElement.style.overflow;

    document.body.style.overflow = 'hidden';
    document.body.style.touchAction = 'manipulation';
    document.body.style.position = 'fixed';
    document.body.style.top = `-${scrollY}px`;
    document.body.style.width = '100%';
    document.documentElement.style.overflow = 'hidden';

    return () => {
      document.body.style.overflow = previousBodyOverflow;
      document.body.style.touchAction = previousBodyTouchAction;
      document.body.style.position = previousBodyPosition;
      document.body.style.top = previousBodyTop;
      document.body.style.width = previousBodyWidth;
      document.documentElement.style.overflow = previousHtmlOverflow;
      window.scrollTo(0, scrollY);
    };
  }, [locked]);
}

function useMobileOverlayEnabled() {
  const [mobileOverlayEnabled, setMobileOverlayEnabled] = useState(false);

  useEffect(() => {
    if (typeof window === 'undefined') {
      return;
    }

    const mediaQuery = window.matchMedia('(max-width: 960px)');
    const update = () => {
      setMobileOverlayEnabled(mediaQuery.matches);
    };

    update();
    mediaQuery.addEventListener('change', update);

    return () => {
      mediaQuery.removeEventListener('change', update);
    };
  }, []);

  return mobileOverlayEnabled;
}

export function PlanListDetailLayout({
  listTitle,
  listExtra,
  listContent,
  classNamePrefix = 'plan-board-page',
  desktopLayout = 'split',
  mobileLayoutMode = 'overlay',
  desktopDetailOpen,
  mobileDetailOpen,
  detailTitle,
  detailActions,
  detailContent,
  onCloseDetail,
  closeLabel = '뒤로가기',
  showDesktopClose = false,
  emptyDetailTitle = '상세 보기',
  emptyDetailContent,
}: PlanListDetailLayoutProps) {
  const mobileOverlayEnabled = useMobileOverlayEnabled();
  const showMobileDetail = mobileOverlayEnabled && mobileDetailOpen;
  const showMobileOverlay = showMobileDetail && mobileLayoutMode === 'overlay';
  const showMobileDetailOnly = showMobileDetail && mobileLayoutMode === 'detail-only';
  const hideInlineDetailCardOnMobile = mobileOverlayEnabled && (!showMobileDetail || showMobileOverlay);

  useBodyScrollLock(showMobileOverlay || showMobileDetailOnly);

  const resolvedEmptyDetailContent = emptyDetailContent ?? <Empty description="목록에서 항목을 선택하세요." />;
  const detailCardOpen = desktopDetailOpen;
  const detailCardTitle = detailCardOpen ? detailTitle : emptyDetailTitle;
  const detailCardContent = detailCardOpen ? detailContent : resolvedEmptyDetailContent;
  const detailCardActions = detailCardOpen ? detailActions : null;
  const splitClassName = `${classNamePrefix}__split${
    desktopLayout === 'stacked' ? ` ${classNamePrefix}__split--stacked` : ''
  }${showMobileDetailOnly ? ` ${classNamePrefix}__split--mobile-detail-only` : ''}`;
  const listCardClassName = `${classNamePrefix}__list-card${
    showMobileDetailOnly ? ` ${classNamePrefix}__list-card--mobile-hidden` : ''
  }`;
  const detailCardClassName = `${classNamePrefix}__editor-card ${classNamePrefix}__detail-card${
    hideInlineDetailCardOnMobile ? ` ${classNamePrefix}__detail-card--mobile-hidden` : ''
  }${showMobileDetailOnly ? ` ${classNamePrefix}__detail-card--mobile-only` : ''}`;
  const detailActionsClassName = `${classNamePrefix}__detail-actions`;
  const detailEmptyClassName = `${classNamePrefix}__detail-empty`;
  const overlayClassName = `${classNamePrefix}__overlay`;
  const overlayCardClassName = `${classNamePrefix}__overlay-card`;
  const overlayHeaderClassName = `${classNamePrefix}__overlay-header`;
  const overlayTitleClassName = `${classNamePrefix}__overlay-title`;
  const overlayBodyClassName = `${classNamePrefix}__overlay-body`;
  const mobileOverlayNode =
    showMobileOverlay && typeof document !== 'undefined'
      ? createPortal(
          <div className={overlayClassName}>
            <Card className={overlayCardClassName} bordered={false}>
              <Flex justify="space-between" align="center" gap={12} className={overlayHeaderClassName}>
                <Space>
                  <Button icon={<ArrowLeftOutlined />} onClick={onCloseDetail}>
                    {closeLabel}
                  </Button>
                  <Title level={5} className={overlayTitleClassName}>
                    {detailTitle}
                  </Title>
                </Space>

                {detailActions ? <Space wrap>{detailActions}</Space> : null}
              </Flex>

              <div className={overlayBodyClassName}>{detailContent}</div>
            </Card>
          </div>,
          document.body,
        )
      : null;

  return (
    <>
      <div className={splitClassName}>
        <Card title={listTitle} className={listCardClassName} extra={listExtra} bordered={false}>
          {listContent}
        </Card>

        <Card
          title={detailCardTitle}
          className={detailCardClassName}
          extra={
            detailCardOpen && (detailCardActions || showDesktopClose || showMobileDetailOnly) ? (
              <Space wrap className={detailActionsClassName}>
                {detailCardActions}
                {showMobileDetailOnly ? (
                  <Button icon={<ArrowLeftOutlined />} onClick={onCloseDetail}>
                    {closeLabel}
                  </Button>
                ) : null}
                {showDesktopClose && !showMobileDetailOnly ? (
                  <Button icon={<CloseOutlined />} onClick={onCloseDetail}>
                    닫기
                  </Button>
                ) : null}
              </Space>
            ) : null
          }
          bordered={false}
        >
          <div className={!detailCardOpen ? detailEmptyClassName : undefined}>{detailCardContent}</div>
        </Card>
      </div>

      {mobileOverlayNode}
    </>
  );
}
