'use client'

import { useEffect, useRef } from 'react'
import type { TrumpPost, Candle } from '@/types'
import { useDashboardStore } from '@/store/dashboard'

interface ChartPanelProps {
  posts?: TrumpPost[]
  candles?: Candle[]
  externalSelectedId?: number | null
  onSelectPost?: (id: number | null) => void
  onSelectDayPosts?: (posts: TrumpPost[]) => void
}

export default function ChartPanel({ posts = [], candles = [], externalSelectedId, onSelectPost, onSelectDayPosts }: ChartPanelProps) {
  const { timeframe } = useDashboardStore()
  const containerRef = useRef<HTMLDivElement>(null)
  const chartRef = useRef<unknown>(null)
  const seriesRef = useRef<unknown>(null)
  const fittedRef = useRef(false)
  const postsRef = useRef(posts)
  postsRef.current = posts
  const selectedPostIdRef = useRef(externalSelectedId)
  selectedPostIdRef.current = externalSelectedId
  const timeframeRef = useRef(timeframe)
  timeframeRef.current = timeframe
  const onSelectRef = useRef(onSelectPost)
  onSelectRef.current = onSelectPost
  const onSelectDayPostsRef = useRef(onSelectDayPosts)
  onSelectDayPostsRef.current = onSelectDayPosts

  // Detect current theme for chart colors
  function getChartColors() {
    const isDark = document.documentElement.dataset.theme === 'dark'
    return {
      background: isDark ? '#121212' : '#ffffff',
      textColor: isDark ? '#666666' : '#888888',
      gridColor: isDark ? '#1e1e1e' : '#f0ede8',
      borderColor: isDark ? '#2a2a2a' : '#e8e4de',
    }
  }

  // Create chart once on mount
  useEffect(() => {
    if (!containerRef.current || typeof window === 'undefined') return
    let destroyed = false
    let ro: ResizeObserver | null = null
    let themeObserver: MutationObserver | null = null

    import('lightweight-charts').then(({ createChart, CrosshairMode }) => {
      if (destroyed || !containerRef.current) return
      const colors = getChartColors()

      const chart = createChart(containerRef.current, {
        width: containerRef.current.clientWidth,
        height: 360,
        layout: {
          background: { color: colors.background },
          textColor: colors.textColor,
        },
        grid: {
          vertLines: { color: colors.gridColor },
          horzLines: { color: colors.gridColor },
        },
        crosshair: { mode: CrosshairMode.Normal },
        rightPriceScale: { borderColor: colors.borderColor },
        timeScale: {
          borderColor: colors.borderColor,
          timeVisible: true,
          rightOffset: 5,
          barSpacing: 10,
        },
        handleScroll: true,
        handleScale: true,
      })

      chartRef.current = chart

      const series = chart.addCandlestickSeries({
        upColor: '#26a69a',
        downColor: '#ef5350',
        borderUpColor: '#26a69a',
        borderDownColor: '#ef5350',
        wickUpColor: '#26a69a',
        wickDownColor: '#ef5350',
      })

      seriesRef.current = series

      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      chart.subscribeClick((param: any) => {
        if (!param.time) return
        const clickTime = typeof param.time === 'number' ? param.time : 0
        if (!clickTime) return

        const bucketByTf: Record<string, number> = {
          '5m': 300, '15m': 900, '1h': 3600, '4h': 14400, '1d': 86400, '1w': 604800,
        }
        const bucketSecs = bucketByTf[timeframeRef.current.toLowerCase()] ?? 3600
        const clickBucket = Math.floor(clickTime / bucketSecs) * bucketSecs

        const inBucket = postsRef.current
          .filter((p) => {
            if (!p.published_at) return false
            const pt = Math.floor(new Date(p.published_at).getTime() / 1000)
            return Math.floor(pt / bucketSecs) * bucketSecs === clickBucket
          })

        if (inBucket.length === 0) {
          onSelectRef.current?.(null)
          return
        }

        // Multiple posts in this candle bucket → show all of them in the right rail
        if (inBucket.length > 1 && onSelectDayPostsRef.current) {
          const sorted = [...inBucket].sort(
            (a, b) => new Date(b.published_at).getTime() - new Date(a.published_at).getTime()
          )
          onSelectDayPostsRef.current(sorted)
          return
        }

        // Single post → show detail directly
        onSelectRef.current?.(inBucket[0].id)
      })

      ro = new ResizeObserver(() => {
        if (containerRef.current && !destroyed) {
          chart.applyOptions({ width: containerRef.current.clientWidth })
        }
      })
      ro.observe(containerRef.current)

      themeObserver = new MutationObserver(() => {
        const colors = getChartColors()
        chart.applyOptions({
          layout: {
            background: { color: colors.background },
            textColor: colors.textColor,
          },
          grid: {
            vertLines: { color: colors.gridColor },
            horzLines: { color: colors.gridColor },
          },
          rightPriceScale: { borderColor: colors.borderColor },
          timeScale: { borderColor: colors.borderColor },
        })
      })
      themeObserver.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ['data-theme'],
      })
    })

    return () => {
      destroyed = true
      ro?.disconnect()
      themeObserver?.disconnect()
      fittedRef.current = false
      if (chartRef.current) {
        // @ts-expect-error lightweight-charts type
        chartRef.current.remove()
        chartRef.current = null
        seriesRef.current = null
      }
    }
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  // Update candles + markers
  useEffect(() => {
    const series = seriesRef.current
    const chart = chartRef.current
    if (!series || !chart || candles.length === 0) return

    const sorted = [...candles].sort((a, b) => a.time - b.time)

    // @ts-expect-error lightweight-charts type
    series.setData(sorted.map((c) => ({
      time: c.time as number,
      open: c.open,
      high: c.high,
      low: c.low,
      close: c.close,
    })))

    const minTime = sorted[0].time
    const maxTime = sorted[sorted.length - 1].time

    const visible = posts.filter((p) => {
      if (!p.published_at) return false
      const t = Math.floor(new Date(p.published_at).getTime() / 1000)
      return t >= minTime && t <= maxTime
    })

    const bucketByTf: Record<string, number> = {
      '5m': 300, '15m': 900, '1h': 3600, '4h': 14400, '1d': 86400, '1w': 604800,
    }
    const candleSpacing = sorted.length > 1 ? sorted[1].time - sorted[0].time : 300
    const bucketSecs = bucketByTf[timeframeRef.current.toLowerCase()] ?? candleSpacing

    const bucketMap = new Map<number, typeof visible>()
    for (const p of visible) {
      const pt = Math.floor(new Date(p.published_at).getTime() / 1000)
      const bucket = Math.floor(pt / bucketSecs) * bucketSecs
      if (!bucketMap.has(bucket)) bucketMap.set(bucket, [])
      bucketMap.get(bucket)!.push(p)
    }
    bucketMap.forEach((ps) => ps.sort((a, b) => (b.ai_confidence ?? 0) - (a.ai_confidence ?? 0)))

    const markers = Array.from(bucketMap.entries())
      .sort(([a], [b]) => a - b)
      .map(([bucketTime, bPosts]) => {
        const isSelected = bPosts.some((p) => p.id === externalSelectedId)
        const best = bPosts[0]
        const count = bPosts.length
        const signalColor = isSelected
          ? '#f59e0b'
          : best.signal === 'short' || best.signal === 'sell'
          ? '#ef5350'
          : best.signal === 'buy'
          ? '#26a69a'
          : '#aaaaaa'
        return {
          time: bucketTime as number,
          position: 'aboveBar' as const,
          color: signalColor,
          shape: 'circle' as const,
          text: count > 1 ? String(count) : '',
          size: isSelected ? 2 : count > 1 ? 1.5 : 1,
        }
      })

    // @ts-expect-error lightweight-charts type
    series.setMarkers(markers)

    if (!fittedRef.current) {
      // @ts-expect-error lightweight-charts type
      chart.timeScale().fitContent()
      fittedRef.current = true
    }
  }, [candles, posts, externalSelectedId])

  useEffect(() => { fittedRef.current = false }, [timeframe])

  return (
    <div
      ref={containerRef}
      style={{ width: '100%', height: 360, borderRadius: 'var(--r-sm)', overflow: 'hidden', cursor: 'crosshair' }}
    />
  )
}
