import { useRef, useCallback, useEffect } from 'react';
import * as LightweightCharts from 'lightweight-charts';

interface ChartInstance {
  chart: LightweightCharts.IChartApi;
  mainSeries: LightweightCharts.ISeriesApi<any> | null;
  volumeSeries: LightweightCharts.ISeriesApi<any> | null;
  overlaySeries: Map<string, LightweightCharts.ISeriesApi<any>>;
  isDisposed: boolean;
}

export function useChartManager() {
  const instancesRef = useRef<Map<string, ChartInstance>>(new Map());

  const disposeChart = useCallback((id: string) => {
    const instance = instancesRef.current.get(id);
    if (!instance || instance.isDisposed) {
      return;
    }

    // Mark as disposed first to prevent any further operations
    instance.isDisposed = true;

    try {
      // Disable all chart updates before removal
      const chart = instance.chart;
      
      // Stop all animations and pending operations
      if (chart.timeScale) {
        try {
          chart.timeScale().unsubscribeVisibleLogicalRangeChange();
        } catch (e) {
          // Ignore
        }
      }
      
      // Clear all series references
      instance.mainSeries = null;
      instance.volumeSeries = null;
      instance.overlaySeries.clear();

      // Remove the chart
      chart.remove();
    } catch (error) {
      // Only log if it's not a disposed error
      if (!error?.message?.includes('disposed')) {
        console.error('Error disposing chart:', error);
      }
    } finally {
      // Remove from instances map
      instancesRef.current.delete(id);
    }
  }, []);

  const createChart = useCallback((
    id: string,
    container: HTMLElement,
    options: LightweightCharts.DeepPartial<LightweightCharts.ChartOptions>
  ): LightweightCharts.IChartApi | null => {
    // Dispose any existing chart with this ID first
    disposeChart(id);

    try {
      const chart = LightweightCharts.createChart(container, options);
      const instance: ChartInstance = {
        chart,
        mainSeries: null,
        volumeSeries: null,
        overlaySeries: new Map(),
        isDisposed: false,
      };
      
      // Wrap chart methods to check disposal state
      const originalApplyOptions = chart.applyOptions.bind(chart);
      chart.applyOptions = (options: any) => {
        if (!instance.isDisposed) {
          originalApplyOptions(options);
        }
      };
      
      const originalTimeScale = chart.timeScale.bind(chart);
      chart.timeScale = () => {
        if (instance.isDisposed) {
          // Return a mock object that does nothing
          return {
            fitContent: () => {},
            setVisibleRange: () => {},
            getVisibleRange: () => null,
            scrollToPosition: () => {},
            applyOptions: () => {},
            options: () => ({}),
            subscribeVisibleTimeRangeChange: () => {},
            unsubscribeVisibleTimeRangeChange: () => {},
            subscribeVisibleLogicalRangeChange: () => {},
            unsubscribeVisibleLogicalRangeChange: () => {},
          } as any;
        }
        return originalTimeScale();
      };
      
      instancesRef.current.set(id, instance);
      return chart;
    } catch (error) {
      console.error('Failed to create chart:', error);
      return null;
    }
  }, [disposeChart]);

  const getChart = useCallback((id: string): ChartInstance | null => {
    const instance = instancesRef.current.get(id);
    if (!instance || instance.isDisposed) {
      return null;
    }
    return instance;
  }, []);

  const setMainSeries = useCallback((id: string, series: LightweightCharts.ISeriesApi<any> | null) => {
    const instance = getChart(id);
    if (instance) {
      instance.mainSeries = series;
    }
  }, [getChart]);

  const setVolumeSeries = useCallback((id: string, series: LightweightCharts.ISeriesApi<any> | null) => {
    const instance = getChart(id);
    if (instance) {
      instance.volumeSeries = series;
    }
  }, [getChart]);

  const addOverlaySeries = useCallback((id: string, name: string, series: LightweightCharts.ISeriesApi<any>) => {
    const instance = getChart(id);
    if (instance) {
      instance.overlaySeries.set(name, series);
    }
  }, [getChart]);

  const disposeAllCharts = useCallback(() => {
    const ids = Array.from(instancesRef.current.keys());
    ids.forEach(id => disposeChart(id));
  }, [disposeChart]);

  // Cleanup on unmount
  useEffect(() => {
    return () => {
      disposeAllCharts();
    };
  }, [disposeAllCharts]);

  return {
    createChart,
    getChart,
    setMainSeries,
    setVolumeSeries,
    addOverlaySeries,
    disposeChart,
    disposeAllCharts,
  };
}