import { Progress as ArkProgress } from '@ark-ui/solid/progress'
import { Show, splitProps, type JSX } from 'solid-js'
import { cn } from '@/utils/cn'

export interface ProgressProps extends JSX.HTMLAttributes<HTMLDivElement> {
  value?: number
  max?: number
  min?: number
  label?: string
  showValue?: boolean
  size?: 'sm' | 'md' | 'lg'
  variant?: 'default' | 'accent' | 'success' | 'warning' | 'danger'
}

const progressVariants = {
  default: 'bg-primary',
  accent: 'bg-primary-container',
  success: 'bg-success',
  warning: 'bg-warning',
  danger: 'bg-danger',
}

const progressSizes = {
  sm: 'h-1',
  md: 'h-1.5',
  lg: 'h-2',
}

export const Progress = (props: ProgressProps) => {
  const [local, rest] = splitProps(props, [
    'class',
    'value',
    'max',
    'min',
    'label',
    'showValue',
    'size',
    'variant',
  ])

  const size = () => local.size ?? 'md'
  const variant = () => local.variant ?? 'default'
  const maxValue = () => local.max ?? 100
  const minValue = () => local.min ?? 0
  const currentValue = () => local.value ?? 0

  return (
    <ArkProgress.Root
      class={cn('relative', local.class)}
      value={currentValue()}
      max={maxValue()}
      min={minValue()}
      {...rest}
    >
      <Show when={local.label || local.showValue}>
        <div class="flex items-center justify-between mb-1.5">
          <Show when={local.label}>
            <ArkProgress.Label class="text-xs font-medium text-muted-fg">
              {local.label}
            </ArkProgress.Label>
          </Show>
          <Show when={local.showValue}>
            <ArkProgress.ValueText class="text-xs font-semibold text-fg tabular-nums">
              {Math.round(currentValue())}%
            </ArkProgress.ValueText>
          </Show>
        </div>
      </Show>

      <ArkProgress.Track
        class={cn(
          'relative w-full overflow-hidden rounded-full bg-surface-high',
          progressSizes[size()],
        )}
      >
        <ArkProgress.Range
          class={cn(
            'h-full rounded-full transition-all duration-300 ease-out',
            progressVariants[variant()],
          )}
        />
      </ArkProgress.Track>
    </ArkProgress.Root>
  )
}

export interface CircularProgressProps extends JSX.HTMLAttributes<HTMLDivElement> {
  value?: number
  max?: number
  size?: number
  strokeWidth?: number
  variant?: 'default' | 'accent' | 'success' | 'warning' | 'danger'
}

const circleVariants = {
  default: 'stroke-primary',
  accent: 'stroke-primary-container',
  success: 'stroke-success',
  warning: 'stroke-warning',
  danger: 'stroke-danger',
}

export const CircularProgress = (props: CircularProgressProps) => {
  const [local, rest] = splitProps(props, [
    'class',
    'value',
    'max',
    'size',
    'strokeWidth',
    'variant',
  ])

  const size = () => local.size ?? 48
  const strokeWidth = () => local.strokeWidth ?? 4
  const variant = () => local.variant ?? 'default'
  const maxValue = () => local.max ?? 100
  const currentValue = () => local.value ?? 0

  const radius = () => (size() - strokeWidth()) / 2
  const circumference = () => radius() * 2 * Math.PI
  const offset = () => circumference() - (currentValue() / maxValue()) * circumference()

  return (
    <ArkProgress.Root
      class={cn('inline-flex', local.class)}
      value={currentValue()}
      max={maxValue()}
      {...rest}
    >
      <ArkProgress.Circle
        class="relative"
        style={{ width: `${size()}px`, height: `${size()}px` }}
      >
        <ArkProgress.CircleTrack
          class="stroke-surface-high"
          style={{ "stroke-width": `${strokeWidth()}px` }}
        />
        <ArkProgress.CircleRange
          class={cn(
            'transition-all duration-300 ease-out',
            circleVariants[variant()],
          )}
          style={{
            "stroke-width": `${strokeWidth()}px`,
            "stroke-dasharray": `${circumference()}px`,
            "stroke-dashoffset": `${offset()}px`,
            transform: 'rotate(-90deg)',
            "transform-origin": '50% 50%',
          }}
        />
        <ArkProgress.ValueText class="absolute inset-0 flex items-center justify-center text-xs font-semibold text-fg tabular-nums">
          {Math.round(currentValue())}%
        </ArkProgress.ValueText>
      </ArkProgress.Circle>
    </ArkProgress.Root>
  )
}
