import { watch } from 'vue'
import type { IChartingLibraryWidget, IStudyApi } from '../types/tradingview'
import { useIndicatorStore } from '../stores/indicators'
import { useChartStore } from '../stores/chart'
import type { IndicatorInstance } from '../stores/indicators'

/**
 * Mapping between TA-Lib indicator names and TradingView indicator names
 * Only includes indicators that are present in BOTH systems (inner join)
 */
const TALIB_TO_TV_NAMES: Record<string, string> = {
  // Overlap Studies (14)
  'SMA': 'Moving Average',
  'EMA': 'Moving Average Exponential',
  'WMA': 'Weighted Moving Average',
  'DEMA': 'DEMA',
  'TEMA': 'TEMA',
  'TRIMA': 'Triangular Moving Average',
  'KAMA': 'KAMA',
  'MAMA': 'MESA Adaptive Moving Average',
  'T3': 'T3',
  'BBANDS': 'Bollinger Bands',
  'MIDPOINT': 'Midpoint',
  'MIDPRICE': 'Midprice',
  'SAR': 'Parabolic SAR',
  'HT_TRENDLINE': 'Hilbert Transform - Instantaneous Trendline',

  // Momentum Indicators (21)
  'RSI': 'Relative Strength Index',
  'MOM': 'Momentum',
  'ROC': 'Rate of Change',
  'TRIX': 'TRIX',
  'CMO': 'Chande Momentum Oscillator',
  'DX': 'Directional Movement Index',
  'ADX': 'Average Directional Movement Index',
  'ADXR': 'Average Directional Movement Index Rating',
  'APO': 'Absolute Price Oscillator',
  'PPO': 'Percentage Price Oscillator',
  'MACD': 'MACD',
  'MFI': 'Money Flow Index',
  'STOCH': 'Stochastic',
  'STOCHF': 'Stochastic Fast',
  'STOCHRSI': 'Stochastic RSI',
  'WILLR': 'Williams %R',
  'CCI': 'Commodity Channel Index',
  'AROON': 'Aroon',
  'AROONOSC': 'Aroon Oscillator',
  'BOP': 'Balance Of Power',
  'ULTOSC': 'Ultimate Oscillator',

  // Volume Indicators (3)
  'AD': 'Chaikin A/D Line',
  'ADOSC': 'Chaikin A/D Oscillator',
  'OBV': 'On Balance Volume',

  // Volatility Indicators (3)
  'ATR': 'Average True Range',
  'NATR': 'Normalized Average True Range',
  'TRANGE': 'True Range',

  // Price Transform (4)
  'AVGPRICE': 'Average Price',
  'MEDPRICE': 'Median Price',
  'TYPPRICE': 'Typical Price',
  'WCLPRICE': 'Weighted Close Price',

  // Cycle Indicators (5)
  'HT_DCPERIOD': 'Hilbert Transform - Dominant Cycle Period',
  'HT_DCPHASE': 'Hilbert Transform - Dominant Cycle Phase',
  'HT_PHASOR': 'Hilbert Transform - Phasor Components',
  'HT_SINE': 'Hilbert Transform - SineWave',
  'HT_TRENDMODE': 'Hilbert Transform - Trend vs Cycle Mode',

  // Statistic Functions (9)
  'BETA': 'Beta',
  'CORREL': 'Pearson\'s Correlation Coefficient',
  'LINEARREG': 'Linear Regression',
  'LINEARREG_ANGLE': 'Linear Regression Angle',
  'LINEARREG_INTERCEPT': 'Linear Regression Intercept',
  'LINEARREG_SLOPE': 'Linear Regression Slope',
  'STDDEV': 'Standard Deviation',
  'TSF': 'Time Series Forecast',
  'VAR': 'Variance',
}

// Total: 60 TA-Lib indicators

/**
 * Custom indicators (implemented in backend, not in TA-Lib)
 */
