import { proxy, useSnapshot } from 'valtio'
import { useEffect, useRef } from 'react'
import { noCase } from 'change-case'
import { titleCase } from 'title-case'
import { hideCurrentModal, showModal } from '../globalState'
import { parseFormattedMessagePacket } from '../botUtils'
import Screen from './Screen'
import { useIsModalActive } from './utilsApp'
import Button from './Button'
import MessageFormattedString from './MessageFormattedString'
import Input, { InputWithLabel } from './Input'

const state = proxy({
  title: '',
  options: [] as string[],
  showCancel: true,
  minecraftJsonMessage: null as null | Record<string, any>,
  behavior: 'resolve-close' as 'resolve-close' | 'close-resolve',
  inputs: {} as Record<string, InputOption>,
  inputsConfirmButton: ''
})

let resolve
export const showOptionsModal = async <T extends string> (
  title: string,
  options: T[],
  { cancel = true, minecraftJsonMessage }: { cancel?: boolean, minecraftJsonMessage? } = {}
): Promise<T | undefined> => {
  showModal({ reactType: 'general-select' })
  let minecraftJsonMessageParsed
  if (minecraftJsonMessage) {
    const parseResult = parseFormattedMessagePacket(minecraftJsonMessage)
    minecraftJsonMessageParsed = parseResult.formatted
    if (parseResult.plain) {
      title += ` (${parseResult.plain})`
    }
  }
  return new Promise((_resolve) => {
    resolve = _resolve
    Object.assign(state, {
      title,
      options,
      showCancel: cancel,
      minecraftJsonMessage: minecraftJsonMessageParsed,
      inputs: {},
      inputsConfirmButton: ''
    })
  })
}

type InputOption = {
  type: 'text' | 'checkbox'
  defaultValue?: string | boolean
  label?: string
}
export const showInputsModal = async <T extends Record<string, InputOption>>(
  title: string,
  inputs: T,
  { cancel = true, minecraftJsonMessage }: { cancel?: boolean, minecraftJsonMessage? } = {}
): Promise<{
  [K in keyof T]: T[K] extends { type: 'text' }
    ? string
    : T[K] extends { type: 'checkbox' }
      ? boolean
      : never
}> => {
  showModal({ reactType: 'general-select' })
  let minecraftJsonMessageParsed
  if (minecraftJsonMessage) {
    const parseResult = parseFormattedMessagePacket(minecraftJsonMessage)
    minecraftJsonMessageParsed = parseResult.formatted
    if (parseResult.plain) {
      title += ` (${parseResult.plain})`
    }
  }
  return new Promise((_resolve) => {
    resolve = _resolve
    Object.assign(state, {
      title,
      inputs,
      showCancel: cancel,
      minecraftJsonMessage: minecraftJsonMessageParsed,
      options: [],
      inputsConfirmButton: 'Confirm'
    })
  })
}

export default () => {
  const { title, options, showCancel, minecraftJsonMessage, inputs, inputsConfirmButton } = useSnapshot(state)
  const isModalActive = useIsModalActive('general-select')
  const inputValues = useRef({})

  useEffect(() => {
    inputValues.current = Object.fromEntries(Object.entries(inputs).map(([key, input]) => [key, input.defaultValue ?? (input.type === 'checkbox' ? false : '')]))
  }, [inputs])

  if (!isModalActive) return

  const resolveClose = (value: any) => {
    if (state.behavior === 'resolve-close') {
      resolve(value)
      hideCurrentModal()
    } else {
      hideCurrentModal()
      resolve(value)
    }
  }

  return <Screen title={title} backdrop>
    {minecraftJsonMessage && <div style={{ textAlign: 'center', }}>
      <MessageFormattedString message={minecraftJsonMessage} />
    </div>}
    <div style={{ display: 'flex', flexDirection: 'column', gap: 9 }}>
      {options.length > 0 && <div style={{ display: 'flex', flexDirection: 'column', gap: 5 }}>
        {options.map(option => <Button
          key={option} onClick={() => {
            resolveClose(option)
          }}
        >{option}
        </Button>)}
      </div>}
      <div style={{ display: 'flex', flexDirection: 'column', gap: 3 }}>
        {Object.entries(inputs).map(([key, input]) => {
          const label = input.label ?? titleCase(noCase(key))
          return <div key={key}>
            {input.type === 'text' && (
              <InputWithLabel
                label={label}
                autoFocus
                type='text'
                defaultValue={input.defaultValue as string}
                onChange={(e) => {
                  inputValues.current[key] = e.target.value
                }}
              />
            )}
            {input.type === 'checkbox' && (
              <label style={{ display: 'flex', alignItems: 'center', gap: 4, fontSize: 12 }}>
                <input
                  type='checkbox'
                  style={{ marginBottom: -1, }}
                  defaultChecked={input.defaultValue as boolean}
                  onChange={(e) => {
                    inputValues.current[key] = e.target.checked
                  }}
                />
                {label}
              </label>
            )}
          </div>
        })}
      </div>
      {inputs && inputsConfirmButton && (
        <Button
          // style={{ marginTop: 30 }}
          onClick={() => {
            resolveClose(inputValues.current)
          }}
        >
          {inputsConfirmButton}
        </Button>
      )}
      {showCancel && (
        <Button
          // style={{ marginTop: 30 }}
          onClick={() => {
            resolveClose(undefined)
          }}
        >
          Cancel
        </Button>
      )}
    </div>
  </Screen>
}
