import {
  AppstoreOutlined,
  ArrowDownOutlined,
  ArrowUpOutlined,
  BorderVerticleOutlined,
  ColumnWidthOutlined,
  SplitCellsOutlined,
} from '@ant-design/icons';
import { Button, Card, Flex, Tag, Typography } from 'antd';
import { useMemo, useRef, useState } from 'react';
import type { SampleMeta } from '../../../widgets/core';
import { WindowUI } from '../WindowUI';
import type { WindowFrame } from '../types';

const { Paragraph, Text } = Typography;

export const sampleMeta: SampleMeta = {
  id: 'window-ui',
  componentId: 'window-ui',
  title: 'Window UI',
  description:
    '모달 스타일의 헤더 작업줄과 콘텐츠 영역을 가지며, 부모 영역 안에서 드래그/리사이즈/최소화/최대화가 가능한 윈도우 컴포넌트입니다.',
  category: 'Overlay',
  kind: 'feature',
  variantLabel: 'Showcase',
  order: 60,
  features: ['docs'],
};

type DemoWindow = {
  id: string;
  title: string;
  subtitle: string;
  tone: string;
  zIndex: number;
  frame: WindowFrame;
  tasks: string[];
};

type StageSize = {
  width: number;
  height: number;
};

function createDefaultWindows(): DemoWindow[] {
  return [
    {
      id: 'inventory-board',
      title: 'Inventory Board',
      subtitle: '입고 / 피킹 / 출고 현황',
      tone: 'blue',
      zIndex: 1,
      frame: { x: 24, y: 24, width: 420, height: 300 },
      tasks: ['입고 검수 대기 12건', '피킹 완료 대기 7건', '출고 마감 임박 3건'],
    },
    {
      id: 'dispatch-board',
      title: 'Dispatch Planner',
      subtitle: '배차 / 배송 계획',
      tone: 'green',
      zIndex: 2,
      frame: { x: 280, y: 96, width: 420, height: 280 },
      tasks: ['배차 미확정 5건', '긴급 배송 2건', '도착 지연 4건'],
    },
    {
      id: 'monitor-board',
      title: 'Ops Monitor',
      subtitle: '실시간 경보 / 작업 로그',
      tone: 'gold',
      zIndex: 3,
      frame: { x: 140, y: 250, width: 420, height: 260 },
      tasks: ['예외 이벤트 3건', '승인 대기 8건', '작업 메모 14건'],
    },
  ];
}

function arrangeHorizontally(previous: DemoWindow[], stageSize: StageSize): DemoWindow[] {
  const width = stageSize.width / previous.length;
  const height = stageSize.height;

  return previous.map((windowItem, index) => ({
    ...windowItem,
    frame: {
      x: index * width,
      y: 0,
      width,
      height,
    },
  }));
}

function arrangeVertically(previous: DemoWindow[], stageSize: StageSize): DemoWindow[] {
  const width = stageSize.width;
  const height = stageSize.height / previous.length;

  return previous.map((windowItem, index) => ({
    ...windowItem,
    frame: {
      x: 0,
      y: index * height,
      width,
      height,
    },
  }));
}

function arrangeGrid(previous: DemoWindow[], stageSize: StageSize): DemoWindow[] {
  const columns = 2;
  const rows = Math.ceil(previous.length / columns);
  const width = stageSize.width / columns;
  const height = stageSize.height / rows;

  return previous.map((windowItem, index) => {
    const column = index % columns;
    const row = Math.floor(index / columns);

    return {
      ...windowItem,
      frame: {
        x: column * width,
        y: row * height,
        width,
        height,
      },
    };
  });
}

function arrangeRecommended(previous: DemoWindow[], stageSize: StageSize): DemoWindow[] {
  const primaryWidth = stageSize.width * 0.62;
  const secondaryWidth = stageSize.width - primaryWidth;
  const topHeight = stageSize.height * 0.48;
  const bottomHeight = stageSize.height - topHeight;

  return [
    {
      ...previous[0],
      frame: { x: 0, y: 0, width: primaryWidth, height: stageSize.height },
    },
    {
      ...previous[1],
      frame: { x: primaryWidth, y: 0, width: secondaryWidth, height: topHeight },
    },
    {
      ...previous[2],
      frame: { x: primaryWidth, y: topHeight, width: secondaryWidth, height: bottomHeight },
    },
  ];
}