const CUSTOM_TO_TV_NAMES: Record<string, string> = {
  'VWAP': 'VWAP',
  'VWMA': 'VWMA',
  'HMA': 'Hull Moving Average',
  'SUPERTREND': 'SuperTrend',
  'DONCHIAN': 'Donchian Channels',
  'KELTNER': 'Keltner Channels',
  'CMF': 'Chaikin Money Flow',
  'VORTEX': 'Vortex Indicator',
  'AO': 'Awesome Oscillator',
  'AC': 'Accelerator Oscillator',
  'CHOP': 'Choppiness Index',
  'MASS': 'Mass Index',
}

// Combined mapping (TA-Lib + Custom)
const ALL_BACKEND_TO_TV_NAMES: Record<string, string> = {
  ...TALIB_TO_TV_NAMES,
  ...CUSTOM_TO_TV_NAMES
}

// Total: 72 indicators (60 TA-Lib + 12 Custom)

/**
 * Reverse mapping from TradingView to backend
 */
const TV_TO_TALIB_NAMES: Record<string, string> = Object.fromEntries(
  Object.entries(TALIB_TO_TV_NAMES).map(([k, v]) => [v, k])
)

const TV_TO_CUSTOM_NAMES: Record<string, string> = Object.fromEntries(
  Object.entries(CUSTOM_TO_TV_NAMES).map(([k, v]) => [v, k])
)

const TV_TO_BACKEND_NAMES: Record<string, string> = Object.fromEntries(
  Object.entries(ALL_BACKEND_TO_TV_NAMES).map(([k, v]) => [v, k])
)

/**
 * Convert TA-Lib parameters to TradingView inputs
 */
function convertTALibParamsToTVInputs(talibName: string, talibParams: Record<string, any>): Record<string, any> {
  const tvInputs: Record<string, any> = {}

  // Common parameter mappings
  const paramMapping: Record<string, string> = {
    'timeperiod': 'length',
    'fastperiod': 'fastLength',
    'slowperiod': 'slowLength',
    'signalperiod': 'signalLength',
    'nbdevup': 'mult',
    'nbdevdn': 'mult',
    'fastlimit': 'fastLimit',
    'slowlimit': 'slowLimit',
    'acceleration': 'start',
    'maximum': 'increment',
    'fastk_period': 'kPeriod',
    'slowk_period': 'kPeriod',
    'slowd_period': 'dPeriod',
    'fastd_period': 'dPeriod',
  }

  // Special handling for specific indicators
  if (talibName === 'BBANDS') {
    tvInputs.length = talibParams.timeperiod || 20
    tvInputs.mult = talibParams.nbdevup || 2
    tvInputs.source = 'close'
  } else if (talibName === 'MACD') {
    tvInputs.fastLength = talibParams.fastperiod || 12
    tvInputs.slowLength = talibParams.slowperiod || 26
    tvInputs.signalLength = talibParams.signalperiod || 9
    tvInputs.source = 'close'
  } else if (talibName === 'RSI') {
    tvInputs.length = talibParams.timeperiod || 14
    tvInputs.source = 'close'
  } else if (['SMA', 'EMA', 'WMA', 'DEMA', 'TEMA', 'TRIMA'].includes(talibName)) {
    tvInputs.length = talibParams.timeperiod || 14
    tvInputs.source = 'close'
  } else if (talibName === 'STOCH') {
    tvInputs.kPeriod = talibParams.fastk_period || 14
    tvInputs.dPeriod = talibParams.slowd_period || 3
    tvInputs.smoothK = talibParams.slowk_period || 3
  } else if (talibName === 'ATR') {
    tvInputs.length = talibParams.timeperiod || 14
  } else if (talibName === 'CCI') {
    tvInputs.length = talibParams.timeperiod || 20
  } else {
    // Generic parameter conversion
    for (const [talibParam, value] of Object.entries(talibParams)) {
      const tvParam = paramMapping[talibParam] || talibParam
      tvInputs[tvParam] = value
    }
  }

  return tvInputs
}

/**
 * Convert TradingView inputs to TA-Lib parameters
 */
