/**
 * AMDZonesOverlay Component
 * Renders AMD (Accumulation, Manipulation, Distribution) zones as shaded areas on the chart
 */

import { useEffect, useRef } from 'react';
import type { IChartApi, ISeriesApi, Time } from 'lightweight-charts';

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

export type AMDPhaseType = 'accumulation' | 'manipulation' | 'distribution' | 'unknown';

export interface AMDZone {
  phase: AMDPhaseType;
  startTime: number;
  endTime: number;
  priceHigh: number;
  priceLow: number;
  confidence: number;
}

export interface AMDZonesOverlayProps {
  chartRef: React.RefObject<IChartApi>;
  zones: AMDZone[];
  visible?: boolean;
  colors?: {
    accumulation: string;
    manipulation: string;
    distribution: string;
    unknown: string;
  };
}

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

const DEFAULT_AMD_COLORS = {
  accumulation: 'rgba(59, 130, 246, 0.15)',   // Blue - calm, building
  manipulation: 'rgba(249, 115, 22, 0.15)',   // Orange - caution, volatility
  distribution: 'rgba(239, 68, 68, 0.15)',    // Red - selling pressure
  unknown: 'rgba(107, 114, 128, 0.1)',        // Gray - uncertain
};

// Border colors for zone edges
const BORDER_COLORS: Record<AMDPhaseType, string> = {
  accumulation: 'rgba(59, 130, 246, 0.5)',
  manipulation: 'rgba(249, 115, 22, 0.5)',
  distribution: 'rgba(239, 68, 68, 0.5)',
  unknown: 'rgba(107, 114, 128, 0.3)',
};

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

export const AMDZonesOverlay: React.FC<AMDZonesOverlayProps> = ({
  chartRef,
  zones,
  visible = true,
  colors = DEFAULT_AMD_COLORS,
}) => {
  const seriesMapRef = useRef<Map<string, ISeriesApi<'Area'>>>(new Map());
  const lineSeriesMapRef = useRef<Map<string, ISeriesApi<'Line'>>>(new Map());

  // Initialize and update zones
  useEffect(() => {
    if (!chartRef.current || !visible) return;

    const chart = chartRef.current;

    // Clear existing series
    seriesMapRef.current.forEach((series) => {
      try {
        chart.removeSeries(series);
      } catch {
        // Series might already be removed
      }
    });
    seriesMapRef.current.clear();

    lineSeriesMapRef.current.forEach((series) => {
      try {
        chart.removeSeries(series);
      } catch {
        // Series might already be removed
      }
    });
    lineSeriesMapRef.current.clear();

    if (zones.length === 0) return;

    // Create area series for each zone
    zones.forEach((zone, index) => {
      const zoneId = `amd-zone-${index}-${zone.phase}`;
      const zoneColor = colors[zone.phase] || DEFAULT_AMD_COLORS[zone.phase];
      const borderColor = BORDER_COLORS[zone.phase];

      // Create area series for the zone fill
      const areaSeries = chart.addAreaSeries({
        topColor: zoneColor,
        bottomColor: 'transparent',
        lineColor: 'transparent',
        lineWidth: 1,
        crosshairMarkerVisible: false,
        lastValueVisible: false,
        priceLineVisible: false,
      });

      // Calculate opacity based on confidence
      const adjustedColor = adjustColorOpacity(zoneColor, zone.confidence);

      areaSeries.applyOptions({
        topColor: adjustedColor,
      });

      // Create data points for the zone area
      const startTime = (zone.startTime / 1000) as Time;
      const endTime = (zone.endTime / 1000) as Time;

      const areaData = [
        { time: startTime, value: zone.priceHigh },
        { time: endTime, value: zone.priceHigh },
      ];

      areaSeries.setData(areaData);
      seriesMapRef.current.set(zoneId, areaSeries);

      // Create top line for visual boundary
      const topLine = chart.addLineSeries({
        color: borderColor,
        lineWidth: 1,
        lineStyle: 2, // Dashed
        crosshairMarkerVisible: false,
        lastValueVisible: false,
        priceLineVisible: false,
      });

      topLine.setData([
        { time: startTime, value: zone.priceHigh },
        { time: endTime, value: zone.priceHigh },
      ]);

      lineSeriesMapRef.current.set(`${zoneId}-top`, topLine);

      // Create bottom line for visual boundary
      const bottomLine = chart.addLineSeries({
        color: borderColor,
        lineWidth: 1,
        lineStyle: 2, // Dashed
        crosshairMarkerVisible: false,
        lastValueVisible: false,
        priceLineVisible: false,
      });

      bottomLine.setData([
        { time: startTime, value: zone.priceLow },
        { time: endTime, value: zone.priceLow },
      ]);

      lineSeriesMapRef.current.set(`${zoneId}-bottom`, bottomLine);
    });

    return () => {
      // Cleanup on unmount
      seriesMapRef.current.forEach((series) => {
        try {
          chart.removeSeries(series);
        } catch {
          // Series might already be removed
        }
      });
      seriesMapRef.current.clear();

      lineSeriesMapRef.current.forEach((series) => {
        try {
          chart.removeSeries(series);
        } catch {
          // Series might already be removed
        }
      });
      lineSeriesMapRef.current.clear();
    };
  }, [chartRef, zones, visible, colors]);

  // Update visibility
  useEffect(() => {
    seriesMapRef.current.forEach((series) => {
      series.applyOptions({ visible });
    });

    lineSeriesMapRef.current.forEach((series) => {
      series.applyOptions({ visible });
    });
  }, [visible]);

  return null;
};

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

/**
 * Adjusts the opacity of an rgba color based on confidence
 */
function adjustColorOpacity(color: string, confidence: number): string {
  // Extract rgba components
  const match = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);

  if (!match) return color;

  const r = match[1];
  const g = match[2];
  const b = match[3];
  const baseOpacity = parseFloat(match[4] || '1');

  // Scale opacity by confidence (minimum 0.05 to keep zones visible)
  const adjustedOpacity = Math.max(0.05, baseOpacity * confidence);

  return `rgba(${r}, ${g}, ${b}, ${adjustedOpacity})`;
}

export default AMDZonesOverlay;
