import React, {useRef, useState, useEffect} from "react";
import { useQuoteData } from "../QueryOptions/apiQueryOptions";
import { useQueryContext } from "../context/querycontext";
import * as echarts from 'echarts';
import ReactECharts from 'echarts-for-react';
import { type QuoteData } from "../QueryOptions/dataTypes";


const ChartComponents: React.FC = () => {
  const chartRef = useRef<ReactECharts>(null);
  const { queryOptions, isLoadingBrokers, isErrorBrokers } = 
  useQueryContext();
  const {data: quoteData, isError: isErrorQuotes } = 
    useQuoteData(queryOptions) as { data: QuoteData | undefined; isLoading: boolean; isError: boolean };


  const [showMidline, setShowMidline] = useState(false);
  
  
  const [latestValues, setLatestValues] = useState({
    lastTimestampA: null as number | null,
    lastTimestampB: null as number | null,
    lastAskA: null as number | null,
    lastBidA: null as number | null,
    lastAskB: null as number | null,
    lastBidB: null as number | null,
    lastMidlineA: null as number | null,
    lastMidlineB: null as number | null,
  });

  useEffect(() => {
    if (quoteData?.records) {
      const newLatestValues = {
        askA: null as number | null,
        bidA: null as number | null,
        midlineA: null as number | null,
        spreadA: null as number | null,
        timestampA: null as string | null,
        askB: null as number | null,
        bidB: null as number | null,
        midlineB: null as number | null,
        spreadB: null as number | null,
        timestampB: null as string | null,
      };

      for (const record of quoteData.records) {
        if (newLatestValues.askA === null && record.askA !== null) {
          newLatestValues.askA = record.askA;
          newLatestValues.bidA = record.bidA;
          newLatestValues.midlineA = record.midlineA;
          newLatestValues.spreadA = record.spreadA;
          newLatestValues.timestampA = record.timestamp;
          // console.log('Updated A in filteredData at:', record.timestamp, 'with askA:', record.askA);
        }
        if (newLatestValues.askB === null && record.askB !== null) {
          newLatestValues.askB = record.askB;
          newLatestValues.bidB = record.bidB;
          newLatestValues.midlineB = record.midlineB;
          newLatestValues.spreadB = record.spreadB;
          newLatestValues.timestampB = record.timestamp;
          // console.log('Updated B in filteredData at:', record.timestamp, 'with askB:', record.askB);
        }
      }

      const lastTimestampA = newLatestValues.timestampA ? new Date(newLatestValues.timestampA).getTime() : (quoteData.records[0]?.timestamp ? new Date(quoteData.records[0].timestamp).getTime() : null);
      const lastTimestampB = newLatestValues.timestampB ? new Date(newLatestValues.timestampB).getTime() : (quoteData.records[0]?.timestamp ? new Date(quoteData.records[0].timestamp).getTime() : null);
      setLatestValues({
        lastTimestampA,
        lastTimestampB,
        lastAskA: newLatestValues.askA,
        lastBidA: newLatestValues.bidA,
        lastAskB: newLatestValues.askB,
        lastBidB: newLatestValues.bidB,
        lastMidlineA: newLatestValues.midlineA,
        lastMidlineB: newLatestValues.midlineB,
      });

      const chartInstance = chartRef.current?.getEchartsInstance();
      if (chartInstance) {
        const timestamps = quoteData.records.map(record => new Date(record.timestamp).getTime());
        if (timestamps.length > 0) {
          const maxTimestamp = Math.max(...timestamps);
          const minTimestamp = Math.min(...timestamps);
          const range = maxTimestamp - minTimestamp;
          const last2Percent = minTimestamp + range * 0.98;

          chartInstance.setOption({
            dataZoom: [
              { startValue: last2Percent, endValue: maxTimestamp },
              { type: 'inside', startValue: last2Percent, endValue: maxTimestamp },
            ],
          }, true);

          const updateMarkLine = () => {
            if (newLatestValues.askA) {
              const option = chartInstance.getOption();
              option.series = (option.series as any[]).map((series: any) => {
                if (series.name === `Ask A (${brokerA}/${symbolA})`) {
                  return {
                    ...series,
                    markLine: {
                      data: [
                        {
                          yAxis: newLatestValues.askA,
                          lineStyle: {
                            type: 'dashed',
                            color: '#007bff',
                            width: 1,
                          },
                          label: {
                            show: true,
                            position: 'insideEndTop',
                            color: 'white',
                            fontWeight: 'bold',
                            fontSize: 12,
                            formatter: () => newLatestValues.askA!.toFixed(5),
                          },
                          silent: true,
                          animation: false,
                          clip: false,
                        },
                      ],
                    },
                  };
                }
                return series;
              });
              chartInstance.setOption(option);
            }
          };

          updateMarkLine();

          chartInstance.on('dataZoom', updateMarkLine);

          return () => {
            chartInstance.off('dataZoom', updateMarkLine);
          };
        }
      }
    }
  }, [quoteData]);


  if (isLoadingBrokers) return <div>Loading brokers...</div>;
  if (isErrorBrokers) return <div>Error loading brokers</div>;
  if (isErrorQuotes) return <div>Error loading quote data</div>;
  if (!quoteData?.records?.length) return <div>No quote data available</div>;


  const { records: filteredData, brokerA, symbolA, brokerB, symbolB } = quoteData;

  const valuesA = filteredData
    .map(records => [records.askA, records.bidA, records.midlineA])
    .flat()
    .filter((v): v is number => v !== null);
  const valuesB = filteredData
    .map(records => [records.askB, records.bidB, records.midlineB])
    .flat()
    .filter((v): v is number => v !== null);
  const buffer = 0.00001;

    

  const minValueA = valuesA.length ? Math.min(...valuesA) - buffer : 0;
  const maxValueA = valuesA.length ? Math.max(...valuesA) + buffer : 100;
  const adjustedMinValueA = Math.min(minValueA, latestValues.lastAskA || minValueA) - buffer;
  const adjustedMaxValueA = Math.max(maxValueA, latestValues.lastAskA || maxValueA) + buffer;
  const minValueB = valuesB.length ? Math.min(...valuesB) - buffer : 0;
  const maxValueB = valuesB.length ? Math.max(...valuesB) + buffer : 100;
  const adjustedMinValueB = Math.min(minValueB, latestValues.lastAskB || minValueB) - buffer;
  const adjustedMaxValueB = Math.max(maxValueB, latestValues.lastAskB || maxValueB) + buffer;


  const {
    // lastTimestampA,
    // lastTimestampB,
    lastAskA,
    lastBidA,
    lastAskB,
    lastBidB,
    // lastMidlineA,
    // lastMidlineB,
  } = latestValues;

  // const firstTimestamp = filteredData.at(0)?.timestamp;

  // console.log(`Last Timestamp A: ${lastTimestampA} last Ask A: ${lastAskA} to First Timestamp ${firstTimestamp}`);
  // console.log(`Last Ask A: ${lastAskA}`);
  // console.log('Last Bid A:', lastBidA);
  // console.log('Last Timestamp B:', lastTimestampB);
  // console.log('Last Ask B:', lastAskB);
  // console.log('Last Bid B:', lastBidB);
  // console.log('Last Midline A:', lastMidlineA);
  // console.log('Last Midline B:', lastMidlineB);

  // console.log('MarkLine Data for Ask A:', lastAskA ? [{ yAxis: lastAskA }] : 'Invalid (null)');

  const typeDataA = filteredData.filter(record => record.directionA === 'buy' || record.directionA === 'sell');
  const typeDataB = filteredData.filter(record => record.directionB === 'buy' || record.directionB === 'sell');


  const typeDataPointBidA = typeDataA.map(record => ({
    coord: [record.timestamp, record.directionA === 'buy' ? record.askA : record.bidA],
    name: record.directionA,
    itemStyle: { color: record.directionA === 'buy' ? '#00ff00' : '#ff0000' },
    symbolRotate: record.directionA === 'buy' ? 0 : 180,
    symbolOffset: record.directionA === 'buy' ? [0, 10] : [0, -10],
  }));

  const typeDataPointBidB = typeDataB.map(record => ({
    coord: [record.timestamp, record.directionB === 'buy' ? record.askB : record.bidB],
    name: record.directionB,
    itemStyle: { color: record.directionB === 'buy' ? '#00ff00' : '#ff0000' },
    symbolRotate: record.directionB === 'buy' ? 0 : 180,
    symbolOffset: record.directionB === 'buy' ? [0, 10] : [0, -10],
  }));

  const markPointDataA = {
    symbol: 'arrow',
    symbolSize: 15,
    label: {
      show: true,
      formatter: (param: any) => param.data.name === 'buy' ? 'Buy' : 'Sell',
      fontSize: 10,
      color: 'white'
    },
    data: typeDataPointBidA
  };

  const markPointDataB = {
    symbol: 'arrow',
    symbolSize: 15,
    label: {
      show: true,
      formatter: (param: any) => param.data.name === 'buy' ? 'Buy' : 'Sell',
      fontSize: 10,
      color: 'white'
    },
    data: typeDataPointBidB
  }; 

  const dataZoom = [
    { type: 'slider', xAxisIndex: 0, start: 0, end: 100, labelFormatter: (value: number) => new Date(value).toLocaleTimeString() },
    { type: 'inside', xAxisIndex: 0, start: 0, end: 100 },
    { type: 'slider', yAxisIndex: 0, start: 0, end: 100, labelFormatter: (value: number) => value.toFixed(5) },
    { type: 'inside', yAxisIndex: 0, start: 0, end: 100 },
    { type: 'slider', yAxisIndex: 1, start: 0, end: 100, labelFormatter: (value: number) => value.toFixed(5) },
    { type: 'inside', yAxisIndex: 1, start: 0, end: 100 },
  ];

  // console.log(echarts.version)

  const marklineAskA = {
    symbol: 'none',
    lineStyle: {
      type: 'dashed',
      color: '#007bff',
    },
    label: {
      show: true,
      position: 'insideEndTop',
      color: 'white',
      fontWeight: 'bold',
      fontSize: 12,
      formatter: () => lastAskA!.toFixed(5)
    },
    data: [
       [
          { coord: ['min', lastAskA] },
          { coord: ['max', lastAskA] }
        ]
    ],
    silent: true,
    animation: false,
    clip: false  
  };

  const marklineAskB = {
    symbol: 'none',
    lineStyle: {
      type: 'dashed',
      color: '#ff4500',
    },
    label: {
      show: true,
      position: 'insideEndTop',
      color: 'white',
      fontWeight: 'bold',
      fontSize: 12,
      formatter: () => lastAskB!.toFixed(5)
    },
    data: [
       [
          { coord: ['min', lastAskB] },
          { coord: ['max', lastAskB] }
        ]
    ],
    silent: true,
    animation: false,
    clip: false  
  };

  const marklineBidA = {
    symbol: 'none',
    lineStyle: {
      type: 'dashed',
      color: '#00b7eb',
    },
    label: {
      show: true,
      position: 'insideEndTop',
      color: 'white',
      fontWeight: 'bold',
      fontSize: 12,
      formatter: () => lastBidA!.toFixed(5)
    },
    data: [
       [
          { coord: ['min', lastBidA] },
          { coord: ['max', lastBidA] }
        ]
    ],
    silent: true,
    animation: false,
    clip: false  
  };

  const marklineBidB = {
    symbol: 'none',
    lineStyle: {
      type: 'dashed',
      color: '#ff8c00',
    },
    label: {
      show: true,
      position: 'insideEndTop',
      color: 'white',
      fontWeight: 'bold',
      fontSize: 12,
      formatter: () => lastBidB!.toFixed(5)
    },
    data: [
       [
          { coord: ['min', lastBidB] },
          { coord: ['max', lastBidB] }
        ]
    ],
    silent: true,
    animation: false,
    clip: false  
  };


  const option = {
    dataset: {
      source: filteredData,
      dimensions: ['timestamp', 'askA', 'askB', 'bidA', 'bidB', 'midlineA', 'midlineB'],
    },
    tooltip: {
      trigger: 'axis',
      formatter: (params: any) => {
        const date = new Date(params[0].value[0]);
        return (
          `Time: ${date.toLocaleTimeString()}<br>` +
          params
            .map((p: any) => `${p.seriesName}: ${p.value[1] != null ? p.value[1].toFixed(5) : 'N/A'}`)
            .join('<br>')
        );
      },
    },
    legend: {
      data: [
        `Ask A (${brokerA}/${symbolA})`,
        `Bid A (${brokerA}/${symbolA})`,
        `Midline A (${brokerA}/${symbolA})`,
        // `Spread A (${brokerA}/${symbolA})`,
        `Ask B (${brokerB}/${symbolB})`,
        `Bid B (${brokerB}/${symbolB})`,
        `Midline B (${brokerB}/${symbolB})`,
        // `Spread B (${brokerB}/${symbolB})`,
      ],
      selected: {
        [`Ask A (${brokerA}/${symbolA})`]: !showMidline,
        [`Bid A (${brokerA}/${symbolA})`]: !showMidline,
        [`Ask B (${brokerB}/${symbolB})`]: !showMidline,
        [`Bid B (${brokerB}/${symbolB})`]: !showMidline,
        [`Midline A (${brokerA}/${symbolA})`]: showMidline,
        [`Midline B (${brokerB}/${symbolB})`]: showMidline,
        // [`Spread A (${brokerA}/${symbolA})`]: showMidline,
        // [`Spread B (${brokerB}/${symbolB})`]: showMidline,
      },
    },
    grid: { left: '5%', right: '5%', bottom: '15%', containLabel: true },
    toolbox: { feature: { dataZoom: {}, saveAsImage: {}, brush: { type: ['rect', 'polygon', 'clear'] } } },
    dataZoom,
    xAxis: {
      type: 'time',
      name: 'Timestamp',
      axisLabel: { formatter: (value: number) => new Date(value).toLocaleString() },
    },
    yAxis: [
      {
        type: 'value',
        name: `${brokerA}/${symbolA}`,
        min: adjustedMinValueA,
        max: adjustedMaxValueA,
        position: 'left',
        axisLabel: { formatter: (value: number) => value.toFixed(5) },
        scale: true,
        splitNumber: 10,
      },
      {
        type: 'value',
        name: `${brokerB}/${symbolB}`,
        min: adjustedMinValueB,
        max: adjustedMaxValueB,
        position: 'right',
        axisLabel: { formatter: (value: number) => value.toFixed(5) },
        scale: true,
        splitNumber: 10,
      },
    ],
    series: [
      {
        name: `Ask A (${brokerA}/${symbolA})`,
        type: 'line',
        data: filteredData.filter(record => record.askA !== null).map(record => [record.timestamp, record.askA]),
        yAxisIndex: 0,
        lineStyle: { color: '#007bff', width: 2 },
        itemStyle: { color: '#007bff' },
        showSymbol: false,
        connectNulls: false,
        markLine: marklineAskA,
      },
      {
        name: `Bid A (${brokerA}/${symbolA})`,
        type: 'line',
        data: filteredData.filter(record => record.bidA !== null).map(record => [record.timestamp, record.bidA]),
        yAxisIndex: 0,
        lineStyle: { color: '#00b7eb', type: 'dashed', width: 2 },
        itemStyle: { color: '#00b7eb' },
        showSymbol: false,
        connectNulls: false,
        markPoint: markPointDataA,
        markLine: marklineBidA,
      },
      {
        name: `Midline A (${brokerA}/${symbolA})`,
        type: 'line',
        data: filteredData.filter(record => record.midlineA !== null).map(record => [record.timestamp, record.midlineA]),
        yAxisIndex: 0,
        lineStyle: { color: '#28a745', width: 2 },
        itemStyle: { color: '#28a745' },
        showSymbol: false,
        connectNulls: false,
        
      },
      // {
      //   name: `Spread A (${brokerA}/${symbolA})`,
      //   type: 'line',
      //   data: filteredData.filter(record => record.spreadA !== null).map(record => [record.timestamp, record.spreadA]),
      //   yAxisIndex: 0,
      //   lineStyle: { color: '#6f42c1', width: 2 },
      //   itemStyle: { color: '#6f42c1' },
      //   showSymbol: false,
      //   connectNulls: false,
      // },
      {
        name: `Ask B (${brokerB}/${symbolB})`,
        type: 'line',
        data: filteredData.filter(record => record.askB !== null).map(record => [record.timestamp, record.askB]),
        yAxisIndex: 1,
        lineStyle: { color: '#ff4500', width: 2 },
        itemStyle: { color: '#ff4500' },
        showSymbol: false,
        connectNulls: false,
        markLine: marklineAskB,
      },
      {
        name: `Bid B (${brokerB}/${symbolB})`,
        type: 'line',
        data: filteredData.filter(record => record.bidB !== null).map(record => [record.timestamp, record.bidB]),
        yAxisIndex: 1,
        lineStyle: { color: '#ff8c00', type: 'dashed', width: 2 },
        itemStyle: { color: '#ff8c00' },
        showSymbol: false,
        connectNulls: false,
        markPoint: markPointDataB,
        maekLine: marklineBidB,
      },
      {
        name: `Midline B (${brokerB}/${symbolB})`,
        type: 'line',
        data: filteredData.filter(record => record.midlineB !== null).map(record => [record.timestamp, record.midlineB]),
        yAxisIndex: 1,
        lineStyle: { color: '#9932cc', width: 2 },
        itemStyle: { color: '#9932cc' },
        showSymbol: false,
        connectNulls: false,
      },
      // {
      //   name: `Spread B (${brokerB}/${symbolB})`,
      //   type: 'line',
      //   data: filteredData.filter(record => record.spreadB !== null).map(record => [record.timestamp, record.spreadB]),
      //   yAxisIndex: 1,
      //   lineStyle: { color: '#dc3545', width: 2 },
      //   itemStyle: { color: '#dc3545' },
      //   showSymbol: false,
      //   connectNulls: false,
      // },
    ],
  };

    
  return (
    <div className="p-4">
      <h2 className="text-2xl font-bold text-gray-800 dark:text-gray-500 mb-4">Quote Chart</h2>
      <div className="flex space-x-4 mb-4">
        <label className="flex items-center space-x-2 text-gray-700 dark:text-gray-500">
          <input
            type="radio"
            name="chartMode"
            checked={!showMidline}
            onChange={() => setShowMidline(false)}
            className="form-radio text-blue-500 focus:ring-blue-500"
          />
          <span>Show Ask/Bid/Spread</span>
        </label>
        <label className="flex items-center space-x-2 text-gray-700 dark:text-gray-500">
          <input
            type="radio"
            name="chartMode"
            checked={showMidline}
            onChange={() => setShowMidline(true)}
            className="form-radio text-blue-500 focus:ring-blue-500"
          />
          <span>Show Midline</span>
        </label>
      </div>
      <ReactECharts
        echarts={echarts}
        ref={chartRef}
        option={option}
        style={{ height: 600, width: '100%' }}
        opts={{ renderer: 'canvas' }}
        theme="dark"
      />
    </div>
  );

};

export default ChartComponents;