<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
import Card from 'primevue/card'
import { createTradingViewDatafeed } from '../composables/useTradingViewDatafeed'
import { useTradingViewShapes } from '../composables/useTradingViewShapes'
import { useTradingViewIndicators } from '../composables/useTradingViewIndicators'
import { useChartStore } from '../stores/chart'
import type { IChartingLibraryWidget } from '../types/tradingview'

const chartContainer = ref<HTMLDivElement | null>(null)
const chartStore = useChartStore()
let tvWidget: IChartingLibraryWidget | null = null
let datafeed: any = null
let isUpdatingFromChart = false // Flag to prevent circular updates
let shapeCleanup: (() => void) | null = null // Cleanup function for shape sync
let indicatorCleanup: (() => void) | null = null // Cleanup function for indicator sync

onMounted(() => {
  if (!chartContainer.value) return

  // Wait for TradingView library to load
  const initChart = () => {
    if (!window.TradingView) {
      setTimeout(initChart, 100)
      return
    }

    try {
      datafeed = createTradingViewDatafeed()

      tvWidget = new window.TradingView.widget({
        symbol: chartStore.chart_state.symbol, // Use symbol from store
        datafeed: datafeed,
        interval: chartStore.chart_state.interval as any,
        container: chartContainer.value!,
        library_path: '/charting_library/',
        locale: 'en',
        disabled_features: [
          'use_localstorage_for_settings',
          'header_symbol_search',
          'symbol_search_hot_key'
        ],
        enabled_features: ['study_templates'],
        // Restrict indicators to only those supported by both TA-Lib and TradingView
        studies_access: {
          type: 'white',
          tools: [
            // Overlap Studies (14)
            { name: 'Moving Average' },
            { name: 'Moving Average Exponential' },
            { name: 'Weighted Moving Average' },
            { name: 'DEMA' },
            { name: 'TEMA' },
            { name: 'Triangular Moving Average' },
            { name: 'KAMA' },
            { name: 'MESA Adaptive Moving Average' },
            { name: 'T3' },
            { name: 'Bollinger Bands' },
            { name: 'Midpoint' },
            { name: 'Midprice' },
            { name: 'Parabolic SAR' },
            { name: 'Hilbert Transform - Instantaneous Trendline' },
            // Momentum Indicators (21)
            { name: 'Relative Strength Index' },
            { name: 'Momentum' },
            { name: 'Rate of Change' },
            { name: 'TRIX' },
            { name: 'Chande Momentum Oscillator' },
            { name: 'Directional Movement Index' },
            { name: 'Average Directional Movement Index' },
            { name: 'Average Directional Movement Index Rating' },
            { name: 'Absolute Price Oscillator' },
            { name: 'Percentage Price Oscillator' },
            { name: 'MACD' },
            { name: 'Money Flow Index' },
            { name: 'Stochastic' },
            { name: 'Stochastic Fast' },
            { name: 'Stochastic RSI' },
            { name: 'Williams %R' },
            { name: 'Commodity Channel Index' },
            { name: 'Aroon' },
            { name: 'Aroon Oscillator' },
            { name: 'Balance Of Power' },
            { name: 'Ultimate Oscillator' },
            // Volume Indicators (3)
            { name: 'Chaikin A/D Line' },
            { name: 'Chaikin A/D Oscillator' },
            { name: 'On Balance Volume' },
            // Volatility Indicators (3)
            { name: 'Average True Range' },
            { name: 'Normalized Average True Range' },
            { name: 'True Range' },
            // Price Transform (4)
            { name: 'Average Price' },
            { name: 'Median Price' },
            { name: 'Typical Price' },
            { name: 'Weighted Close Price' },
            // Cycle Indicators (5)
            { name: 'Hilbert Transform - Dominant Cycle Period' },
            { name: 'Hilbert Transform - Dominant Cycle Phase' },
            { name: 'Hilbert Transform - Phasor Components' },
            { name: 'Hilbert Transform - SineWave' },
            { name: 'Hilbert Transform - Trend vs Cycle Mode' },
            // Statistic Functions (9)
            { name: 'Beta' },
            { name: 'Pearson\'s Correlation Coefficient' },
            { name: 'Linear Regression' },
            { name: 'Linear Regression Angle' },
            { name: 'Linear Regression Intercept' },
            { name: 'Linear Regression Slope' },
            { name: 'Standard Deviation' },
            { name: 'Time Series Forecast' },
            { name: 'Variance' },
            // Custom Indicators (12)
            { name: 'VWAP' },
            { name: 'VWMA' },
            { name: 'Hull Moving Average' },
            { name: 'SuperTrend' },
            { name: 'Donchian Channels' },
            { name: 'Keltner Channels' },
            { name: 'Chaikin Money Flow' },
            { name: 'Vortex Indicator' },
            { name: 'Awesome Oscillator' },
            { name: 'Accelerator Oscillator' },
            { name: 'Choppiness Index' },
            { name: 'Mass Index' }
          ]
        },
        fullscreen: false,
        autosize: true,
        theme: 'Dark',
        timezone: 'Etc/UTC'
      })

      tvWidget.onChartReady(() => {
        console.log('TradingView chart ready')
        setupChartListeners()
        setupStoreWatchers()
        // Initialize visible range on chart load
        initializeVisibleRange()
        // Setup shape synchronization
        if (tvWidget) {
          shapeCleanup = useTradingViewShapes(tvWidget)
          indicatorCleanup = useTradingViewIndicators(tvWidget)
        }
      })
    } catch (error) {
      console.error('Failed to initialize TradingView widget:', error)
    }
  }

  initChart()
})

