import { useEffect, useMemo, useRef, useState, type CSSProperties } from 'react';
import {
  clearNotifications,
  deleteNotification,
  listNotifications,
  markAllNotificationsRead,
  markNotificationRead,
  subscribeNotificationEvents,
} from '../api/client';
import type { UserNotification } from '../types';

const POPOVER_WIDTH = 340;
const HEADER_POPOVER_OPEN_EVENT = 'tkmind:header-popover-open';
const HEADER_POPOVER_ID = 'notification-center';

function formatTime(timestamp: number) {
  const date = new Date(timestamp);
  if (Number.isNaN(date.getTime())) return '';
  return `${date.getMonth() + 1}/${date.getDate()} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
}

type Filter = 'all' | 'unread' | 'read';

function parseNotificationLines(body: string) {
  return body
    .split('\n')
    .map((line) => line.trim())
    .filter(Boolean);
}

export function NotificationCenter({
  onOpenRecharge,
}: {
  onOpenRecharge?: () => void;
}) {
  const [open, setOpen] = useState(false);
  const [filter, setFilter] = useState<Filter>('all');
  const [items, setItems] = useState<UserNotification[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [popoverStyle, setPopoverStyle] = useState<CSSProperties>({});
  const wrapRef = useRef<HTMLDivElement>(null);

  const unreadCount = useMemo(
    () => items.reduce((count, item) => count + (item.status === 'unread' ? 1 : 0), 0),
    [items],
  );

  const load = async (nextFilter = filter) => {
    setLoading(true);
    setError(null);
    try {
      const notifications = await listNotifications(nextFilter, 50);
      setItems(notifications);
    } catch (err) {
      setError(err instanceof Error ? err.message : '读取通知失败');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    const syncAll = () => {
      if (document.visibilityState === 'visible') {
        void load('all');
      }
    };
    void load('all');
    const unsubscribe = subscribeNotificationEvents({
      onNotification: () => void load('all'),
      onSync: () => void load('all'),
    });
    window.addEventListener('focus', syncAll);
    document.addEventListener('visibilitychange', syncAll);
    return () => {
      unsubscribe();
      window.removeEventListener('focus', syncAll);
      document.removeEventListener('visibilitychange', syncAll);
    };
  }, []);

  useEffect(() => {
    if (!open) return;
    const handleClick = (event: MouseEvent) => {
      if (wrapRef.current && !wrapRef.current.contains(event.target as Node)) {
        setOpen(false);
      }
    };
    document.addEventListener('click', handleClick);
    return () => document.removeEventListener('click', handleClick);
  }, [open]);

  useEffect(() => {
    const handleOtherPopoverOpen = (event: Event) => {
      const detail = (event as CustomEvent<{ id?: string }>).detail;
      if (detail?.id && detail.id !== HEADER_POPOVER_ID) {
        setOpen(false);
      }
    };
    window.addEventListener(HEADER_POPOVER_OPEN_EVENT, handleOtherPopoverOpen);
    return () => window.removeEventListener(HEADER_POPOVER_OPEN_EVENT, handleOtherPopoverOpen);
  }, []);

  useEffect(() => {
    if (!open) return;
    const updatePosition = () => {
      const anchor = wrapRef.current;
      if (!anchor) return;
      const rect = anchor.getBoundingClientRect();
      const width = Math.min(POPOVER_WIDTH, window.innerWidth - 24);
      let left = rect.left + rect.width / 2 - width / 2;
      left = Math.max(12, Math.min(left, window.innerWidth - width - 12));
      setPopoverStyle({
        position: 'fixed',
        top: rect.bottom + 10,
        left,
        width,
      });
    };
    updatePosition();
    window.addEventListener('resize', updatePosition);
    window.addEventListener('scroll', updatePosition, true);
    return () => {
      window.removeEventListener('resize', updatePosition);
      window.removeEventListener('scroll', updatePosition, true);
    };
  }, [open]);

  const visibleItems = filter === 'all' ? items : items.filter((item) => item.status === filter);

  return (
    <div className={`notification-center${open ? ' open' : ''}`} ref={wrapRef}>
      <button
        type="button"
        className="header-icon-btn notification-center-trigger"
        aria-label="通知中心"
        aria-expanded={open}
        onClick={() => {
          setOpen((value) => {
            const next = !value;
            if (next) {
              window.dispatchEvent(
                new CustomEvent(HEADER_POPOVER_OPEN_EVENT, {
                  detail: { id: HEADER_POPOVER_ID },
                }),
              );
            }
            return next;
          });
          if (!open) void load(filter);
        }}
      >
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">
          <path
            d="M12 4a5 5 0 00-5 5v2.7c0 .5-.18.97-.5 1.33L5 15h14l-1.5-1.97a2.1 2.1 0 01-.5-1.33V9a5 5 0 00-5-5z"
            stroke="currentColor"
            strokeWidth="1.75"
            strokeLinecap="round"
            strokeLinejoin="round"
          />
          <path d="M10 18a2 2 0 004 0" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" />
        </svg>
        {unreadCount > 0 && <span className="notification-center-badge">{unreadCount > 99 ? '99+' : unreadCount}</span>}
      </button>

      {open && (
        <div className="notification-center-popover" role="dialog" aria-label="通知中心" style={popoverStyle}>
          <div className="notification-center-head">
            <div>
              <h4>通知中心</h4>
              <p>{unreadCount > 0 ? `${unreadCount} 条未读` : '通知已处理完'}</p>
            </div>
            <div className="notification-center-actions">
              <button type="button" className="ghost-btn" onClick={() => void markAllNotificationsRead().then(() => load(filter))}>
                全部已读
              </button>
              <button
                type="button"
                className="notification-center-clear-all-btn"
                onClick={() => void clearNotifications(filter).then(() => load(filter))}
              >
                全部清除
              </button>
            </div>
          </div>

          <div className="notification-center-filters">
            {(['all', 'unread', 'read'] as Filter[]).map((value) => (
              <button
                key={value}
                type="button"
                className={`notification-center-filter${filter === value ? ' is-active' : ''}`}
                onClick={() => {
                  setFilter(value);
                  void load(value);
                }}
              >
                {value === 'all' ? '全部' : value === 'unread' ? '未读' : '已读'}
              </button>
            ))}
          </div>

          {loading ? <p className="notification-center-state">正在读取通知…</p> : null}
          {error ? <p className="notification-center-state is-error">{error}</p> : null}
          {!loading && !error && visibleItems.length === 0 ? <p className="notification-center-state">暂时没有通知</p> : null}

          <div className="notification-center-list">
            {visibleItems.map((item) => (
              <article key={item.id} className={`notification-center-item${item.status === 'unread' ? ' is-unread' : ''}`}>
                <div className="notification-center-item-head">
                  <strong>{item.title}</strong>
                  <span>{formatTime(item.createdAt)}</span>
                </div>
                {item.notificationType === 'todo_digest' ? (
                  <div className="notification-center-digest">
                    {parseNotificationLines(item.body).map((line, index) => (
                      <div
                        key={`${item.id}-${index}`}
                        className={`notification-center-digest-line${index === 0 ? ' is-title' : ''}`}
                      >
                        {line}
                      </div>
                    ))}
                  </div>
                ) : (
                  <p>{item.body}</p>
                )}
                <div className="notification-center-item-actions">
                  {item.status === 'unread' ? (
                    <button
                      type="button"
                      className="notification-center-read-btn"
                      onClick={() => void markNotificationRead(item.id).then(() => load(filter))}
                    >
                      标为已读
                    </button>
                  ) : (
                    <span className="notification-center-read-tag">已读</span>
                  )}
                  {item.notificationType === 'balance_low' && onOpenRecharge ? (
                    <button
                      type="button"
                      className="ghost-btn"
                      onClick={() => {
                        if (item.status === 'unread') {
                          void markNotificationRead(item.id).then(() => load(filter));
                        }
                        setOpen(false);
                        onOpenRecharge();
                      }}
                    >
                      去充值
                    </button>
                  ) : null}
                  <button
                    type="button"
                    className="notification-center-clear-btn"
                    onClick={() => void deleteNotification(item.id).then(() => load(filter))}
                  >
                    清除
                  </button>
                </div>
              </article>
            ))}
          </div>
        </div>
      )}
    </div>
  );
}
