/**
 * SignalMarkers Component
 * Renders buy/sell/hold signal markers on the trading chart
 * Supports custom colors, shapes, and enhanced tooltips
 */

import { useEffect, useRef, useCallback } from 'react';
import type { IChartApi, ISeriesApi, Time, SeriesMarker } from 'lightweight-charts';
import type { SignalMarker } from '../../../../../types/mlOverlay.types';

// ============================================================================
// Types
// ============================================================================

export type SignalType = 'BUY' | 'SELL' | 'HOLD';

export interface EnhancedSignalMarker extends SignalMarker {
  signalType?: SignalType;
  confidence?: number;
  price?: number;
  stopLoss?: number;
  takeProfit?: number;
  riskReward?: number;
}

export interface SignalMarkersProps {
  chartRef: React.RefObject<IChartApi>;
  candleSeriesRef: React.RefObject<ISeriesApi<'Candlestick'>>;
  signals: EnhancedSignalMarker[];
  visible?: boolean;
  colors?: {
    buy: string;
    sell: string;
    hold: string;
  };
  showConfidence?: boolean;
  onSignalClick?: (signal: EnhancedSignalMarker) => void;
}

// ============================================================================
// Default Colors
// ============================================================================

const DEFAULT_COLORS = {
  buy: '#10b981',
  sell: '#ef4444',
  hold: '#f59e0b',
};

// ============================================================================
// Helper Functions
// ============================================================================

function getSignalColor(
  signal: EnhancedSignalMarker,
  colors: typeof DEFAULT_COLORS
): string {
  if (signal.color) return signal.color;

  switch (signal.signalType) {
    case 'BUY':
      return colors.buy;
    case 'SELL':
      return colors.sell;
    case 'HOLD':
      return colors.hold;
    default:
      return colors.hold;
  }
}

function getSignalShape(signalType?: SignalType): 'arrowUp' | 'arrowDown' | 'circle' {
  switch (signalType) {
    case 'BUY':
      return 'arrowUp';
    case 'SELL':
      return 'arrowDown';
    case 'HOLD':
      return 'circle';
    default:
      return 'circle';
  }
}

function getSignalPosition(signalType?: SignalType): 'aboveBar' | 'belowBar' {
  switch (signalType) {
    case 'BUY':
      return 'belowBar';
    case 'SELL':
      return 'aboveBar';
    default:
      return 'aboveBar';
  }
}

function formatSignalText(signal: EnhancedSignalMarker, showConfidence: boolean): string {
  const parts: string[] = [];

  if (signal.signalType) {
    parts.push(signal.signalType);
  }

  if (showConfidence && signal.confidence !== undefined) {
    parts.push(`${Math.round(signal.confidence * 100)}%`);
  }

  if (signal.riskReward !== undefined) {
    parts.push(`RR:${signal.riskReward.toFixed(1)}`);
  }

  return parts.join(' ') || signal.text;
}

function convertToLightweightMarkers(
  signals: EnhancedSignalMarker[],
  colors: typeof DEFAULT_COLORS,
  showConfidence: boolean
): SeriesMarker<Time>[] {
  return signals.map((signal) => ({
    time: (signal.time / 1000) as Time,
    position: signal.position || getSignalPosition(signal.signalType),
    color: getSignalColor(signal, colors),
    shape: signal.shape || getSignalShape(signal.signalType),
    text: formatSignalText(signal, showConfidence),
    size: signal.confidence ? Math.max(1, Math.min(3, Math.round(signal.confidence * 3))) : 2,
  }));
}

// ============================================================================
// Component
// ============================================================================

export const SignalMarkers: React.FC<SignalMarkersProps> = ({
  chartRef,
  candleSeriesRef,
  signals,
  visible = true,
  colors = DEFAULT_COLORS,
  showConfidence = true,
  onSignalClick,
}) => {
  const markersSetRef = useRef(false);
  const signalsRef = useRef<EnhancedSignalMarker[]>([]);

  // Store signals for click handling
  useEffect(() => {
    signalsRef.current = signals;
  }, [signals]);

  // Handle chart click to detect signal clicks
  const handleChartClick = useCallback(
    (param: { time?: Time; point?: { x: number; y: number } }) => {
      if (!param.time || !onSignalClick || signalsRef.current.length === 0) return;

      const clickedTime = param.time as number;

      // Find signal closest to clicked time
      const tolerance = 3600; // 1 hour tolerance
      const clickedSignal = signalsRef.current.find((signal) => {
        const signalTime = signal.time / 1000;
        return Math.abs(signalTime - clickedTime) < tolerance;
      });

      if (clickedSignal) {
        onSignalClick(clickedSignal);
      }
    },
    [onSignalClick]
  );

  // Subscribe to chart clicks
  useEffect(() => {
    if (!chartRef.current || !onSignalClick) return;

    const chart = chartRef.current;
    chart.subscribeClick(handleChartClick);

    return () => {
      chart.unsubscribeClick(handleChartClick);
    };
  }, [chartRef, handleChartClick, onSignalClick]);

  // Update markers
  useEffect(() => {
    if (!chartRef.current || !candleSeriesRef.current) {
      return;
    }

    const candleSeries = candleSeriesRef.current;

    if (!visible || signals.length === 0) {
      // Clear markers if not visible or no signals
      if (markersSetRef.current) {
        candleSeries.setMarkers([]);
        markersSetRef.current = false;
      }
      return;
    }

    // Convert and set markers
    const markers = convertToLightweightMarkers(signals, colors, showConfidence);

    // Sort markers by time (required by lightweight-charts)
    markers.sort((a, b) => (a.time as number) - (b.time as number));

    candleSeries.setMarkers(markers);
    markersSetRef.current = true;

    return () => {
      // Clear markers on cleanup
      if (markersSetRef.current && candleSeriesRef.current) {
        try {
          candleSeriesRef.current.setMarkers([]);
        } catch {
          // Series might be removed
        }
        markersSetRef.current = false;
      }
    };
  }, [chartRef, candleSeriesRef, signals, visible, colors, showConfidence]);

  return null;
};

export default SignalMarkers;
