import { BellOutlined, ReloadOutlined } from '@ant-design/icons';
import { Alert, Badge, Button, Drawer, Empty, List, Modal, Segmented, Space, Spin, Tag, Typography } from 'antd';
import { useEffect, useRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import {
  type NotificationMessageItem,
  type NotificationMessageListStatus,
  type NotificationMessagePriority,
} from './notificationApi';
import { useNotificationController } from './chatV2/hooks/useNotificationController';
import './HeaderMessageCenter.css';

const { Paragraph, Text, Title } = Typography;
const SWIPE_DELETE_THRESHOLD_PX = 88;
const SWIPE_DELETE_LIMIT_PX = 132;
const TOUCH_TAP_SLOP_PX = 10;

function getNotificationLinkMetadata(metadata: Record<string, unknown> | null | undefined) {
  if (!metadata || typeof metadata !== 'object') {
    return null;
  }

  const linkUrl = typeof metadata.linkUrl === 'string' ? metadata.linkUrl.trim() : '';
  const linkLabel = typeof metadata.linkLabel === 'string' ? metadata.linkLabel.trim() : '';

  if (!linkUrl) {
    return null;
  }

  return {
    linkUrl,
    linkLabel: linkLabel || '바로가기',
  };
}

function formatDateTime(value: string | null) {
  if (!value) {
    return '-';
  }

  const date = new Date(value);

  if (Number.isNaN(date.getTime())) {
    return value;
  }

  return new Intl.DateTimeFormat('ko-KR', {
    dateStyle: 'medium',
    timeStyle: 'short',
  }).format(date);
}

function getPriorityTagColor(priority: NotificationMessagePriority) {
  switch (priority) {
    case 'urgent':
      return 'red';
    case 'high':
      return 'volcano';
    case 'low':
      return 'default';
    default:
      return 'blue';
  }
}

function getPriorityLabel(priority: NotificationMessagePriority) {
  switch (priority) {
    case 'urgent':
      return '긴급';
    case 'high':
      return '높음';
    case 'low':
      return '낮음';
    default:
      return '보통';
  }
}

function getMetadataText(metadata: Record<string, unknown> | null | undefined, key: string) {
  if (!metadata || typeof metadata !== 'object') {
    return '';
  }

  const value = metadata[key];
  return typeof value === 'string' ? value.trim() : '';
}

function getFirstMetadataText(metadata: Record<string, unknown> | null | undefined, keys: string[]) {
  for (const key of keys) {
    const value = getMetadataText(metadata, key);

    if (value) {
      return value;
    }
  }

  return '';
}

function extractChatDetailSections(message: NotificationMessageItem | null) {
  if (!message || message.category !== 'chat') {
    return null;
  }

  const questionText = getFirstMetadataText(message.metadata, ['questionText', 'userText', 'requestText', 'question']);
  const answerText = getFirstMetadataText(message.metadata, ['answerText', 'responseText', 'replyText', 'answer']);

  if (questionText || answerText) {
    return { questionText, answerText };
  }

  const bodyLines = String(message.body ?? '')
    .split('\n')
    .map((line) => line.trim())
    .filter(Boolean);

  const questionLine = bodyLines.find((line) => line.startsWith('질문:'));
  const answerLine = bodyLines.find((line) => line.startsWith('답변:'));

  const parsedQuestionText = questionLine ? questionLine.replace(/^질문:\s*/, '').trim() : '';
  const parsedAnswerText = answerLine ? answerLine.replace(/^답변:\s*/, '').trim() : '';

  if (!parsedQuestionText && !parsedAnswerText) {
    return null;
  }

  return {
    questionText: parsedQuestionText,
    answerText: parsedAnswerText,
  };
}

export function HeaderMessageCenter({ isMobileViewport }: { isMobileViewport: boolean }) {
  const navigate = useNavigate();
  const swipeStartXRef = useRef<number | null>(null);
  const swipeStartYRef = useRef<number | null>(null);
  const swipeLockedIdRef = useRef<number | null>(null);
  const swipeMovedRef = useRef(false);
  const touchScrollDetectedRef = useRef(false);
  const suppressClickRef = useRef(false);
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [swipedMessageId, setSwipedMessageId] = useState<number | null>(null);
  const [draggingMessageId, setDraggingMessageId] = useState<number | null>(null);
  const [dragOffsetX, setDragOffsetX] = useState(0);
  const {
    listStatus,
    setListStatus,
    unreadCount,
    detailOpen,
    setDetailOpen,
    messages,
    selectedMessage,
    listLoading,
    detailLoading,
    toggleReadLoading,
    deletingMessageId,
    listError,
    detailError,
    loadMessages,
    openMessageDetail,
    handleToggleReadState,
    handleDeleteMessage: deleteMessage,
  } = useNotificationController(drawerOpen);

  const listStatusOptions: Array<{ value: NotificationMessageListStatus; label: string }> = [
    { value: 'unread', label: `안읽음 ${unreadCount}` },
    { value: 'all', label: '전체' },
  ];

  const resetSwipeState = () => {
    swipeStartXRef.current = null;
    swipeStartYRef.current = null;
    swipeLockedIdRef.current = null;
    swipeMovedRef.current = false;
    touchScrollDetectedRef.current = false;
    setDraggingMessageId(null);
    setDragOffsetX(0);
  };

  const handleDeleteMessage = async (id: number) => {
    try {
      await deleteMessage(id);
      setSwipedMessageId((current) => (current === id ? null : current));
    } finally {
      resetSwipeState();
    }
  };

  const handleSwipeStart = (id: number, clientX: number, clientY: number) => {
    if (deletingMessageId === id) {
      return;
    }

    swipeStartXRef.current = clientX;
    swipeStartYRef.current = clientY;
    swipeLockedIdRef.current = id;
    swipeMovedRef.current = false;
    touchScrollDetectedRef.current = false;
    setDraggingMessageId(id);
    setDragOffsetX(0);
    setSwipedMessageId((current) => (current === id ? id : null));
  };

  const handleSwipeMove = (id: number, clientX: number, clientY: number) => {
    if (swipeLockedIdRef.current !== id || swipeStartXRef.current === null || swipeStartYRef.current === null) {
      return;
    }

    const deltaX = clientX - swipeStartXRef.current;
    const deltaY = clientY - swipeStartYRef.current;
    const absDeltaX = Math.abs(deltaX);
    const absDeltaY = Math.abs(deltaY);

    if (absDeltaY > TOUCH_TAP_SLOP_PX && absDeltaY > absDeltaX) {
      touchScrollDetectedRef.current = true;
      setSwipedMessageId(null);
      setDraggingMessageId(null);
      setDragOffsetX(0);
      return;
    }

    const nextOffset = deltaX >= 0 ? 0 : Math.max(deltaX, -SWIPE_DELETE_LIMIT_PX);
    if (Math.abs(nextOffset) >= 12) {
      swipeMovedRef.current = true;
      suppressClickRef.current = true;
    }
    setDraggingMessageId(id);
    setDragOffsetX(nextOffset);
  };

  const handleSwipeEnd = (id: number) => {
    if (swipeLockedIdRef.current !== id) {
      return false;
    }

    if (touchScrollDetectedRef.current) {
      resetSwipeState();
      setSwipedMessageId(null);
      window.setTimeout(() => {
        suppressClickRef.current = false;
      }, 0);
      return false;
    }

    const shouldDelete = dragOffsetX <= -SWIPE_DELETE_THRESHOLD_PX;
    const wasSwipeGesture = swipeMovedRef.current;
    resetSwipeState();

    if (shouldDelete) {
      void handleDeleteMessage(id);
      return false;
    }

    setSwipedMessageId(null);
    window.setTimeout(() => {
      suppressClickRef.current = false;
    }, 0);
    return !wasSwipeGesture;
  };

  const handleActivateMessage = (id: number) => {
    if (suppressClickRef.current || swipeMovedRef.current) {
      suppressClickRef.current = false;
      return;
    }

    if (draggingMessageId === id || swipedMessageId === id) {
      setSwipedMessageId(null);
      resetSwipeState();
      return;
    }

    void openMessageDetail(id);
  };

  const handleOpenLinkedPage = () => {
    const link = getNotificationLinkMetadata(selectedMessage?.metadata);

    if (!link || typeof window === 'undefined') {
      return;
    }

    try {
      const url = new URL(link.linkUrl, window.location.origin);

      if (url.origin === window.location.origin) {
        navigate(`${url.pathname}${url.search}${url.hash}`);
        setDetailOpen(false);
        setDrawerOpen(false);
        return;
      }
    } catch {
      // Fall through to full navigation for invalid or external urls.
    }

    window.location.assign(link.linkUrl);
  };

  useEffect(() => {
    if (!drawerOpen) {
      resetSwipeState();
      setSwipedMessageId(null);
    }
  }, [drawerOpen]);

  const selectedMessageLink = getNotificationLinkMetadata(selectedMessage?.metadata);
  const selectedChatDetail = extractChatDetailSections(selectedMessage);

  return (
    <>
      <Badge count={unreadCount} size="small" offset={[-2, 4]} className="header-message-center__badge">
        <Button
          type="text"
          className="header-message-center__trigger"
          icon={<BellOutlined />}
          aria-label="알림 메시지 열기"
          onClick={() => {
            setDrawerOpen(true);
          }}
        />
      </Badge>

      <Drawer
        title="수신 알림"
        placement="right"
        width={isMobileViewport ? '100%' : 420}
        open={drawerOpen}
        onClose={() => {
          setDrawerOpen(false);
        }}
        extra={
          <Button
            type="text"
            icon={<ReloadOutlined />}
            aria-label="알림 목록 새로고침"
            onClick={() => {
              void loadMessages();
            }}
          />
        }
      >
        <Space direction="vertical" size={12} style={{ width: '100%' }}>
          <div className="header-message-center__summary">
            <Text strong>{listStatus === 'unread' ? `안읽음 메시지 ${unreadCount}건` : '전체 알림 목록'}</Text>
            <Text type="secondary">최신순으로 최대 30건까지 표시합니다.</Text>
          </div>

          <Segmented
            block
            value={listStatus}
            options={listStatusOptions}
            className="header-message-center__tabs"
            onChange={(value) => {
              setListStatus(value as NotificationMessageListStatus);
            }}
          />

          {listError ? <Alert type="error" showIcon message={listError} /> : null}

          {listLoading ? (
            <div className="header-message-center__loading">
              <Spin />
            </div>
          ) : messages.length ? (
            <List
              itemLayout="vertical"
              dataSource={messages}
              renderItem={(item) => (
                <List.Item className={`header-message-center__item ${item.read ? '' : 'is-unread'}`}>
                  <div
                    className={`header-message-center__swipe ${swipedMessageId === item.id ? 'is-swiped' : ''} ${draggingMessageId === item.id ? 'is-dragging' : ''}`}
                  >
                    <button
                      type="button"
                      className="header-message-center__delete-action"
                      aria-label={`${item.title} 알림 삭제`}
                      disabled={deletingMessageId === item.id}
                      onClick={() => {
                        void handleDeleteMessage(item.id);
                      }}
                    >
                      {deletingMessageId === item.id ? '삭제 중' : '삭제'}
                    </button>
                    <button
                      type="button"
                      className="header-message-center__item-button"
                      style={{
                        transform:
                          draggingMessageId === item.id
                            ? `translateX(${dragOffsetX}px)`
                            : swipedMessageId === item.id
                              ? `translateX(-${SWIPE_DELETE_THRESHOLD_PX}px)`
                              : undefined,
                      }}
                      onTouchStart={(event) => {
                        handleSwipeStart(
                          item.id,
                          event.changedTouches[0]?.clientX ?? 0,
                          event.changedTouches[0]?.clientY ?? 0,
                        );
                      }}
                      onTouchMove={(event) => {
                        handleSwipeMove(
                          item.id,
                          event.changedTouches[0]?.clientX ?? 0,
                          event.changedTouches[0]?.clientY ?? 0,
                        );
                      }}
                      onTouchEnd={() => {
                        const shouldOpenDetail = handleSwipeEnd(item.id);

                        if (shouldOpenDetail) {
                          suppressClickRef.current = true;
                          void openMessageDetail(item.id);
                        }
                      }}
                      onTouchCancel={() => {
                        handleSwipeEnd(item.id);
                      }}
                      onClick={() => {
                        handleActivateMessage(item.id);
                      }}
                    >
                      <div className="header-message-center__item-header">
                        <Space size={8} wrap>
                          <Tag color={getPriorityTagColor(item.priority)}>{getPriorityLabel(item.priority)}</Tag>
                          <Tag>{item.category}</Tag>
                          {!item.read ? <Tag color="gold">안읽음</Tag> : null}
                        </Space>
                        <Text type="secondary" className="header-message-center__item-time">
                          {formatDateTime(item.createdAt)}
                        </Text>
                      </div>
                      <Title level={5} className="header-message-center__item-title" ellipsis={{ rows: 2 }}>
                        {item.title}
                      </Title>
                      <Paragraph className="header-message-center__item-preview" ellipsis={{ rows: 2 }}>
                        {item.preview}
                      </Paragraph>
                    </button>
                    <div className="header-message-center__swipe-hint">왼쪽으로 밀어 삭제</div>
                  </div>
                </List.Item>
              )}
            />
          ) : (
            <Empty description="수신된 알림이 없습니다." />
          )}
        </Space>
      </Drawer>

      <Modal
        title="알림 상세"
        open={detailOpen}
        width={isMobileViewport ? 'calc(100vw - 24px)' : 680}
        onCancel={() => {
          setDetailOpen(false);
        }}
        footer={[
          <Button key="open-link" disabled={!selectedMessageLink} onClick={handleOpenLinkedPage}>
            {selectedMessageLink?.linkLabel ?? '바로가기'}
          </Button>,
          <Button key="toggle-read" loading={toggleReadLoading} disabled={!selectedMessage} onClick={() => { void handleToggleReadState(); }}>
            {selectedMessage?.read ? '안읽음으로 변경' : '읽음 처리'}
          </Button>,
          <Button key="close" type="primary" onClick={() => { setDetailOpen(false); }}>
            닫기
          </Button>,
        ]}
      >
        {detailError ? <Alert type="error" showIcon message={detailError} style={{ marginBottom: 16 }} /> : null}

        {detailLoading ? (
          <div className="header-message-center__loading">
            <Spin />
          </div>
        ) : selectedMessage ? (
          <Space direction="vertical" size={16} style={{ width: '100%' }}>
            <Space size={8} wrap>
              <Tag color={getPriorityTagColor(selectedMessage.priority)}>
                {getPriorityLabel(selectedMessage.priority)}
              </Tag>
              <Tag>{selectedMessage.category}</Tag>
              <Tag>{selectedMessage.source}</Tag>
              <Tag color={selectedMessage.read ? 'green' : 'gold'}>
                {selectedMessage.read ? '읽음' : '안읽음'}
              </Tag>
            </Space>
            <div className="header-message-center__detail-meta">
              <Text type="secondary">수신 시각 {formatDateTime(selectedMessage.createdAt)}</Text>
              <Text type="secondary">확인 시각 {formatDateTime(selectedMessage.readAt)}</Text>
            </div>
            <Title level={4} style={{ margin: 0 }}>
              {selectedMessage.title}
            </Title>
            {selectedChatDetail ? (
              <Space direction="vertical" size={12} style={{ width: '100%' }}>
                {selectedChatDetail.questionText ? (
                  <div className="header-message-center__detail-section">
                    <Text type="secondary">요청내용</Text>
                    <Paragraph className="header-message-center__detail-body">
                      {selectedChatDetail.questionText}
                    </Paragraph>
                  </div>
                ) : null}
                {selectedChatDetail.answerText ? (
                  <div className="header-message-center__detail-section">
                    <Text type="secondary">답변</Text>
                    <Paragraph className="header-message-center__detail-body">
                      {selectedChatDetail.answerText}
                    </Paragraph>
                  </div>
                ) : null}
              </Space>
            ) : (
              <Paragraph className="header-message-center__detail-body">
                {selectedMessage.body}
              </Paragraph>
            )}
          </Space>
        ) : (
          <Empty description="표시할 알림이 없습니다." />
        )}
      </Modal>
    </>
  );
}
