/**
 * 매매 시그널 알림 목록 행 — 4칸이 목록 너비를 꽉 채움, 보조지표 2개↑ 시 우측 슬롯만 스크롤
 */
import React, { useCallback, useEffect, useMemo, useRef, useState, memo } from 'react';
import type { Theme } from '../../types';
import type { TickerData } from '../../hooks/useMarketTicker';
import { useLiveReceiveFlash } from '../../hooks/useLiveReceiveFlash';
import { useTradeNotificationSignalSnapshot } from '../../hooks/useTradeNotificationSignalSnapshot';
import type { StrategyDto } from '../../utils/backendApi';
import { resolveNotificationStrategy } from '../../utils/resolveNotificationStrategy';
import { normalizeMarketCode } from '../../utils/strategyHydrate';
import type { TradeNotificationItem } from '../../contexts/TradeNotificationContext';
import {
  buildSignalDetailRows,
  formatCandleTypeKo,
  formatSignalPrice,
  formatSignalTime,
  getMarketDisplayLine,
  getSignalTypeKo,
} from '../../utils/tradeSignalDisplay';
import { useTradeAlertTimeFormat } from '../../utils/tradeAlertTimeFormat';
import {
  buildStrategyChartIndicators,
  candleTypeToTimeframe,
} from '../../utils/strategyToChartIndicators';
import { formatIndicatorDisplayLabel } from '../../utils/indicatorRegistry';
import { useIndicatorSettings } from '../../hooks/useIndicatorSettings';
import TradeSignalChartCard from './TradeSignalChartCard';
import TradeNotificationSignalCard from './TradeNotificationSignalCard';
import TradeNotificationHScrollPane from './TradeNotificationHScrollPane';
import VirtualLiveBadge from '../virtual/VirtualLiveBadge';
import type { VirtualLiveStatus } from '../../hooks/useVirtualTargetLiveStatus';

const IcTrash = () => (
  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
    <polyline points="3 6 5 6 21 6" />
    <path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
    <line x1="10" y1="11" x2="10" y2="17" />
    <line x1="14" y1="11" x2="14" y2="17" />
  </svg>
);

const IcReport = () => (
  <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden>
    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
    <polyline points="14 2 14 8 20 8" />
    <line x1="16" y1="13" x2="8" y2="13" />
    <line x1="16" y1="17" x2="8" y2="17" />
    <line x1="10" y1="9" x2="8" y2="9" />
  </svg>
);

export type TradeNotificationRowLayout = 'list' | 'grid';

interface Props {
  item: TradeNotificationItem;
  theme: Theme;
  isSelected: boolean;
  layoutMode?: TradeNotificationRowLayout;
  chartsEnabled?: boolean;
  chartLiveReceiveHighlight?: boolean;
  /** 해당 종목 시세 (전체 tickers Map 대신 행 단위 전달 — memo·리렌더 최소화) */
  ticker?: TickerData;
  onSelect: () => void;
  onDelete: (e: React.MouseEvent) => void;
  onDetail: () => void;
  onGoToChart: () => void;
  /** 매매 버튼 클릭 → 우측 매매 패널 열기 */
  onTrade?: () => void;
  /** 상세분석 레포트 버튼 클릭 */
  onReport?: () => void;
  reportLoading?: boolean;
  /** 가상 스크롤 목록에서는 div + role=listitem */
  itemTag?: 'li' | 'div';
  /** 목록 화면에서 선로드한 전략 목록 (ID·이름 fallback) */
  prefetchedStrategies?: StrategyDto[];
}

const MAX_INDICATOR_CARDS = 8;

