import * as React from 'react'
import { useId } from 'react'
import * as RechartsChart from 'recharts'
import { cn } from '@/lib/utils'

export interface ChartConfig {
  [key: string]: {
    label?: string
    icon?: React.ComponentType
    color?: string
  }
}

type ChartContextProps = {
  config: ChartConfig
}

const THEMES = { light: '', dark: '.dark' } as const
const CHART_INITIAL_DIMENSION = { width: 1, height: 1 }

const ChartContext = React.createContext<ChartContextProps | null>(null)

export function useChart() {
  const context = React.useContext(ChartContext)

  if (!context) {
    throw new Error('useChart must be used within a <ChartContainer>')
  }

  return context
}

export function ChartContainer({
  id,
  config,
  className,
  children,
  ...props
}: React.ComponentProps<'div'> & {
  config: ChartConfig
  children: React.ComponentProps<
    typeof RechartsChart.ResponsiveContainer
  >['children']
}) {
  const uniqueId = useId()
  const chartId = `chart-${id || uniqueId.replace(/:/g, '')}`
  const containerRef = React.useRef<HTMLDivElement>(null)
  const [isReady, setIsReady] = React.useState(false)

  React.useLayoutEffect(() => {
    const node = containerRef.current
    if (!node) return

    const updateSize = () => {
      const rect = node.getBoundingClientRect()
      const hasSize = rect.width > 0 && rect.height > 0
      setIsReady((current) => (current === hasSize ? current : hasSize))
    }

    updateSize()

    if (typeof ResizeObserver === 'undefined') return

    const observer = new ResizeObserver(updateSize)
    observer.observe(node)

    return () => observer.disconnect()
  }, [])

  return (
    <ChartContext.Provider value={{ config }}>
      <div
        ref={containerRef}
        data-chart={chartId}
        className={cn(
          'chart flex aspect-video min-h-0 min-w-0 justify-center text-xs',
          className
        )}
        {...props}
      >
        <ChartStyle id={chartId} config={config} />
        {isReady ? (
          <RechartsChart.ResponsiveContainer
            width='100%'
            height='100%'
            minWidth={0}
            initialDimension={CHART_INITIAL_DIMENSION}
          >
            {children}
          </RechartsChart.ResponsiveContainer>
        ) : (
          <div className='h-full w-full' />
        )}
      </div>
    </ChartContext.Provider>
  )
}

export function ChartStyle({
  id,
  config,
}: {
  id: string
  config: ChartConfig
}) {
  const colorConfig = Object.entries(config).filter(
    ([, itemConfig]) => itemConfig.color
  )

  if (!colorConfig.length) return null

  return (
    <style
      dangerouslySetInnerHTML={{
        __html: Object.entries(THEMES)
          .map(
            ([, prefix]) => `
${prefix} [data-chart=${id}] {
${colorConfig
  .map(([key, itemConfig]) => `  --color-${key}: ${itemConfig.color};`)
  .join('\n')}
}
`
          )
          .join('\n'),
      }}
    />
  )
}

export const ChartTooltip = RechartsChart.Tooltip

export function ChartTooltipContent({ active, payload, label }: any) {
  const { config } = useChart()

  if (!active || !payload?.length) return null

  return (
    <div className='min-w-32 rounded-md border bg-background/95 p-2.5 text-xs shadow-lg backdrop-blur'>
      {label ? (
        <div className='mb-2 font-medium text-foreground'>{label}</div>
      ) : null}
      {payload.map((item: any) => (
        <div
          key={item.dataKey}
          className='flex items-center justify-between gap-4 py-0.5'
        >
          <span className='flex items-center gap-2 text-muted-foreground'>
            <span
              className='h-2 w-2 rounded-full'
              style={{ backgroundColor: item.color || item.fill }}
            />
            {config[item.dataKey]?.label || item.name || item.dataKey}
          </span>
          <span className='font-medium text-foreground tabular-nums'>
            {typeof item.value === 'number'
              ? item.value.toLocaleString('en-US')
              : item.value}
          </span>
        </div>
      ))}
    </div>
  )
}

export function ChartLegendContent({ payload }: any) {
  const { config } = useChart()

  if (!payload?.length) return null

  const orderedPayload = [...payload].sort(
    (left: any, right: any) =>
      Object.keys(config).indexOf(left.value) -
      Object.keys(config).indexOf(right.value)
  )

  return (
    <div className='flex flex-wrap items-center justify-end gap-4 text-xs text-muted-foreground'>
      {orderedPayload.map((item: any) => (
        <div key={item.value} className='flex items-center gap-1.5'>
          <span
            className='h-2 w-2 rounded-full'
            style={{ backgroundColor: item.color }}
          />
          <span>{config[item.value]?.label || item.value}</span>
        </div>
      ))}
    </div>
  )
}

// Re-export Recharts components
export {
  Area,
  AreaChart,
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  Legend,
  Pie,
  PieChart,
  Radar,
  RadarChart,
  ResponsiveContainer,
  Sector,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts'
