import type { ReactNode } from 'react'

export type VisualTone =
  | 'slate'
  | 'blue'
  | 'violet'
  | 'amber'
  | 'emerald'
  | 'orange'
  | 'rose'
  | 'cyan'
export type TrendDirection = 'up' | 'down' | 'neutral'
export type FlowNodeVariant = 'stripe' | 'outline' | 'subtle'
export type FlowNodeSize = 'compact' | 'regular'
export type StatAccent = 'cyan' | 'rose' | 'amber' | 'violet' | 'orange' | 'emerald'

export interface StatCardProps {
  label: string
  value: ReactNode
  detail?: ReactNode
  trend?: ReactNode
  trendDirection?: TrendDirection
  accentColor?: StatAccent
  children?: ReactNode
  className?: string
}

export interface UptimeBarProps {
  percent: number
  segments?: number
  highlightIndices?: number[]
  className?: string
}

export interface MetricTileProps {
  label: string
  value: ReactNode
  icon?: ReactNode
  tone?: Exclude<VisualTone, 'rose'>
  className?: string
}

export interface FlowNodeCardProps {
  title: string
  eyebrow?: ReactNode
  meta?: ReactNode
  icon?: ReactNode
  tone?: VisualTone
  variant?: FlowNodeVariant
  size?: FlowNodeSize
  className?: string
  children?: ReactNode
}

function isClassName(value: string | false | null | undefined): value is string {
  return typeof value === 'string' && value.length > 0
}

function hasRenderableNode(value: ReactNode | undefined): boolean {
  return value !== undefined && value !== null && value !== false && value !== ''
}

function cx(...values: (string | false | null | undefined)[]): string {
  return values.filter(isClassName).join(' ')
}

function normalizeAccent(
  tone: StatCardProps['accentColor']
): 'cyan' | 'rose' | 'amber' | 'violet' | 'orange' | 'emerald' {
  return tone ?? 'cyan'
}

export function StatCard({
  label,
  value,
  detail,
  trend,
  trendDirection = 'neutral',
  accentColor = 'cyan',
  children,
  className,
}: StatCardProps) {
  const accent = normalizeAccent(accentColor)

  return (
    <div className={cx('cmm-react-stat-card', className)}>
      <p className="cmm-react-stat-card__label">{label}</p>
      {hasRenderableNode(value) && (
        <p className={cx('cmm-react-stat-card__value', `cmm-react-stat-card__value--${accent}`)}>
          {value}
        </p>
      )}
      {hasRenderableNode(detail) && <p className="cmm-react-stat-card__detail">{detail}</p>}
      {hasRenderableNode(children) && (
        <div className="cmm-react-stat-card__children">{children}</div>
      )}
      {hasRenderableNode(trend) && (
        <span
          className={cx(
            'cmm-react-stat-card__trend',
            `cmm-react-stat-card__trend--${trendDirection}`
          )}
        >
          {trend}
        </span>
      )}
    </div>
  )
}

export function UptimeBar({
  percent,
  segments = 30,
  highlightIndices = [12, 24],
  className,
}: UptimeBarProps) {
  const clampedPercent = Math.max(0, Math.min(100, percent))
  const activeSegments = Math.round((clampedPercent / 100) * segments)
  const highlights = new Set(highlightIndices)

  return (
    <div className={cx('cmm-react-uptime-bar', className)}>
      {Array.from({ length: segments }, (_, index) => (
        <div
          key={index}
          className={cx(
            'cmm-react-uptime-bar__segment',
            index < activeSegments && 'cmm-react-uptime-bar__segment--active',
            highlights.has(index)
              ? 'cmm-react-uptime-bar__segment--highlight'
              : 'cmm-react-uptime-bar__segment--default'
          )}
        />
      ))}
    </div>
  )
}

export function MetricTile({ label, value, icon, tone = 'slate', className }: MetricTileProps) {
  return (
    <div className={cx('cmm-react-metric-tile', `cmm-react-metric-tile--${tone}`, className)}>
      {hasRenderableNode(icon) && (
        <div className={cx('cmm-react-metric-tile__icon', `cmm-react-metric-tile__icon--${tone}`)}>
          {icon}
        </div>
      )}
      <div className="cmm-react-metric-tile__body">
        <div className="cmm-react-metric-tile__value">{value}</div>
        <div className="cmm-react-metric-tile__label">{label}</div>
      </div>
    </div>
  )
}

export function FlowNodeCard({
  title,
  eyebrow,
  meta,
  icon,
  tone = 'slate',
  variant = 'stripe',
  size = 'regular',
  className,
  children,
}: FlowNodeCardProps) {
  return (
    <div
      className={cx(
        'cmm-react-flow-node-card',
        `cmm-react-flow-node-card--${tone}`,
        `cmm-react-flow-node-card--${variant}`,
        `cmm-react-flow-node-card--${size}`,
        className
      )}
    >
      <div className="cmm-react-flow-node-card__header">
        {hasRenderableNode(icon) && (
          <div
            className={cx(
              'cmm-react-flow-node-card__icon',
              `cmm-react-flow-node-card__icon--${tone}`
            )}
          >
            {icon}
          </div>
        )}
        <div className="cmm-react-flow-node-card__body">
          <div className="cmm-react-flow-node-card__title">{title}</div>
          {hasRenderableNode(eyebrow) && (
            <div className="cmm-react-flow-node-card__eyebrow">{eyebrow}</div>
          )}
        </div>
      </div>
      {hasRenderableNode(meta) && <div className="cmm-react-flow-node-card__meta">{meta}</div>}
      {hasRenderableNode(children) && (
        <div className="cmm-react-flow-node-card__content">{children}</div>
      )}
    </div>
  )
}