function convertTVInputsToTALibParams(tvName: string, tvInputs: Record<string, any>): { talibName: string | null, talibParams: Record<string, any> } {
  const talibName = TV_TO_BACKEND_NAMES[tvName] || null
  if (!talibName) {
    console.warn('[Indicators] No backend mapping for TradingView indicator:', tvName)
    return { talibName: null, talibParams: {} }
  }

  const talibParams: Record<string, any> = {}

  // Reverse parameter mappings
  const reverseMapping: Record<string, string> = {
    'length': 'timeperiod',
    'fastLength': 'fastperiod',
    'slowLength': 'slowperiod',
    'signalLength': 'signalperiod',
    'mult': 'nbdevup',
    'fastLimit': 'fastlimit',
    'slowLimit': 'slowlimit',
    'start': 'acceleration',
    'increment': 'maximum',
    'kPeriod': 'fastk_period',
    'dPeriod': 'slowd_period',
    'smoothK': 'slowk_period',
  }

  // Special handling for specific indicators
  if (talibName === 'BBANDS') {
    // TradingView uses in_0 for length, in_1 for multiplier
    talibParams.timeperiod = tvInputs.in_0 || tvInputs.length || 20
    talibParams.nbdevup = tvInputs.in_1 || tvInputs.mult || 2
    talibParams.nbdevdn = tvInputs.in_1 || tvInputs.mult || 2
    talibParams.matype = 0 // SMA
  } else if (talibName === 'MACD') {
    talibParams.fastperiod = tvInputs.fastLength || 12
    talibParams.slowperiod = tvInputs.slowLength || 26
    talibParams.signalperiod = tvInputs.signalLength || 9
  } else if (talibName === 'RSI') {
    talibParams.timeperiod = tvInputs.in_0 || tvInputs.length || 14
  } else if (['SMA', 'EMA', 'WMA', 'DEMA', 'TEMA', 'TRIMA'].includes(talibName)) {
    talibParams.timeperiod = tvInputs.in_0 || tvInputs.length || 14
  } else if (talibName === 'STOCH') {
    talibParams.fastk_period = tvInputs.kPeriod || 14
    talibParams.slowd_period = tvInputs.dPeriod || 3
    talibParams.slowk_period = tvInputs.smoothK || 3
    talibParams.slowk_matype = 0 // SMA
    talibParams.slowd_matype = 0 // SMA
  } else if (talibName === 'ATR') {
    talibParams.timeperiod = tvInputs.length || 14
  } else if (talibName === 'CCI') {
    talibParams.timeperiod = tvInputs.length || 20
  } else {
    // Generic parameter conversion
    for (const [tvParam, value] of Object.entries(tvInputs)) {
      if (tvParam === 'source') continue // Skip source parameter
      const talibParam = reverseMapping[tvParam] || tvParam
      talibParams[talibParam] = value
    }
  }

  return { talibName, talibParams }
}

/**
 * Setup bidirectional synchronization between TradingView indicators and IndicatorStore
 */