export function Sample() {
  const stageRef = useRef<HTMLDivElement>(null);
  const [windows, setWindows] = useState<DemoWindow[]>(() => createDefaultWindows());
  const [activeLayoutKey, setActiveLayoutKey] = useState<string | null>(null);

  const getStageSize = (): StageSize => {
    const rect = stageRef.current?.getBoundingClientRect();

    return {
      width: rect?.width ?? 1000,
      height: rect?.height ?? 560,
    };
  };

  const actionButtons = useMemo(
    () => [
      {
        key: 'recommended',
        label: '추천 배치',
        icon: <AppstoreOutlined />,
        apply: arrangeRecommended,
      },
      {
        key: 'horizontal',
        label: '가로 분할',
        icon: <ColumnWidthOutlined />,
        apply: arrangeHorizontally,
      },
      {
        key: 'vertical',
        label: '세로 분할',
        icon: <BorderVerticleOutlined />,
        apply: arrangeVertically,
      },
      {
        key: 'grid',
        label: '그리드',
        icon: <SplitCellsOutlined />,
        apply: arrangeGrid,
      },
    ],
    [],
  );

  const applyLayout = (layoutKey: string, nextWindows: DemoWindow[]) => {
    const selectedLayout = actionButtons.find((action) => action.key === layoutKey);

    if (!selectedLayout) {
      return nextWindows;
    }

    return selectedLayout.apply(nextWindows, getStageSize());
  };

  const moveWindow = (windowId: string, direction: 'up' | 'down') => {
    setWindows((previous) => {
      const currentIndex = previous.findIndex((item) => item.id === windowId);

      if (currentIndex < 0) {
        return previous;
      }

      const targetIndex = direction === 'up' ? currentIndex - 1 : currentIndex + 1;

      if (targetIndex < 0 || targetIndex >= previous.length) {
        return previous;
      }

      const reordered = [...previous];
      const [selectedWindow] = reordered.splice(currentIndex, 1);
      reordered.splice(targetIndex, 0, selectedWindow);

      return activeLayoutKey ? applyLayout(activeLayoutKey, reordered) : reordered;
    });
  };

  const activateWindow = (windowId: string) => {
    setWindows((previous) => {
      const highestZIndex = Math.max(...previous.map((item) => item.zIndex));

      return previous.map((item) =>
        item.id === windowId
          ? {
              ...item,
              zIndex: highestZIndex + 1,
            }
          : item,
      );
    });
  };

  return (
    <Card title="Window UI Sample" extra={<Text code>samples/Sample.tsx</Text>}>
      <Paragraph>
        헤더를 드래그하면 부모 영역 안에서 이동하고, 헤더 더블클릭 또는 우측 버튼으로 최대화/복원이
        가능합니다. 최소화 버튼은 작업줄 형태로 콘텐츠를 접고, 멀티 윈도우일 때는 추천 배치 버튼으로
        가로/세로/그리드 정렬도 가능합니다. 배치 후에는 아래 순서 편집 UI에서 창 순서를 다시 지정할 수
        있습니다.
      </Paragraph>

      <div className="window-ui-sample">
        <Flex wrap gap="small" className="window-ui-sample__actions">
          {actionButtons.map((action) => (
            <Button
              key={action.key}
              icon={action.icon}
              onClick={() => {
                setActiveLayoutKey(action.key);
                setWindows((previous) => applyLayout(action.key, previous));
              }}
            >
              {action.label}
            </Button>
          ))}
        </Flex>

        {activeLayoutKey ? (
          <Card size="small" title="배치 순서 편집">
            <Flex vertical gap="small">
              {windows.map((windowItem, index) => (
                <Flex key={windowItem.id} align="center" justify="space-between" gap="small">
                  <Flex align="center" gap="small">
                    <Tag color="blue">{index + 1}</Tag>
                    <Text strong>{windowItem.title}</Text>
                    <Text type="secondary">{windowItem.subtitle}</Text>
                  </Flex>
                  <Flex gap="small">
                    <Button
                      icon={<ArrowUpOutlined />}
                      disabled={index === 0}
                      onClick={() => {
                        moveWindow(windowItem.id, 'up');
                      }}
                    >
                      위로
                    </Button>
                    <Button
                      icon={<ArrowDownOutlined />}
                      disabled={index === windows.length - 1}
                      onClick={() => {
                        moveWindow(windowItem.id, 'down');
                      }}
                    >
                      아래로
                    </Button>
                  </Flex>
                </Flex>
              ))}
            </Flex>
          </Card>
        ) : null}

        <div ref={stageRef} className="window-ui-sample__stage">
          <div className="window-ui-sample__desktop" />

          {windows.map((windowItem) => (
            <WindowUI
              key={windowItem.id}
              title={windowItem.title}
              subtitle={windowItem.subtitle}
              frame={windowItem.frame}
              zIndex={windowItem.zIndex}
              onActivate={() => {
                activateWindow(windowItem.id);
              }}
              onFrameChange={(nextFrame) => {
                setWindows((previous) =>
                  previous.map((item) =>
                    item.id === windowItem.id ? { ...item, frame: nextFrame } : item,
                  ),
                );
              }}
            >
              <Flex vertical gap={14}>
                <Tag color={windowItem.tone}>{windowItem.title}</Tag>
                <Paragraph>
                  부모 컨테이너 안에서만 움직이도록 제한되어 있고, 추천 배치 버튼으로 여러 창을 빠르게
                  균등 분할할 수 있습니다.
                </Paragraph>
                <Card size="small" title="Active Tasks">
                  <Flex vertical gap={10}>
                    {windowItem.tasks.map((task) => (
                      <Text key={task}>{task}</Text>
                    ))}
                  </Flex>
                </Card>
                <Card size="small" title="Window Controls">
                  <Flex vertical gap={10}>
                    <Text>드래그: 헤더 작업줄</Text>
                    <Text>리사이즈: 모서리/변 가장자리</Text>
                    <Text>배치: 추천 / 가로 / 세로 / 그리드</Text>
                  </Flex>
                </Card>
              </Flex>
            </WindowUI>
          ))}
        </div>

        <div className="window-ui-sample__footer">
          <span>부모 기준 제한 이동</span>
          <span>최소화 / 최대화 / 복원 지원</span>
          <span>헤더 더블클릭 + 다중 창 균등 분할 지원</span>
        </div>
      </div>
    </Card>
  );
}
