import React, { createContext, useContext, useLayoutEffect, useRef, useState } from 'react'
import { cn } from '../utils/cn'

// ─── Primary Pill Tabs ────────────────────────────────────────────────────────

const PillTabsContext = createContext<{
  value: string
  onChange: (value: string) => void
} | null>(null)

function usePillTabsContext() {
  const ctx = useContext(PillTabsContext)
  if (!ctx) throw new Error('PillTab must be used inside <PillTabs>')
  return ctx
}

export const PillTabs: React.FC<{
  defaultValue?: string
  value?: string
  children: React.ReactNode
  onValueChange?: (value: string) => void
}> = ({ defaultValue, value: controlledValue, children, onValueChange }) => {
  const [internalValue, setInternalValue] = useState(defaultValue ?? '')
  const isControlled = controlledValue !== undefined
  const value = isControlled ? controlledValue : internalValue

  const handleChange = (newValue: string) => {
    if (!isControlled) setInternalValue(newValue)
    onValueChange?.(newValue)
  }

  return (
    <PillTabsContext.Provider value={{ value, onChange: handleChange }}>
      {children}
    </PillTabsContext.Provider>
  )
}

export const PillTabsList: React.FC<{ children: React.ReactNode; className?: string }> = ({
  children,
  className = '',
}) => {
  const { value } = usePillTabsContext()
  const containerRef = useRef<HTMLDivElement>(null)
  const [indicator, setIndicator] = useState<{ left: number; width: number } | null>(null)

  useLayoutEffect(() => {
    const el = containerRef.current
    if (!el) return
    const updateIndicator = () => {
      const active = el.querySelector<HTMLElement>('[data-active="true"]')
      if (!active) return
      const cRect = el.getBoundingClientRect()
      const aRect = active.getBoundingClientRect()
      if (aRect.width === 0) return
      setIndicator({ left: aRect.left - cRect.left, width: aRect.width })
    }
    updateIndicator()
    const ro = new ResizeObserver(updateIndicator)
    ro.observe(el)
    return () => ro.disconnect()
  }, [value])

  return (
    <div ref={containerRef} className={`relative inline-flex gap-1 bg-slate-100 p-0.5 rounded-[10px] ${className}`}>
      {indicator && (
        <div
          className="absolute top-0.5 bottom-0.5 bg-teal-500 rounded-lg shadow-soft-sm pointer-events-none"
          style={{ left: indicator.left, width: indicator.width, transition: 'left 0.2s ease-out, width 0.2s ease-out' }}
        />
      )}
      {children}
    </div>
  )
}

export const PillTab: React.FC<{
  value: string
  children: React.ReactNode
  className?: string
}> = ({ value, children, className = '' }) => {
  const { value: activeValue, onChange } = usePillTabsContext()
  const isActive = activeValue === value

  return (
    <button
      type="button"
      data-active={isActive}
      className={cn(
        'relative z-10 px-4 py-1.5 text-caption transition-colors duration-150 rounded-lg cursor-pointer',
        isActive ? 'text-white font-bold' : 'text-slate-500 font-semibold hover:text-slate-800',
        className
      )}
      onClick={() => onChange(value)}
    >
      {children}
    </button>
  )
}

// ─── Neutral Pill Tabs ────────────────────────────────────────────────────────

const NeutralPillTabsContext = createContext<{
  value: string
  onChange: (value: string) => void
} | null>(null)

function useNeutralPillTabsContext() {
  const ctx = useContext(NeutralPillTabsContext)
  if (!ctx) throw new Error('NeutralPillTab must be used inside <NeutralPillTabs>')
  return ctx
}

export const NeutralPillTabs: React.FC<{
  defaultValue?: string
  value?: string
  children: React.ReactNode
  onValueChange?: (value: string) => void
}> = ({ defaultValue, value: controlledValue, children, onValueChange }) => {
  const [internalValue, setInternalValue] = useState(defaultValue ?? '')
  const isControlled = controlledValue !== undefined
  const value = isControlled ? controlledValue : internalValue

  const handleChange = (newValue: string) => {
    if (!isControlled) setInternalValue(newValue)
    onValueChange?.(newValue)
  }

  return (
    <NeutralPillTabsContext.Provider value={{ value, onChange: handleChange }}>
      {children}
    </NeutralPillTabsContext.Provider>
  )
}

export const NeutralPillTabsList: React.FC<{ children: React.ReactNode; className?: string }> = ({
  children,
  className = '',
}) => {
  const { value } = useNeutralPillTabsContext()
  const containerRef = useRef<HTMLDivElement>(null)
  const [indicator, setIndicator] = useState<{ left: number; width: number } | null>(null)

  useLayoutEffect(() => {
    const el = containerRef.current
    if (!el) return
    const updateIndicator = () => {
      const active = el.querySelector<HTMLElement>('[data-active="true"]')
      if (!active) return
      const cRect = el.getBoundingClientRect()
      const aRect = active.getBoundingClientRect()
      if (aRect.width === 0) return
      setIndicator({ left: aRect.left - cRect.left, width: aRect.width })
    }
    updateIndicator()
    const ro = new ResizeObserver(updateIndicator)
    ro.observe(el)
    return () => ro.disconnect()
  }, [value])

  return (
    <div ref={containerRef} className={`relative inline-flex gap-1 bg-slate-100 p-0.5 rounded-[10px] ${className}`}>
      {indicator && (
        <div
          className="absolute top-0.5 bottom-0.5 bg-white rounded-lg shadow-soft-sm pointer-events-none"
          style={{ left: indicator.left, width: indicator.width, transition: 'left 0.2s ease-out, width 0.2s ease-out' }}
        />
      )}
      {children}
    </div>
  )
}

export const NeutralPillTab: React.FC<{
  value: string
  children: React.ReactNode
  className?: string
}> = ({ value, children, className = '' }) => {
  const { value: activeValue, onChange } = useNeutralPillTabsContext()
  const isActive = activeValue === value

  return (
    <button
      type="button"
      data-active={isActive}
      className={cn(
        'relative z-10 px-4 py-1.5 text-caption transition-colors duration-150 rounded-lg cursor-pointer',
        isActive ? 'text-slate-800 font-bold' : 'text-slate-500 font-semibold hover:text-slate-800',
        className
      )}
      onClick={() => onChange(value)}
    >
      {children}
    </button>
  )
}

export type TabItem = { value: string; label: string }