export function useTradingViewIndicators(tvWidget: IChartingLibraryWidget) {
  const indicatorStore = useIndicatorStore()
  const chartStore = useChartStore()

  let isApplyingTVUpdate = false // Prevent circular updates when TV modifies indicators
  let isUpdatingStore = false // Prevent circular updates when we update the store from TV
  let isChartReady = false // Track if chart API is ready

  /**
   * Convert TradingView study to our IndicatorInstance format
   */
  function convertTVStudyToIndicator(tvStudy: any, symbol: string, studyId?: string): IndicatorInstance | null {
    try {
      console.log('[Indicators] convertTVStudyToIndicator called with:', { tvStudy, symbol, studyId })
      console.log('[Indicators] Study object keys:', Object.keys(tvStudy))
      console.log('[Indicators] Study object type:', typeof tvStudy)

      // Expose study object to window for debugging
      ;(window as any).__lastTVStudy = tvStudy
      console.log('[Indicators] Study object exposed as window.__lastTVStudy for debugging')

      // Study object has methods - name() gives the indicator type, title() gives display name
      let studyName = 'Unknown'

      // Try tvStudy.study().name() first
      if (typeof tvStudy.study === 'function') {
        try {
          const innerStudy = tvStudy.study()
          if (innerStudy && typeof innerStudy.name === 'function') {
            studyName = innerStudy.name()
            console.log('[Indicators] Called tvStudy.study().name():', studyName)
          }
        } catch (e) {
          console.log('[Indicators] Error calling study().name():', e)
        }
      }

      // Try name() directly if that didn't work
      if (studyName === 'Unknown' && typeof tvStudy.name === 'function') {
        try {
          studyName = tvStudy.name()
          console.log('[Indicators] Called study.name():', studyName)
        } catch (e) {
          console.log('[Indicators] Error calling name():', e)
        }
      }

      // Fallback to title() if name() didn't work
      if (studyName === 'Unknown' && typeof tvStudy.title === 'function') {
        try {
          studyName = tvStudy.title()
          console.log('[Indicators] Called study.title():', studyName)
        } catch (e) {
          console.log('[Indicators] Error calling title():', e)
        }
      }

      // Final fallback to property access
      if (studyName === 'Unknown') {
        studyName = tvStudy._study?.name?.() ||
                   tvStudy._metaInfo?.description ||
                   tvStudy._metaInfo?.shortDescription || 'Unknown'
      }

      console.log('[Indicators] Study name extracted:', studyName)

      const talibName = TV_TO_BACKEND_NAMES[studyName]
      console.log('[Indicators] Backend mapping:', studyName, '->', talibName)

      if (!talibName) {
        console.log('[Indicators] TradingView study not mapped to backend:', studyName)
        console.log('[Indicators] Available mappings:', Object.keys(TV_TO_BACKEND_NAMES).slice(0, 10))
        return null
      }

      // Extract inputs from study - try calling getInputValues() if it's a method
      let tvInputs: any = {}

      if (typeof tvStudy.getInputValues === 'function') {
        try {
          const inputsArray = tvStudy.getInputValues()
          console.log('[Indicators] Called study.getInputValues():', inputsArray)

          // Convert array of {id, value} objects to a simple object
          if (Array.isArray(inputsArray)) {
            tvInputs = {}
            for (const input of inputsArray) {
              if (input.id && input.value !== undefined) {
                tvInputs[input.id] = input.value
              }
            }
            console.log('[Indicators] Converted array inputs to object:', tvInputs)
          } else {
            tvInputs = inputsArray
          }
        } catch (e) {
          console.log('[Indicators] Error calling getInputValues():', e)
        }
      } else {
        tvInputs = tvStudy.inputs || tvStudy._inputs || {}
      }

      console.log('[Indicators] TV inputs:', tvInputs)

      const { talibParams } = convertTVInputsToTALibParams(studyName, tvInputs)
      console.log('[Indicators] Converted TA-Lib params:', talibParams)

      const now = Math.floor(Date.now() / 1000)

      const indicator = {
        id: studyId || tvStudy.id || `ind_${Date.now()}`,
        talib_name: talibName,
        instance_name: `${talibName}_${Date.now()}`,
        parameters: talibParams,
        tv_study_id: studyId || tvStudy.id,
        tv_indicator_name: studyName,
        tv_inputs: tvInputs,
        visible: true,
        pane: 'chart',
        symbol,
        created_at: now,
        modified_at: now
      }

      console.log('[Indicators] Created indicator object:', indicator)
      return indicator
    } catch (error) {
      console.error('[Indicators] Error converting TV study:', error)
      return null
    }
  }

  /**
   * Setup listeners for TradingView indicator events
   */
  function setupIndicatorListeners() {
    try {
      const chart = tvWidget.activeChart()
      if (!chart) {
        console.warn('[Indicators] Active chart not available yet')
        return () => {}
      }
      isChartReady = true

      console.log('[Indicators] Setting up indicator event subscriptions')
      console.log('[Indicators] Chart ready, widget:', tvWidget)

      // Subscribe to 'study_event' - fires for specific study instance events with ID
      // Callback signature: (studyId: string, eventType: string)
      tvWidget.subscribe('study_event', (studyId: any, eventType?: any) => {
        console.log('[Indicators] ===== STUDY_EVENT FIRED =====')
        console.log('[Indicators] Arg 1 (studyId):', studyId)
        console.log('[Indicators] Arg 2 (eventType):', eventType)

        if (isApplyingTVUpdate) {
          console.log('[Indicators] Ignoring study_event - isApplyingTVUpdate is true')
          return
        }

        const currentSymbol = chartStore.chart_state.symbol

        // If studyId is actually an object, extract the real values
        let actualStudyId = studyId
        let actualEventType = eventType

        if (typeof studyId === 'object' && studyId !== null) {
          actualStudyId = studyId.id || studyId.studyId
          actualEventType = studyId.type || studyId.event || eventType
        }

        console.log('[Indicators] Parsed - Study ID:', actualStudyId, 'Event type:', actualEventType)

        if (!actualStudyId) {
          console.warn('[Indicators] No study ID found, cannot process event')
          return
        }

        // Filter out events we don't care about
        if (actualEventType && !['create', 'remove'].includes(actualEventType)) {
          console.log('[Indicators] Ignoring event type:', actualEventType)
          return
        }

        // If we have an event type, handle it specifically
        if (actualEventType === 'create') {
          console.log('[Indicators] New indicator created with ID:', actualStudyId)

          // Wait for TradingView to finish initializing the study
          setTimeout(() => {
            try {
              const study = chart.getStudyById(actualStudyId)
              if (study) {
                console.log('[Indicators] Retrieved new study after timeout')

                const indicator = convertTVStudyToIndicator(study, currentSymbol, actualStudyId)
                if (indicator) {
                  console.log('[Indicators] Adding new indicator to store:', indicator)
                  isUpdatingStore = true
                  indicatorStore.addIndicator(indicator)
                  console.log('[Indicators] Indicator added! Store now has:', Object.keys(indicatorStore.indicators).length, 'indicators')
                  isUpdatingStore = false
                } else {
                  console.warn('[Indicators] Conversion returned null - indicator not supported')
                }
              }
            } catch (error) {
              console.error('[Indicators] Error handling create event:', error)
            }
          }, 0)
        }
        else if (actualEventType === 'remove') {
          console.log('[Indicators] Indicator removed with ID:', actualStudyId)

          const existingIndicator = Object.values(indicatorStore.indicators).find(
            ind => ind.tv_study_id === actualStudyId
          )

          if (existingIndicator) {
            console.log('[Indicators] Removing indicator from store:', existingIndicator.id)
            isUpdatingStore = true
            indicatorStore.removeIndicator(existingIndicator.id)
            console.log('[Indicators] Indicator removed!')
            isUpdatingStore = false
          } else {
            console.log('[Indicators] Indicator not found in store for removal')
          }
        }
        else {
          // No event type provided, just a study ID - check if it exists
          console.log('[Indicators] Event fired with study ID but no type, checking if study exists...')

          try {
            const study = chart.getStudyById(actualStudyId)
            if (study) {
              console.log('[Indicators] Study exists - likely created or modified')

              const existingIndicator = Object.values(indicatorStore.indicators).find(
                ind => ind.tv_study_id === actualStudyId
              )

              if (!existingIndicator) {
                // New indicator
                console.log('[Indicators] New indicator detected, adding to store...')
                const indicator = convertTVStudyToIndicator(study, currentSymbol, actualStudyId)
                if (indicator) {
                  isUpdatingStore = true
                  indicatorStore.addIndicator(indicator)
                  console.log('[Indicators] Indicator added!')
                  isUpdatingStore = false
                }
              } else {
                console.log('[Indicators] Indicator already exists in store')
              }
            }
          } catch (error) {
            // Study doesn't exist - it was removed
            console.log('[Indicators] Study does not exist - checking for removal...')

            const existingIndicator = Object.values(indicatorStore.indicators).find(
              ind => ind.tv_study_id === actualStudyId
            )

            if (existingIndicator) {
              console.log('[Indicators] Removing indicator from store')
              isUpdatingStore = true
              indicatorStore.removeIndicator(existingIndicator.id)
              isUpdatingStore = false
            }
          }
        }

        console.log('[Indicators] ===== STUDY_EVENT COMPLETE =====')
      })

      // Subscribe to 'study_properties_changed' - fires when indicator settings are modified
      // This is the key event for detecting when users edit indicator parameters
      // Callback signature: (studyId: string)
      tvWidget.subscribe('study_properties_changed', (studyId: any) => {
        console.log('[Indicators] ===== STUDY_PROPERTIES_CHANGED FIRED =====')
        console.log('[Indicators] Study ID:', studyId)

        if (isApplyingTVUpdate) {
          console.log('[Indicators] Ignoring properties change - isApplyingTVUpdate is true')
          return
        }

        const currentSymbol = chartStore.chart_state.symbol

        if (studyId && typeof studyId === 'string') {
          console.log('[Indicators] Study properties changed for ID:', studyId)

          // Wait for TradingView to finish applying the changes
          setTimeout(() => {
            try {
              const study = chart.getStudyById(studyId)
              if (study) {
                console.log('[Indicators] Retrieved updated study')

                // Find existing indicator in store
                const existingIndicator = Object.values(indicatorStore.indicators).find(
                  ind => ind.tv_study_id === studyId
                )

                if (existingIndicator) {
                  console.log('[Indicators] Found existing indicator:', existingIndicator.id)

                  // Get the study name using study().name()
                  let studyName = 'Unknown'
                  if (typeof study.study === 'function') {
                    const innerStudy = study.study()
                    if (innerStudy && typeof innerStudy.name === 'function') {
                      studyName = innerStudy.name()
                    }
                  }

                  console.log('[Indicators] Study name:', studyName)

                  // Get inputs - try calling getInputValues() if available
                  let tvInputs: any = {}
                  if (typeof study.getInputValues === 'function') {
                    const inputsArray = study.getInputValues()

                    // Convert array of {id, value} objects to a simple object
                    if (Array.isArray(inputsArray)) {
                      tvInputs = {}
                      for (const input of inputsArray) {
                        if (input.id && input.value !== undefined) {
                          tvInputs[input.id] = input.value
                        }
                      }
                      console.log('[Indicators] Converted inputs array to object:', tvInputs)
                    } else {
                      tvInputs = inputsArray
                    }
                  }

                  console.log('[Indicators] TV inputs:', tvInputs)

                  const { talibParams } = convertTVInputsToTALibParams(studyName, tvInputs)

                  console.log('[Indicators] Old params:', existingIndicator.parameters)
                  console.log('[Indicators] New params:', talibParams)

                  // Update the store with new parameters
                  if (JSON.stringify(existingIndicator.parameters) !== JSON.stringify(talibParams)) {
                    console.log('[Indicators] Parameters changed, updating store...')
                    isUpdatingStore = true
                    indicatorStore.updateIndicator(existingIndicator.id, {
                      parameters: talibParams,
                      tv_inputs: tvInputs
                    })
                    console.log('[Indicators] Indicator updated in store!')
                    isUpdatingStore = false
                  } else {
                    console.log('[Indicators] Parameters unchanged (might be visual properties only)')
                  }
                } else {
                  console.log('[Indicators] No existing indicator found, doing full sync...')
                  // Might be a new indicator, do full sync
                  if (!isUpdatingStore && !isApplyingTVUpdate) {
                    syncIndicatorsFromTV()
                  }
                }
              }
            } catch (error) {
              console.error('[Indicators] Error handling study_properties_changed:', error)
            }
          }, 0)
        } else {
          console.log('[Indicators] No study ID in event, doing full sync...')
          // Fallback to full sync
          setTimeout(() => {
            if (!isUpdatingStore && !isApplyingTVUpdate) {
              syncIndicatorsFromTV()
            }
          }, 100)
        }

        console.log('[Indicators] ===== STUDY_PROPERTIES_CHANGED COMPLETE =====')
      })

      // Initial sync on data load
      const dataLoadedSubscription = chart.onDataLoaded().subscribe(null, () => {
        console.log('[Indicators] Chart data loaded, performing initial sync')
        syncIndicatorsFromTV()
      })

      // Cleanup function
      return () => {
        console.log('[Indicators] Cleaning up event subscriptions')
        try {
          // Unsubscribe from all widget events
          tvWidget.unsubscribe('study_event')
          tvWidget.unsubscribe('study_properties_changed')

          if (dataLoadedSubscription && typeof dataLoadedSubscription.unsubscribe === 'function') {
            dataLoadedSubscription.unsubscribe()
          }
        } catch (error) {
          console.error('[Indicators] Error during cleanup:', error)
        }
      }
    } catch (error) {
      console.error('[Indicators] Error setting up indicator listeners:', error)
      return () => {}
    }
  }

  /**
   * Scan TradingView for indicators and sync to store
   */
  function syncIndicatorsFromTV() {
    if (!isChartReady) return

    try {
      const chart = tvWidget.activeChart()
      if (!chart) return

      const currentSymbol = chartStore.chart_state.symbol
      const allStudies = chart.getAllStudies()

      if (!allStudies) return

      const seenStudyIds = new Set<string>()

      isUpdatingStore = true
      try {
        for (const studyInfo of allStudies) {
          seenStudyIds.add(studyInfo.id)

          // getAllStudies() returns simple objects {id, name}
          // We need to get the full study object using getStudyById()
          try {
            const tvStudy = chart.getStudyById(studyInfo.id)
            if (!tvStudy) continue

            const indicator = convertTVStudyToIndicator(tvStudy, currentSymbol, studyInfo.id)
            if (!indicator) continue

            const existingIndicator = Object.values(indicatorStore.indicators).find(
              ind => ind.tv_study_id === studyInfo.id
            )

            if (!existingIndicator) {
              console.log('[Indicators] New indicator detected:', indicator)
              indicatorStore.addIndicator(indicator)
            } else if (JSON.stringify(existingIndicator.parameters) !== JSON.stringify(indicator.parameters)) {
              console.log('[Indicators] Indicator parameters changed:', indicator.id)
              indicatorStore.updateIndicator(existingIndicator.id, {
                parameters: indicator.parameters,
                tv_inputs: indicator.tv_inputs
              })
            }
          } catch (err) {
            console.warn('[Indicators] Could not get study details for:', studyInfo.id, err)
          }
        }

        // Check for deleted indicators
        const allStoreIndicators = indicatorStore.getAllIndicators()
        for (const storeIndicator of allStoreIndicators) {
          if (storeIndicator.symbol === currentSymbol &&
              storeIndicator.tv_study_id &&
              !seenStudyIds.has(storeIndicator.tv_study_id)) {
            console.log('[Indicators] Indicator deleted:', storeIndicator.id)
            indicatorStore.removeIndicator(storeIndicator.id)
          }
        }
      } finally {
        isUpdatingStore = false
      }
    } catch (error) {
      console.error('[Indicators] Error syncing indicators from TV:', error)
    }
  }

  /**
   * Setup watchers for IndicatorStore changes to apply to TradingView
   */
  function setupStoreWatchers() {
    watch(
      () => indicatorStore.indicators,
      async (newIndicators, oldIndicators) => {
        if (isUpdatingStore || !isChartReady) return

        isApplyingTVUpdate = true

        try {
          // Check if widget is ready before accessing activeChart
          if (!tvWidget || typeof tvWidget.activeChart !== 'function') {
            console.log('[Indicators] Widget not ready, skipping store update')
            isApplyingTVUpdate = false
            return
          }

          const chart = tvWidget.activeChart()
          if (!chart) {
            console.log('[Indicators] Chart not available, skipping store update')
            isApplyingTVUpdate = false
            return
          }

          const currentSymbol = chartStore.chart_state.symbol

          // Find added indicators
          for (const [id, indicator] of Object.entries(newIndicators)) {
            if (indicator.symbol && indicator.symbol !== currentSymbol) continue

            if (!oldIndicators || !oldIndicators[id]) {
              // Indicator was added to store
              await createTVStudy(indicator)
            } else {
              // Check if indicator exists in TradingView
              let study = null
              if (indicator.tv_study_id) {
                try {
                  study = chart.getStudyById(indicator.tv_study_id)
                } catch (e) {
                  // Study doesn't exist
                }
              }

              if (!study) {
                // Indicator is in store but not in TradingView - create it
                await createTVStudy(indicator)
              } else if (JSON.stringify(indicator) !== JSON.stringify(oldIndicators[id])) {
                // Indicator was modified
                updateTVStudy(indicator)
              }
            }
          }

          // Find removed indicators
          if (oldIndicators) {
            for (const [id, indicator] of Object.entries(oldIndicators)) {
              if (indicator.symbol && indicator.symbol !== currentSymbol) continue

              if (!newIndicators[id]) {
                removeTVStudy(indicator)
              }
            }
          }
        } catch (error) {
          console.error('[Indicators] Error applying store changes:', error)
        } finally {
          isApplyingTVUpdate = false
        }
      },
      { deep: true }
    )
  }

  /**
   * Create an indicator in TradingView
   */
  async function createTVStudy(indicator: IndicatorInstance) {
    if (!isChartReady) return

    try {
      const chart = tvWidget.activeChart()
      if (!chart) return

      const currentSymbol = chartStore.chart_state.symbol
      const tvName = ALL_BACKEND_TO_TV_NAMES[indicator.talib_name]

      if (!tvName) {
        console.warn('[Indicators] No TradingView mapping for backend indicator:', indicator.talib_name)
        return
      }

      const tvInputs = convertTALibParamsToTVInputs(indicator.talib_name, indicator.parameters)

      console.log(`[Indicators] Creating TradingView study: ${tvName} with inputs:`, tvInputs)

      const studyId = await chart.createStudy(tvName, false, false, tvInputs)

      // If TradingView assigned a different ID, update the store
      if (studyId && studyId !== indicator.tv_study_id) {
        isUpdatingStore = true
        await new Promise(resolve => setTimeout(resolve, 0))

        try {
          indicatorStore.updateIndicator(indicator.id, {
            tv_study_id: studyId,
            symbol: indicator.symbol || currentSymbol
          })
        } finally {
          await new Promise(resolve => setTimeout(resolve, 0))
          isUpdatingStore = false
        }
      }
    } catch (error) {
      console.error('[Indicators] Error creating TV study:', error)
    }
  }

  /**
   * Update an indicator in TradingView
   */
  function updateTVStudy(indicator: IndicatorInstance) {
    if (!isChartReady || !indicator.tv_study_id) return

    try {
      const chart = tvWidget.activeChart()
      if (!chart) return

      const study = chart.getStudyById(indicator.tv_study_id)
      if (!study) {
        console.warn('[Indicators] Study not found in TV, creating instead:', indicator.id)
        createTVStudy(indicator)
        return
      }

      const tvInputs = convertTALibParamsToTVInputs(indicator.talib_name, indicator.parameters)

      // Update study inputs
      chart.getStudyById(indicator.tv_study_id).applyOverrides(tvInputs)

      console.log('[Indicators] Updated study in TV:', indicator.id)
    } catch (error) {
      console.error('[Indicators] Error updating TV study:', error)
    }
  }

  /**
   * Remove an indicator from TradingView
   */
  function removeTVStudy(indicator: IndicatorInstance) {
    if (!isChartReady || !indicator.tv_study_id) return

    try {
      const chart = tvWidget.activeChart()
      if (!chart) return

      chart.removeStudy(indicator.tv_study_id)
      console.log('[Indicators] Removed study from TV:', indicator.id)
    } catch (error) {
      console.error('[Indicators] Error removing TV study:', error)
    }
  }

  // Initialize
  const cleanupIndicatorListeners = setupIndicatorListeners()
  setupStoreWatchers()

  // Return cleanup function
  return () => {
    cleanupIndicatorListeners()
  }
}