function initializeVisibleRange() {
  if (!tvWidget) return

  const chart = tvWidget.activeChart()
  const timeScale = chart.getVisibleRange()

  if (timeScale) {
    const startTime = Math.floor(timeScale.from)
    const endTime = Math.floor(timeScale.to)

    console.log('[ChartView] Initial visible range:', {
      from: new Date(startTime * 1000).toISOString(),
      to: new Date(endTime * 1000).toISOString()
    })

    chartStore.chart_state.start_time = startTime
    chartStore.chart_state.end_time = endTime
  }
}

function setupChartListeners() {
  if (!tvWidget) return

  const chart = tvWidget.activeChart()

  // Listen for symbol changes
  chart.onSymbolChanged().subscribe(null, () => {
    const symbolInfo = chart.symbolExt()
    if (symbolInfo && symbolInfo.ticker) {
      console.log('[ChartView] Symbol changed to:', symbolInfo.ticker)
      isUpdatingFromChart = true
      chartStore.chart_state.symbol = symbolInfo.ticker
      isUpdatingFromChart = false
    }
  })

  // Listen for interval changes
  chart.onIntervalChanged().subscribe(null, (interval: string) => {
    console.log('[ChartView] Interval changed to:', interval)
    isUpdatingFromChart = true
    chartStore.chart_state.interval = interval
    isUpdatingFromChart = false
  })

  // Listen for visible range changes (when user pans/zooms)
  chart.onVisibleRangeChanged().subscribe(null, () => {
    const timeScale = chart.getVisibleRange()
    if (timeScale) {
      // Convert from seconds to seconds (TradingView uses seconds for visible range)
      const startTime = Math.floor(timeScale.from)
      const endTime = Math.floor(timeScale.to)

      console.log('[ChartView] Visible range changed:', {
        from: new Date(startTime * 1000).toISOString(),
        to: new Date(endTime * 1000).toISOString()
      })

      isUpdatingFromChart = true
      chartStore.chart_state.start_time = startTime
      chartStore.chart_state.end_time = endTime
      isUpdatingFromChart = false
    }
  })
}

function setupStoreWatchers() {
  if (!tvWidget) return

  const chart = tvWidget.activeChart()

  // Watch for external changes to symbol (e.g., from backend/agent)
  watch(
    () => chartStore.chart_state.symbol,
    (newSymbol) => {
      if (isUpdatingFromChart) return // Ignore updates that came from the chart itself

      console.log('[ChartView] Store symbol changed externally to:', newSymbol)
      const currentSymbol = chart.symbolExt()
      if (currentSymbol && currentSymbol.ticker !== newSymbol) {
        chart.setSymbol(newSymbol, () => {
          console.log('[ChartView] Chart symbol updated to:', newSymbol)
        })
      }
    }
  )

  // Watch for external changes to interval
  watch(
    () => chartStore.chart_state.interval,
    (newInterval) => {
      if (isUpdatingFromChart) return

      console.log('[ChartView] Store interval changed externally to:', newInterval)
      if (chart.resolution() !== newInterval) {
        chart.setResolution(newInterval, () => {
          console.log('[ChartView] Chart interval updated to:', newInterval)
        })
      }
    }
  )

  // Note: Visible range is typically only set by user interaction,
  // but we could add a watcher here if we want the backend to be able
  // to change the visible range programmatically
}

onBeforeUnmount(() => {
  // Cleanup shape synchronization
  if (shapeCleanup) {
    shapeCleanup()
    shapeCleanup = null
  }

  // Cleanup indicator synchronization
  if (indicatorCleanup) {
    indicatorCleanup()
    indicatorCleanup = null
  }

  if (tvWidget) {
    tvWidget.remove()
    tvWidget = null
  }
  if (datafeed && typeof datafeed.destroy === 'function') {
    datafeed.destroy()
    datafeed = null
  }
})
</script>

<template>
  <Card class="chart-card">
    <template #content>
      <div ref="chartContainer" class="chart-container"></div>
    </template>
  </Card>
</template>

<style scoped>
.chart-card {
  height: 100% !important;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: none;
  border-radius: 0 !important;
  background: var(--p-surface-0);
}

.chart-card :deep(.p-card) {
  border-radius: 0 !important;
}

.chart-card :deep(.p-card-body) {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 0;
  overflow: hidden;
}

.chart-card :deep(.p-card-content) {
  flex: 1;
  display: flex;
  overflow: hidden;
  padding: 0;
}

.chart-container {
  flex: 1;
  width: 100%;
  height: 100%;
}
</style>