const TradeNotificationListRow: React.FC<Props> = ({
  item,
  theme,
  isSelected,
  layoutMode = 'list',
  chartsEnabled = true,
  chartLiveReceiveHighlight = true,
  ticker,
  onSelect,
  onDelete,
  onDetail,
  onGoToChart,
  onTrade,
  onReport,
  reportLoading = false,
  itemTag = 'li',
  prefetchedStrategies = [],
}) => {
  useTradeAlertTimeFormat();
  const isBuy = item.signalType === 'BUY';
  const allDetailRows = buildSignalDetailRows(item);
  const metaRows = allDetailRows.filter(
    row => row.label !== '종목' && row.label !== '매매 구분' && row.label !== '기준 가격' && row.label !== '전략',
  );
  const strategyRow = allDetailRows.find(row => row.label === '전략');
  const { primary, secondary } = getMarketDisplayLine(item.market);
  const sym = item.market.replace(/^KRW-/, '');
  const isListLayout = layoutMode === 'list';
  const chartTf = candleTypeToTimeframe(item.candleType ?? '1m');
  const candleKo = formatCandleTypeKo(item.candleType);

  const { getParams, getVisualConfig } = useIndicatorSettings();
  const [strategy, setStrategy] = useState<StrategyDto | undefined>();
  const [strategies, setStrategies] = useState<StrategyDto[]>([]);
  const strategyLabel = item.strategyName?.trim()
    || strategy?.name
    || strategyRow?.value
    || '실시간 전략';
  const rowRef = useRef<HTMLLIElement | HTMLDivElement>(null);
  const RowTag = itemTag;
  const [inView, setInView] = useState(false);
  /** 펼쳐보기 중인 차트: 'candle' | 지표 id | null */
  const [expandedChartKey, setExpandedChartKey] = useState<string | null>(null);

  useEffect(() => {
    const el = rowRef.current;
    if (!el) return;
    const io = new IntersectionObserver(
      entries => {
        setInView(entries[0]?.isIntersecting ?? false);
      },
      { rootMargin: '120px 0px', threshold: 0.05 },
    );
    io.observe(el);
    return () => io.disconnect();
  }, [item.id]);

  const panelActive = isListLayout && inView;
  const gridActive = !isListLayout && inView;
  const marketCode = normalizeMarketCode(item.market);

  useEffect(() => {
    if (!panelActive || !isListLayout) {
      setStrategy(undefined);
      setStrategies([]);
      return;
    }
    let cancelled = false;
    setStrategies(prefetchedStrategies);
    if (!item.strategyId && !item.strategyName?.trim()) {
      return () => { cancelled = true; };
    }
    void resolveNotificationStrategy(
      item.strategyId,
      item.strategyName,
      prefetchedStrategies,
      item.market,
    ).then(({ strategy: s, strategyId: sid }) => {
      if (!cancelled && s) setStrategy(s);
      else if (!cancelled && !s && sid == null) setStrategy(undefined);
    });
    return () => { cancelled = true; };
  }, [item.strategyId, item.strategyName, item.market, panelActive, isListLayout, prefetchedStrategies]);

  useEffect(() => {
    setExpandedChartKey(null);
  }, [item.id, layoutMode]);

  const indicatorCards = useMemo(() => {
    if (!isListLayout || !strategy) return [];
    const all = buildStrategyChartIndicators(strategy, getParams, getVisualConfig);
    return all.slice(0, MAX_INDICATOR_CARDS).map(ind => ({
      id: ind.id,
      type: ind.type,
      label: formatIndicatorDisplayLabel(ind.type),
      config: [ind],
    }));
  }, [strategy, getParams, getVisualConfig, isListLayout]);

  /** 통합 차트용: 전략의 모든 보조지표를 하나의 차트에 넘긴다 */
  const allIndicatorConfigs = useMemo(
    () => indicatorCards.flatMap(c => c.config),
    [indicatorCards],
  );

  const chartExpanded = isListLayout && expandedChartKey != null;
  const chartActive = isListLayout && chartsEnabled && panelActive;
  const signalCardEnabled = isListLayout && panelActive && !chartExpanded;
  const expandedIndicator = indicatorCards.find(c => c.id === expandedChartKey);

  const signalSnapshotEnabled = item.strategyId != null && (
    signalCardEnabled || gridActive
  );
  const { snapshot, loading: signalLoading } = useTradeNotificationSignalSnapshot(
    item.market,
    item.strategyId,
    strategy,
    item.strategyName,
    signalSnapshotEnabled,
    prefetchedStrategies,
  );

  const [chartActivitySeq, setChartActivitySeq] = useState(0);
  const bumpChartActivity = useCallback(() => {
    setChartActivitySeq(n => n + 1);
  }, []);

  const liveReceiveEnabled = inView && chartLiveReceiveHighlight;
  const receiveSignal = useMemo(() => {
    if (!liveReceiveEnabled) return null;
    return [
      ticker?.tradePrice ?? '',
      ticker?.changeRate ?? '',
      snapshot?.updatedAt ?? 0,
      chartActivitySeq,
    ].join('|');
  }, [
    liveReceiveEnabled,
    ticker?.tradePrice,
    ticker?.changeRate,
    snapshot?.updatedAt,
    chartActivitySeq,
  ]);
  const receiving = useLiveReceiveFlash(receiveSignal, liveReceiveEnabled);
  const highlightReceiving = chartLiveReceiveHighlight && receiving;
  const gridLiveStatus: VirtualLiveStatus = gridActive
    ? (ticker?.tradePrice != null || snapshot?.updatedAt ? 'live' : 'connecting')
    : 'idle';

  const indicatorChartCount = indicatorCards.length;
  /** 보조지표 2개 이상이면 첫 1개만 보이고 나머지는 좌우 스크롤 */
  const indicatorScrollNeeded = indicatorChartCount >= 2;
  const indicatorPlaceholder = item.strategyId != null && indicatorChartCount === 0 && chartActive;

  const signalMarker = useMemo(
    () => ({
      candleTime: item.candleTime,
      signalType: item.signalType,
      price: item.price,
    }),
    [item.candleTime, item.signalType, item.price],
  );

  const handleRowClick = useCallback((e: React.MouseEvent) => {
    const t = e.target as HTMLElement;
    if (t.closest(
      'button, a, input, select, textarea, .tnl-chart-view-btn, .tnl-hscroll-pane__rail-btn',
    )) {
      return;
    }
    onSelect();
  }, [onSelect]);

  const summaryCard = (
    <article
      className={[
        'tnl-summary-card',
        isBuy ? 'tnl-summary-card--buy' : 'tnl-summary-card--sell',
        !isListLayout ? 'tnl-summary-card--grid' : '',
        isSelected ? 'tnl-summary-card--selected' : '',
        !isListLayout && highlightReceiving ? 'tnl-summary-card--receiving' : '',
      ].filter(Boolean).join(' ')}
      aria-label="알림 요약"
    >
          <div className="tnl-summary-panel" role="presentation">
            <div className="tnl-summary-head">
              <div className="tnl-summary-title">
                <span className="tnl-summary-ko">{primary}</span>
                <span className="tnl-summary-sym">{sym || secondary}</span>
              </div>
              <div className="tnl-summary-head-actions">
                {!isListLayout && gridActive && (
                  <VirtualLiveBadge
                    status={gridLiveStatus}
                    receiving={highlightReceiving}
                  />
                )}
                <span className={`tnl-signal ${isBuy ? 'tnl-signal--buy' : 'tnl-signal--sell'}`}>
                  {item.signalType}
                </span>
                {!item.isRead && <span className="tnl-dot tnl-summary-dot" aria-label="미확인" />}
              </div>
            </div>

            {/* 전략명 태그 — 헤더 바로 아래에 표시 */}
            <div className="tnl-summary-strategy-tag" title={strategyLabel} aria-label={`전략: ${strategyLabel}`}>
              <span className="tnl-summary-strategy-tag-ic" aria-hidden>⚡</span>
              <span className="tnl-summary-strategy-tag-name">{strategyLabel}</span>
            </div>

            <div className="tnl-summary-quote" aria-label="시그널 가격">
              <div className="tnl-summary-quote-left">
                <span
                  className={`tnl-summary-arrow${isBuy ? ' tnl-summary-arrow--buy' : ' tnl-summary-arrow--sell'}`}
                  aria-hidden
                >
                  {isBuy ? '▲' : '▼'}
                </span>
                <span className="tnl-summary-pair">{sym || secondary}/KRW</span>
                <span className={`tnl-summary-type${isBuy ? ' tnl-summary-type--buy' : ' tnl-summary-type--sell'}`}>
                  {getSignalTypeKo(item.signalType)}
                </span>
              </div>
              <div className="tnl-summary-quote-right">
                <span
                  className={`tnl-summary-price${isBuy ? ' tnl-summary-price--buy' : ' tnl-summary-price--sell'}`}
                >
                  {formatSignalPrice(item.price)}
                </span>
              </div>
            </div>

            <div className="tnl-summary-meta">
              {metaRows.map(row => (
                <div
                  key={row.label}
                  className={[
                    'tnl-summary-info-row',
                    row.label === '캔들 시각' ? 'tnl-summary-info-row--candle' : '',
                  ].filter(Boolean).join(' ')}
                >
                  <span className="tnl-summary-info-lbl">{row.label}</span>
                  {row.label === '캔들 시각' ? (
                    <span
                      className={[
                        'tnl-summary-info-val',
                        'tnl-summary-info-val--candle',
                        row.highlight ? 'tnl-summary-info-val--hi' : '',
                      ].filter(Boolean).join(' ')}
                    >
                      {formatSignalTime(item.candleTime)}
                      <span className="tnl-candle-interval">
                        {' · '}
                        {candleKo}
                      </span>
                    </span>
                  ) : (
                    <span className={`tnl-summary-info-val${row.highlight ? ' tnl-summary-info-val--hi' : ''}`}>
                      {row.value}
                    </span>
                  )}
                </div>
              ))}
            </div>

            <div className="tnl-summary-strategy-field">
              <span className="tnl-summary-strategy-lbl">투자전략</span>
              <span className="tnl-summary-strategy-box" title={strategyLabel}>
                {strategyLabel}
              </span>
            </div>
          </div>

          <div className="tnl-summary-card-actions">
            <button
              type="button"
              className="tnl-row-icon-btn"
              title="삭제"
              aria-label="알림 삭제"
              onClick={onDelete}
            >
              <IcTrash />
            </button>
            <button type="button" className="tnl-row-action" onClick={onDetail}>
              상세
            </button>
            <button type="button" className="tnl-row-chart" onClick={onGoToChart}>
              차트
            </button>
            {onTrade && (
              <button type="button" className="tnl-row-trade" onClick={onTrade}>
                매매
              </button>
            )}
            {onReport && (
              <button
                type="button"
                className={['tnl-row-report', reportLoading ? 'tnl-row-report--loading' : ''].filter(Boolean).join(' ')}
                title="상세분석 레포트"
                aria-label="상세분석 레포트"
                disabled={reportLoading}
                onClick={onReport}
              >
                <IcReport />
              </button>
            )}
          </div>
    </article>
  );

  const rowClassName = [
    'tnl-row',
    isListLayout ? 'tnl-row--gallery' : 'tnl-row--grid',
    !item.isRead ? 'tnl-row--unread' : '',
    isSelected ? 'tnl-row--selected' : '',
    receiving && isListLayout ? 'tnl-row--receiving' : '',
  ].filter(Boolean).join(' ');

  if (!isListLayout) {
    return (
      <RowTag
        ref={rowRef as React.Ref<HTMLLIElement & HTMLDivElement>}
        role={itemTag === 'div' ? 'listitem' : undefined}
        className={rowClassName}
        onClick={handleRowClick}
      >
        {summaryCard}
      </RowTag>
    );
  }

  return (
    <RowTag
      ref={rowRef as React.Ref<HTMLLIElement & HTMLDivElement>}
      role={itemTag === 'div' ? 'listitem' : undefined}
      className={rowClassName}
      onClick={handleRowClick}
    >
      <div
        className={['tnl-row-gallery', chartExpanded ? 'tnl-row-gallery--chart-expanded' : ''].filter(Boolean).join(' ')}
      >
        <TradeNotificationHScrollPane
          className="tnl-row-gallery-detail"
          label="알림 상세"
        >
          {summaryCard}
        </TradeNotificationHScrollPane>

        {chartExpanded ? (
          /* 전체보기 — 통합 차트 (캔들 + 보조지표) 를 넓게 표시 */
          <div className="tnl-row-gallery-combined-chart tnl-row-gallery-combined-chart--expanded">
            <TradeSignalChartCard
              label="캔들"
              meta={candleKo}
              market={item.market}
              timeframe={chartTf}
              theme={theme}
              indicators={allIndicatorConfigs}
              enabled={chartActive}
              expanded
              onExpand={() => setExpandedChartKey('candle')}
              onRestore={() => setExpandedChartKey(null)}
              onRealtimeActivity={chartActive ? bumpChartActivity : undefined}
              signalMarker={signalMarker}
            />
          </div>
        ) : (
          <>
            <TradeNotificationHScrollPane
              className="tnl-row-gallery-signal"
              label="신호 일치율"
            >
              <TradeNotificationSignalCard
                market={item.market}
                strategyId={item.strategyId}
                strategy={strategy}
                strategies={strategies}
                strategyLabel={strategyLabel}
                meta={strategyLabel}
                candleType={item.candleType}
                theme={theme}
                ticker={ticker}
                enabled={signalCardEnabled}
                snapshot={snapshot}
                signalLoading={signalLoading}
                onExpandCharts={() => setExpandedChartKey('candle')}
              />
            </TradeNotificationHScrollPane>

            {/* 통합 차트 — 캔들(상단) + 전략 보조지표(하단)
                key에 indicator ids를 포함하여 전략 로드 후 차트를 완전히 재마운트 */}
            <div
              className="tnl-row-gallery-combined-chart"
              aria-label="캔들 및 보조지표 차트"
            >
              <TradeSignalChartCard
                key={`combined-${item.market}-${chartTf}-${allIndicatorConfigs.map(c => c.id).join(',')}`}
                label="캔들"
                meta={candleKo}
                market={item.market}
                timeframe={chartTf}
                theme={theme}
                indicators={allIndicatorConfigs}
                enabled={chartActive}
                expanded={false}
                onExpand={() => setExpandedChartKey('candle')}
                onRestore={() => setExpandedChartKey(null)}
                onRealtimeActivity={chartActive ? bumpChartActivity : undefined}
                signalMarker={signalMarker}
              />
              {indicatorPlaceholder && (
                <div className="tnl-combined-chart-placeholder">전략 지표 로딩 중…</div>
              )}
            </div>
          </>
        )}
      </div>
    </RowTag>
  );
};

