import { JsonValue } from 'type-fest'
import React, { useState } from 'react'

import { useValueAugmentations } from './hooks'
import {
  ArrayIndex,
  BracketDecoration,
  ObjectKey,
  Item,
  ItemList,
  PrimitiveValue,
  ToggleObjectButton,
  DefaultToggleIcon,
  LabelDecorations,
  ColonSeparator
} from './style'


export type ToggleObjectButtonProps = {
  collapsed: boolean
}

export type ObjectViewProps = {
  value: JsonValue | Record<string, unknown>
  expandButtonIcon?: React.FC<ToggleObjectButtonProps>
  label?: React.ReactNode
}

export const JSONView = ({ value, label, expandButtonIcon: ToggleIcon = DefaultToggleIcon }: ObjectViewProps) => {
  const { isObjectLike, decorations } = useValueAugmentations(value)
  const [isCollapsed, setIsCollapsed] = useState(!!label)

  return (
    <>
      {label && (
        <LabelDecorations>
          {label}
          <ColonSeparator />
          {isObjectLike && (
            <>
              <ToggleObjectButton onClick={() => setIsCollapsed(!isCollapsed)}>
                <ToggleIcon collapsed={isCollapsed} />
              </ToggleObjectButton>
              <BracketDecoration>{decorations[0]}</BracketDecoration>
              {isCollapsed && (
                <>
                  ...
                  <BracketDecoration>{decorations[1]}</BracketDecoration>
                </>
              )}
            </>
          )}
        </LabelDecorations>
      )}

      {isObjectLike && !isCollapsed && (
        <>
          {!label && <BracketDecoration>{decorations[0]}</BracketDecoration>}
          {(Array.isArray(value) && (
            <ItemList>
              {value.map((item, i) => (
                <Item key={i}>
                  <JSONView value={item} label={<ArrayIndex>{i}</ArrayIndex>} />
                </Item>
              ))}
            </ItemList>
          )) ||
            (typeof value === 'object' && value !== null && (
              <ItemList>
                {Object.entries(value).map(([k, v]) => (
                  <Item key={k}>
                    <JSONView value={v as JsonValue} label={<ObjectKey>{k}</ObjectKey>} />
                  </Item>
                ))}
              </ItemList>
            ))}
          <BracketDecoration>{decorations[1]}</BracketDecoration>
        </>
      )}

      {!isObjectLike && <PrimitiveValue rawValue={value}>{value?.toString()}</PrimitiveValue>}
    </>
  )
}
