import React, { useState, useEffect, useCallback } from 'react';
import {
  Box,
  List,
  ListItem,
  ListItemText,
  IconButton,
  Typography,
  Divider,
  CircularProgress,
  Alert,
  Chip,
  Tooltip,
} from '@mui/material';
import {
  Info as InfoIcon,
  Delete as DeleteIcon,
  FiberManualRecord as UnreadIcon,
  ExpandMore,
  ExpandLess,
  FormatListBulleted as AlertListIcon,
  OpenInNew as OpenInNewIcon,
  Analytics as AnalyticsIcon,
} from '@mui/icons-material';
import { getNotifications, deleteNotification, getNotificationDetail, AlertNotificationDto } from '../../services/alertApi';
import type { BacktestResult, TradeRecord } from '../../services/backtestApi';
import { TradeSignalDetailDialog } from '../TradeSignalDetailDialog';
import { format } from 'date-fns';
import AlertDetailDialog from './AlertDetailDialog';
import {
  buildBacktestResultFromAlertDetail,
  buildTradeRecordFromAlertDetail,
} from '../../utils/alertTradeRecordFromDetail';
import { useAlertNotification } from '../../contexts/AlertNotificationContext';
import { useNavigation } from '../../contexts/NavigationContext';
import upbitApiService from '../../services/upbitApi';
import {
  extractStrategyNames,
  extractStockStrategyPairs,
  resolveStockStrategyPairRow,
  resolveSymbols,
} from '../../utils/alertMessageParser';
import {
  alertMarkerTimeIsoFromDto,
  inferAlertSignalFromNotification,
} from '../../utils/alertSignalInference';
import { getUpbitWebExchangeUrl } from '../../utils/upbitWebUrls';

interface AlertNotificationListProps {
  maxItems?: number;
  onDoubleClickNotification?: (notification: AlertNotificationDto) => void;
}

/** AlertSnackbar와 동일: 통합/단일 알림에 대해 타이틀(전략명)과 종목·전략 쌍 */
function getTitleAndPairs(
  notification: AlertNotificationDto
): { title: string; pairs: Array<{ koreanName: string; strategyName: string; symbol?: string }> } {
  if (!notification) return { title: '', pairs: [] };
  const msg = notification.message || '';

  if (msg.includes('알림 조건 충족') && msg.includes('개)')) {
    const strategyNames = extractStrategyNames(msg);
    const pairs = extractStockStrategyPairs(msg) ?? [];
    const title =
      strategyNames && strategyNames.length > 0
        ? strategyNames.length <= 3
          ? strategyNames.join(', ')
          : `${strategyNames.slice(0, 2).join(', ')} 외 ${strategyNames.length - 2}개 전략`
        : '🎯 통합 알림';
    return { title, pairs: pairs.map((p) => ({ ...p, symbol: undefined })) };
  }

  if (notification.koreanName) {
    const firstLine = msg.split('\n')[0]?.trim() || '';
    const strategyName = firstLine.replace(/^[\s🧪🎯✅]*/, '').trim() || '알림';
    const title = strategyName;
    const pairs = [{ koreanName: notification.koreanName, strategyName, symbol: notification.symbol }];
    return { title, pairs };
  }

  return { title: notification.symbol || '알림', pairs: [] };
}

/**
 * 알림 목록 컴포넌트 (알림 팝업과 동일한 종목 펼침 UI)
 */
