import { AutoComplete, Input, Modal, Space, Tag, Typography } from 'antd';
import type { InputRef } from 'antd';
import { useEffect, useMemo, useRef, useState } from 'react';
import type { SearchKeywordOption } from './types';
import type { SearchOpenMode } from '../../layer/search/types';

const { Text, Title } = Typography;

export type SearchCommandModalProps = {
  open: boolean;
  options: SearchKeywordOption[];
  recentOptions?: SearchKeywordOption[];
  mode: SearchOpenMode;
  onClose: () => void;
  onSelectOption: (option: SearchKeywordOption) => void;
  title?: string;
  description?: string;
  placeholder?: string;
  submitHint?: string;
};

export function SearchCommandModal({
  open,
  options,
  recentOptions = [],
  mode,
  onClose,
  onSelectOption,
  title,
  description,
  placeholder,
  submitHint,
}: SearchCommandModalProps) {
  const inputRef = useRef<InputRef | null>(null);
  const [query, setQuery] = useState('');
  const [isMobileViewport, setIsMobileViewport] = useState(() => {
    if (typeof window === 'undefined') {
      return false;
    }

    return window.innerWidth <= 768;
  });

  useEffect(() => {
    if (!open) {
      setQuery('');
    }
  }, [open]);

  const submitOption = (option: SearchKeywordOption | undefined) => {
    if (!option) {
      return;
    }

    onSelectOption(option);
    onClose();
  };

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

    const mediaQuery = window.matchMedia('(max-width: 768px)');
    const updateViewport = () => {
      setIsMobileViewport(mediaQuery.matches);
    };

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

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

  const autoSuggestedOptionId = useMemo(() => {
    if (query.trim().length > 0) {
      return null;
    }

    return recentOptions[0]?.id ?? null;
  }, [query, recentOptions]);

  const filteredOptions = useMemo(() => {
    const normalizedQuery = query.trim().toLowerCase();

    const matchedOptions = normalizedQuery.length === 0
      ? [
          ...recentOptions.slice(0, 1),
          ...options.filter((option) => option.id !== recentOptions[0]?.id),
        ].slice(0, 8)
      : options.filter((option) => {
          const haystacks = [
            option.label,
            option.group,
            option.description ?? '',
            ...(option.keywords ?? []),
          ];

          return haystacks.some((value) => value.toLowerCase().includes(normalizedQuery));
        }).slice(0, 12);

    return matchedOptions.map((option) => ({
      value: option.id,
      label: (
        <Space direction="vertical" size={2} className="search-command__option">
          <Space size={8}>
            <Text strong>{option.label}</Text>
            <Tag>{option.group}</Tag>
            {option.id === autoSuggestedOptionId ? <Tag color="gold">자동 추천</Tag> : null}
          </Space>
          {option.description && !isMobileViewport ? (
            <Text type="secondary" className="search-command__option-copy">
              {option.description}
            </Text>
          ) : null}
        </Space>
      ),
    }));
  }, [autoSuggestedOptionId, isMobileViewport, options, query, recentOptions]);

  const visibleRecentOptions = useMemo(() => {
    if (query.trim().length > 0) {
      return [];
    }

    return recentOptions.slice(0, 4);
  }, [query, recentOptions]);

  return (
    <Modal
      open={open}
      footer={null}
      onCancel={onClose}
      forceRender
      keyboard
      maskClosable
      centered={false}
      width={minWidth()}
      className="search-command-modal"
      style={{ top: 18 }}
      styles={{ body: { padding: 18 } }}
      destroyOnClose
      afterOpenChange={(nextOpen) => {
        if (!nextOpen) {
          return;
        }

        window.requestAnimationFrame(() => {
          inputRef.current?.focus({
            cursor: 'all',
          });
          inputRef.current?.input?.focus();
        });
      }}
    >
      <Space direction="vertical" size={14} className="search-command">
        <div className="search-command__header">
          <Title level={4} className="search-command__title">
            {title ?? (mode === 'window' ? '윈도우 검색' : '통합 검색')}
          </Title>
          <Text type="secondary" className="search-command__description">
            {(isMobileViewport ? description?.split('.').filter(Boolean)[0] : description)
              ?? (mode === 'window'
                ? isMobileViewport ? '선택 항목을 창으로 엽니다.' : '선택한 항목을 Window UI 콘텐츠로 바로 엽니다.'
                : '키워드로 문서, API, 컴포넌트, 위젯을 빠르게 찾을 수 있습니다.')}
          </Text>
        </div>
        {visibleRecentOptions.length > 0 ? (
          <div className="search-command__recent">
            <Text type="secondary" className="search-command__recent-label">
              최근 실행 추천
            </Text>
            <div className="search-command__recent-actions">
              {visibleRecentOptions.map((option) => (
                <button
                  key={`recent-${option.id}`}
                  type="button"
                  className="search-command__recent-chip"
                  onClick={() => {
                    submitOption(option);
                  }}
                >
                  <Text strong>{option.label}</Text>
                  <Text type="secondary">{option.group}</Text>
                </button>
              ))}
            </div>
          </div>
        ) : null}
        <AutoComplete
          popupClassName="search-command__dropdown"
          className="search-command__autocomplete"
          options={filteredOptions}
          value={query}
          onSearch={setQuery}
          onChange={setQuery}
          onSelect={(value) => {
            submitOption(options.find((option) => option.id === value));
          }}
        >
          <Input
            id="app-search-command-input"
            ref={(element) => {
              inputRef.current = element;
            }}
            size="large"
            autoFocus
            placeholder={placeholder ?? '검색어를 입력하세요'}
            allowClear
            onPressEnter={() => {
              const firstOption = filteredOptions[0];
              submitOption(options.find((option) => option.id === firstOption?.value));
            }}
          />
        </AutoComplete>
        <Text type="secondary">
          {(isMobileViewport ? submitHint?.split('.').filter(Boolean)[0] : submitHint)
            ?? (mode === 'window'
              ? isMobileViewport ? '선택하면 창이 열립니다.' : '선택하거나 Enter를 누르면 Window UI 콘텐츠가 열립니다.'
              : '선택하거나 Enter를 누르면 바로 이동합니다.')}
        </Text>
      </Space>
    </Modal>
  );
}

function minWidth() {
  if (typeof window === 'undefined') {
    return 560;
  }

  return Math.min(560, window.innerWidth - 24);
}
