import React from 'react'

export type AccentKey =
  | 'primary'
  | 'warning'
  | 'info'
  | 'success'
  | 'danger'
  | 'secondary'
  | 'green'
  | 'pink'
  | 'yellow'
  | 'light'
  | 'dark'

export interface PanelProps extends React.HTMLAttributes<HTMLDivElement> {
  size?: number
  variant?: 'border' | 'solid'
  accent?: AccentKey
  children?: React.ReactNode
}

const Panel: React.FC<PanelProps> = ({ children }) => <>{children}</>
Panel.displayName = 'SplitPanel'

interface SplitProps {
  direction?: 'horizontal' | 'vertical'
  gutter?: string | number
  className?: string
  // allow any children but we will look for Panel elements
  children?: React.ReactNode
  variant?: 'border' | 'solid'
  accent?: AccentKey
}

const Split: React.FC<SplitProps> & { Panel: React.FC<PanelProps> } = ({
  direction = 'horizontal',
  gutter = 20,
  className = '',
  children,
  variant: splitVariant,
  accent: splitAccent,
}) => {
  const childrenArray = React.Children.toArray(children)
  if (childrenArray.length < 1) {
    throw new Error('Split requires at least one child Panel')
  }

  const gutterVal = typeof gutter === 'number' ? `${gutter}px` : gutter
  const containerStyle: React.CSSProperties = { ['--split-gutter' as any]: gutterVal }

  const dirClass = direction === 'vertical' ? 'split--vertical' : 'split--horizontal'

  // detect Panel children and extract sizes and passthrough props
  const sizes: (number | null)[] = childrenArray.map((c) => {
    if (React.isValidElement(c) && (c.type as any).displayName === 'SplitPanel') {
      const p = c as React.ReactElement<PanelProps>
      return typeof p.props.size === 'number' ? p.props.size : 1
    }
    return null
  })

  const allPanels = sizes.every((s) => s != null)

  // compute flex styles if panels provided sizes

  return (
    <div className={`split ${dirClass} ${className}`.trim()} style={containerStyle}>
      {childrenArray.map((child, idx) => {
        const style: React.CSSProperties = {}
        let extraClass = ''
        let extraStyle: React.CSSProperties | undefined

        if (React.isValidElement(child) && (child.type as any).displayName === 'SplitPanel') {
          const p = child as React.ReactElement<PanelProps>
          extraClass = p.props.className || ''
          extraStyle = p.props.style
          // inherit variant/accent from parent if panel doesn't specify one
          if (!p.props.variant && splitVariant) {
            // handled below
          }
          if (!p.props.accent && splitAccent) {
            // handled below
          }
        }

        if (allPanels) {
          const unit = (sizes[idx] || 0) as number
          style.flex = `${unit} 1 0`
        }

        const mergedStyle = extraStyle ? { ...style, ...extraStyle } : style
        const childElem = React.isValidElement(child) ? (child as React.ReactElement<PanelProps>) : null
        const variant = childElem ? childElem.props.variant ?? splitVariant : splitVariant
        // Determine accent: a panel with its own `accent` always uses it.
        // Otherwise, if the parent `Split` has an `accent`, only the first
        // panel (top-left decoration) and the last panel (bottom-right)
        // receive the inherited accent. No other panels inherit the split
        // accent.
        const panelHasOwnAccent = !!(childElem && childElem.props.accent)
        let accent: AccentKey | undefined = undefined
        let accentTL = false
        let accentBR = false
        const lastIndex = childrenArray.length - 1
        const isFirst = idx === 0
        const isLast = idx === lastIndex

        if (panelHasOwnAccent) {
          // panel-specified accent: show both decorations
          accent = childElem!.props.accent as AccentKey
          accentTL = true
          accentBR = true
        } else if (splitAccent) {
          // inherited accent from Split: only first gets top-left, last gets bottom-right
          if (isFirst) {
            accent = splitAccent
            accentTL = true
          }
          if (isLast) {
            accent = splitAccent
            accentBR = true
          }
        }
        let variantClass = ''
        if (variant === 'border') variantClass = 'pane--border'
        else if (variant === 'solid') variantClass = 'pane--solid'

        const paneClass = `pane ${variantClass} ${extraClass} ${accentTL ? 'pane--accent--tl' : ''} ${accentBR ? 'pane--accent--br' : ''}`.trim()

        // attach accent color as CSS var for the mixin to pick up
        const finalStyle = { ...mergedStyle }
        if (accent) {
          ;(finalStyle as any)['--pane-accent-color'] = `var(--color-variant-${accent})`
        }

        return (
          <div className={paneClass} key={idx} style={finalStyle}>
            {child}
          </div>
        )
      })}
    </div>
  )
}

Split.Panel = Panel
export { Split }
export default Split