const AlertNotificationList: React.FC<AlertNotificationListProps> = ({ maxItems = 20, onDoubleClickNotification }) => {
  const { latestNotification } = useAlertNotification();
  const { navigateToPage } = useNavigation();
  const [cryptoMap, setCryptoMap] = useState<Map<string, string>>(new Map());
  const [notifications, setNotifications] = useState<AlertNotificationDto[]>([]);
  const [loading, setLoading] = useState(false);
  const [initialFetchDone, setInitialFetchDone] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [detailDialogOpen, setDetailDialogOpen] = useState(false);
  const [selectedNotificationId, setSelectedNotificationId] = useState<number | null>(null);
  const [expandedById, setExpandedById] = useState<Record<number, boolean>>({});
  const [signalDetailOpen, setSignalDetailOpen] = useState(false);
  const [signalDetailTrade, setSignalDetailTrade] = useState<TradeRecord | null>(null);
  const [signalDetailBacktestResult, setSignalDetailBacktestResult] = useState<BacktestResult | null>(null);

  useEffect(() => {
    upbitApiService
      .getActiveCryptos()
      .then((cryptos) => {
        const map = new Map<string, string>();
        cryptos.forEach((c) => map.set(c.koreanName, c.symbol));
        setCryptoMap(map);
      })
      .catch(() => {});
  }, []);

  const fetchList = useCallback(
    async (showSpinner: boolean) => {
      try {
        if (showSpinner) {
          setLoading(true);
          setError(null);
        }
        const data = await getNotifications(undefined, 0, maxItems);
        setNotifications(data.content);
      } catch (err: unknown) {
        console.error('알림 목록 로드 실패:', err);
        if (showSpinner) {
          setError('알림 목록을 불러오는데 실패했습니다.');
        }
      } finally {
        if (showSpinner) {
          setLoading(false);
        }
        setInitialFetchDone(true);
      }
    },
    [maxItems]
  );

  useEffect(() => {
    void fetchList(true);
  }, [fetchList]);

  useEffect(() => {
    if (!initialFetchDone || latestNotification?.id == null) return;
    setNotifications((prev) => {
      if (prev.some((n) => n.id === latestNotification.id)) return prev;
      return [latestNotification, ...prev].slice(0, maxItems);
    });
    void fetchList(false);
    // eslint-disable-next-line react-hooks/exhaustive-deps -- id 기준 동기화
  }, [latestNotification?.id, initialFetchDone, maxItems, fetchList]);

  const handleShowDetail = (notificationId: number) => {
    setSelectedNotificationId(notificationId);
    setDetailDialogOpen(true);
  };

  const handleCloseDetail = () => {
    setDetailDialogOpen(false);
    setSelectedNotificationId(null);
    void fetchList(true);
  };

  const handleDelete = async (notificationId: number, event: React.MouseEvent) => {
    event.stopPropagation();
    if (!window.confirm('이 알림을 삭제하시겠습니까?')) {
      return;
    }
    try {
      await deleteNotification(notificationId);
      setNotifications((prev) => prev.filter((n) => n.id !== notificationId));
      setExpandedById((prev) => {
        const next = { ...prev };
        delete next[notificationId];
        return next;
      });
    } catch (err: unknown) {
      console.error('알림 삭제 실패:', err);
      alert('알림 삭제에 실패했습니다.');
    }
  };

  const handleDoubleClick = (notification: AlertNotificationDto) => {
    if (onDoubleClickNotification && notification.symbol) {
      onDoubleClickNotification(notification);
    } else if (notification.id) {
      handleShowDetail(notification.id);
    }
  };

  const handleDetailButtonClick = (notificationId: number, event: React.MouseEvent) => {
    event.stopPropagation();
    if (notificationId) {
      handleShowDetail(notificationId);
    }
  };

  const handleOpenSignalDetail = async (
    e: React.MouseEvent,
    notification: AlertNotificationDto,
    pair: { koreanName: string; strategyName: string; navSymbol?: string; symbol?: string }
  ) => {
    e.stopPropagation();
    if (!notification.id) return;
    try {
      const rowSym = (pair.navSymbol ?? pair.symbol ?? '').trim();
      const detail = await getNotificationDetail(
        notification.id,
        rowSym ? { symbol: rowSym } : undefined
      );
      const inferred =
        inferAlertSignalFromNotification(notification, pair.koreanName) ?? 'BUY';
      const strategy =
        pair.strategyName?.trim() ||
        (notification.conditionDescription || '').replace(/^전략:\s*/, '').trim() ||
        undefined;
      const trade = buildTradeRecordFromAlertDetail(detail, inferred, strategy);
      const backtestResult = buildBacktestResultFromAlertDetail(detail, trade);
      setSignalDetailTrade(trade);
      setSignalDetailBacktestResult(backtestResult);
      setSignalDetailOpen(true);
    } catch (err) {
      console.error(err);
      alert('신호 상세를 불러오지 못했습니다.');
    }
  };

  const handleStockClick = (notification: AlertNotificationDto, koreanName: string, symbol?: string) => {
    const timeIso = alertMarkerTimeIsoFromDto(notification);
    const inferred = inferAlertSignalFromNotification(notification, koreanName);
    const extras: { alertSignal?: 'BUY' | 'SELL'; alertMarkerTime?: string } = {};
    if (inferred && timeIso) {
      extras.alertSignal = inferred;
      extras.alertMarkerTime = timeIso;
    }
    if (symbol) {
      navigateToPage('alert-list', { symbol, koreanName, ...extras });
      return;
    }
    const resolved = resolveSymbols([koreanName], cryptoMap);
    if (resolved.length > 0) {
      navigateToPage('alert-list', {
        symbol: resolved[0].symbol,
        koreanName: resolved[0].koreanName,
        ...extras,
      });
    }
  };

  const toggleExpand = (id: number, e: React.MouseEvent) => {
    e.stopPropagation();
    setExpandedById((prev) => ({ ...prev, [id]: !prev[id] }));
  };

  if (loading && notifications.length === 0) {
    return (
      <Box sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center', minHeight: 200 }}>
        <CircularProgress />
      </Box>
    );
  }

  if (error) {
    return (
      <Alert severity="error" sx={{ m: 2 }}>
        {error}
      </Alert>
    );
  }

  if (notifications.length === 0) {
    return (
      <Box sx={{ p: 4, textAlign: 'center' }}>
        <Typography variant="body1" color="text.secondary">
          알림이 없습니다.
        </Typography>
      </Box>
    );
  }

  return (
    <Box>
      <List disablePadding>
        {notifications.map((notification, index) => {
          const { title, pairs } = getTitleAndPairs(notification);
          const hasStockList = pairs.length > 0;
          const displayPairs = pairs.map((p) => resolveStockStrategyPairRow(p, cryptoMap));

          const firstName = displayPairs[0]?.koreanName ?? notification.koreanName ?? '';
          const otherCount = Math.max(0, displayPairs.length - 1);
          const stockSummaryLine =
            firstName !== '' ? `${firstName} 외 ${otherCount}종목` : '종목 정보 없음';

          const expanded = notification.id != null && !!expandedById[notification.id];

          return (
            <React.Fragment key={notification.id ?? `n-${index}`}>
              {index > 0 && <Divider />}
              <ListItem
                alignItems="flex-start"
                onDoubleClick={() => handleDoubleClick(notification)}
                sx={{
                  flexDirection: 'column',
                  alignItems: 'stretch',
                  py: 1.25,
                  px: 1.5,
                  bgcolor: notification.isRead ? 'transparent' : 'action.hover',
                  '&:hover': { bgcolor: 'action.selected' },
                  cursor: 'pointer',
                }}
              >
                <Box sx={{ display: 'flex', width: '100%', gap: 1 }}>
                  <Box sx={{ pt: 0.25, width: 20, flexShrink: 0 }}>
                    {!notification.isRead && <UnreadIcon color="primary" fontSize="small" />}
                  </Box>
                  <Box sx={{ flex: 1, minWidth: 0 }}>
                    <Box
                      sx={{
                        display: 'flex',
                        alignItems: 'flex-start',
                        gap: 1,
                        mb: 0.5,
                        width: '100%',
                      }}
                    >
                      <Box
                        sx={{
                          flex: 1,
                          minWidth: 0,
                          display: 'flex',
                          flexWrap: 'wrap',
                          alignItems: 'center',
                          gap: 1,
                        }}
                      >
                        <Typography variant="subtitle1" fontWeight={notification.isRead ? 'normal' : 'bold'}>
                          {title}
                        </Typography>
                        {!notification.isRead && <Chip label="새 알림" size="small" color="primary" />}
                      </Box>
                      <Box
                        sx={{
                          display: 'flex',
                          flexShrink: 0,
                          alignItems: 'center',
                          gap: 0.25,
                          mt: -0.25,
                        }}
                      >
                        <IconButton
                          size="small"
                          onClick={(e) => notification.id && handleDetailButtonClick(notification.id, e)}
                          title="상세보기"
                          color="primary"
                        >
                          <InfoIcon fontSize="small" />
                        </IconButton>
                        <IconButton
                          size="small"
                          onClick={(e) => notification.id && handleDelete(notification.id, e)}
                          title="삭제"
                          color="error"
                        >
                          <DeleteIcon fontSize="small" />
                        </IconButton>
                      </Box>
                    </Box>
                    <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.25, mb: 0.5 }}>
                      {hasStockList && notification.id != null && (
                        <IconButton
                          size="small"
                          onClick={(e) => toggleExpand(notification.id!, e)}
                          aria-expanded={expanded}
                          aria-label={expanded ? '종목 목록 접기' : '종목 목록 펼치기'}
                          sx={{ p: 0.5, mr: 0.25 }}
                        >
                          {expanded ? <ExpandLess fontSize="small" /> : <ExpandMore fontSize="small" />}
                        </IconButton>
                      )}
                      <Typography variant="body2" color="text.secondary">
                        {stockSummaryLine}
                      </Typography>
                    </Box>
                    <Typography variant="caption" color="text.secondary" sx={{ display: 'block' }}>
                      {notification.triggeredAt ? format(new Date(notification.triggeredAt), 'yyyy-MM-dd HH:mm:ss') : '-'}
                    </Typography>

                    {expanded && hasStockList && (
                      <List
                        dense
                        disablePadding
                        sx={{
                          mt: 1,
                          border: '1px solid',
                          borderColor: 'divider',
                          borderRadius: 1,
                          overflow: 'hidden',
                          maxHeight: 220,
                          overflowY: 'auto',
                        }}
                        onClick={(e) => e.stopPropagation()}
                      >
                        {displayPairs.map((pair, i) => {
                          const marketSym = pair.navSymbol ?? pair.symbol;
                          const upbitUrl = getUpbitWebExchangeUrl(marketSym, notification.timeInterval);
                          return (
                          <ListItem
                            key={`${pair.navSymbol ?? pair.displaySymbol}-${pair.koreanName}-${i}`}
                            sx={{
                              py: 0.5,
                              px: 1.5,
                              cursor: 'pointer',
                              '&:hover': { bgcolor: 'action.hover' },
                              borderBottom: i < displayPairs.length - 1 ? '1px solid' : 'none',
                              borderColor: 'divider',
                            }}
                            onClick={() => handleStockClick(notification, pair.koreanName, pair.navSymbol ?? pair.symbol)}
                            secondaryAction={
                              <Box
                                sx={{ display: 'flex', alignItems: 'center', gap: 0.25, mr: -0.5 }}
                                onClick={(e) => e.stopPropagation()}
                              >
                                <Tooltip
                                  title="알림목록으로 이동"
                                  placement="top"
                                  PopperProps={{ sx: { zIndex: 11050 } }}
                                >
                                  <IconButton
                                    size="small"
                                    edge="end"
                                    onClick={(e) => {
                                      e.stopPropagation();
                                      handleStockClick(notification, pair.koreanName, pair.navSymbol ?? pair.symbol);
                                    }}
                                    aria-label="알림목록으로 이동"
                                  >
                                    <AlertListIcon fontSize="small" />
                                  </IconButton>
                                </Tooltip>
                                {upbitUrl ? (
                                  <Tooltip
                                    placement="top"
                                    PopperProps={{ sx: { zIndex: 11050 } }}
                                    title={
                                      notification.timeInterval
                                        ? `업비트 웹 차트 (시간봉 ${notification.timeInterval})`
                                        : '업비트 웹에서 차트 보기'
                                    }
                                  >
                                    <IconButton
                                      size="small"
                                      component="a"
                                      href={upbitUrl}
                                      target="_blank"
                                      rel="noopener noreferrer"
                                      onClick={(e) => e.stopPropagation()}
                                      aria-label="업비트에서 차트 열기"
                                      sx={{ color: 'success.main' }}
                                    >
                                      <OpenInNewIcon fontSize="small" />
                                    </IconButton>
                                  </Tooltip>
                                ) : null}
                                <Tooltip
                                  title="알림 발생 시점 기준 전략·신호 상세 (해당 행 종목)"
                                  placement="top"
                                  PopperProps={{ sx: { zIndex: 11050 } }}
                                >
                                  <span>
                                    <IconButton
                                      size="small"
                                      onClick={(e) => handleOpenSignalDetail(e, notification, pair)}
                                      aria-label="전략 신호 상세"
                                      color="primary"
                                    >
                                      <AnalyticsIcon fontSize="small" />
                                    </IconButton>
                                  </span>
                                </Tooltip>
                              </Box>
                            }
                          >
                            <ListItemText
                              primary={pair.koreanName}
                              secondary={pair.displaySymbol}
                              primaryTypographyProps={{ fontSize: '13px', fontWeight: 500 }}
                              secondaryTypographyProps={{ fontSize: '11px', color: 'text.secondary' }}
                            />
                          </ListItem>
                          );
                        })}
                      </List>
                    )}
                  </Box>
                </Box>
              </ListItem>
            </React.Fragment>
          );
        })}
      </List>

      <AlertDetailDialog
        open={detailDialogOpen}
        notificationId={selectedNotificationId}
        onClose={handleCloseDetail}
        onMarkAsRead={() => void fetchList(true)}
      />

      <TradeSignalDetailDialog
        open={signalDetailOpen}
        trade={signalDetailTrade}
        backtestResult={signalDetailBacktestResult}
        onClose={() => {
          setSignalDetailOpen(false);
          setSignalDetailTrade(null);
          setSignalDetailBacktestResult(null);
        }}
      />
    </Box>
  );
};

export default AlertNotificationList;