function listRowPropsEqual(prev: Props, next: Props): boolean {
  if (prev.item !== next.item) {
    if (
      prev.item.id !== next.item.id
      || prev.item.isRead !== next.item.isRead
      || prev.item.receivedAt !== next.item.receivedAt
      || prev.item.strategyId !== next.item.strategyId
      || prev.item.strategyName !== next.item.strategyName
    ) return false;
  }
  return (
    prev.theme === next.theme
    && prev.isSelected === next.isSelected
    && prev.layoutMode === next.layoutMode
    && prev.chartsEnabled === next.chartsEnabled
    && prev.chartLiveReceiveHighlight === next.chartLiveReceiveHighlight
    && prev.reportLoading === next.reportLoading
    && prev.itemTag === next.itemTag
    && prev.prefetchedStrategies === next.prefetchedStrategies
    && prev.ticker?.tradePrice === next.ticker?.tradePrice
    && prev.ticker?.changeRate === next.ticker?.changeRate
    && prev.ticker?.accTradePrice24 === next.ticker?.accTradePrice24
    && prev.onSelect === next.onSelect
    && prev.onDelete === next.onDelete
    && prev.onDetail === next.onDetail
    && prev.onGoToChart === next.onGoToChart
    && prev.onTrade === next.onTrade
    && prev.onReport === next.onReport
  );
}

export default memo(TradeNotificationListRow, listRowPropsEqual);
