import ButtonGroup from '@components/forms/ButtonGroup'
import Checkbox from '@components/forms/Checkbox'
import Input from '@components/forms/Input'
import Label from '@components/forms/Label'
import { HotKey } from '@components/settings/HotKeysSettings'
import Button from '@components/shared/Button'
import InlineNotification from '@components/shared/InlineNotification'
import Modal from '@components/shared/Modal'
import Tooltip from '@components/shared/Tooltip'
import useLocalStorageState from 'hooks/useLocalStorageState'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
import { ModalProps } from 'types/modal'
import { HOT_KEYS_KEY } from 'utils/constants'

type FormErrors = Partial<Record<keyof HotKeyForm, string>>

type HotKeyForm = {
  baseKey: string
  triggerKey: string
  price: string
  side: 'buy' | 'sell'
  size: string
  sizeType: 'percentage' | 'notional'
  orderType: 'limit' | 'market'
  ioc: boolean
  post: boolean
  margin: boolean
  reduce: boolean
}

const DEFAULT_FORM_VALUES: HotKeyForm = {
  baseKey: 'shift',
  triggerKey: '',
  price: '',
  side: 'buy',
  size: '',
  sizeType: 'percentage',
  orderType: 'limit',
  ioc: false,
  post: false,
  margin: false,
  reduce: false,
}

const HotKeyModal = ({ isOpen, onClose }: ModalProps) => {
  const { t } = useTranslation(['common', 'settings', 'trade'])
  const [hotKeys, setHotKeys] = useLocalStorageState<HotKey[]>(HOT_KEYS_KEY, [])
  const [hotKeyForm, setHotKeyForm] = useState<HotKeyForm>({
    ...DEFAULT_FORM_VALUES,
  })
  const [formErrors, setFormErrors] = useState<FormErrors>({})

  const handleSetForm = (propertyName: string, value: string | boolean) => {
    setFormErrors({})
    setHotKeyForm((prevState) => ({ ...prevState, [propertyName]: value }))
  }

  const handlePostOnlyChange = (postOnly: boolean) => {
    if (postOnly) {
      handleSetForm('ioc', !postOnly)
    }
    handleSetForm('post', postOnly)
  }

  const handleIocChange = (ioc: boolean) => {
    if (ioc) {
      handleSetForm('post', !ioc)
    }
    handleSetForm('ioc', ioc)
  }

  const isFormValid = (form: HotKeyForm) => {
    const invalidFields: FormErrors = {}
    setFormErrors({})
    const triggerKey: (keyof HotKeyForm)[] = ['triggerKey']
    const requiredFields: (keyof HotKeyForm)[] = ['size', 'price', 'triggerKey']
    const numberFields: (keyof HotKeyForm)[] = ['size', 'price']
    const alphanumericRegex = /^[a-zA-Z0-9]+$/
    for (const key of triggerKey) {
      const value = form[key] as string
      if (value.length > 1) {
        invalidFields[key] = t('settings:error-too-many-characters')
      }
      if (!alphanumericRegex.test(value)) {
        invalidFields[key] = t('settings:error-alphanumeric-only')
      }
    }
    for (const key of requiredFields) {
      const value = form[key] as string
      if (!value) {
        if (hotKeyForm.orderType === 'market') {
          if (key !== 'price') {
            invalidFields[key] = t('settings:error-required-field')
          }
        } else {
          invalidFields[key] = t('settings:error-required-field')
        }
      }
    }
    for (const key of numberFields) {
      const value = form[key] as string
      if (value) {
        if (isNaN(parseFloat(value))) {
          invalidFields[key] = t('settings:error-must-be-number')
        }
        if (parseFloat(value) < 0) {
          invalidFields[key] = t('settings:error-must-be-above-zero')
        }
        if (parseFloat(value) > 100) {
          if (key === 'price') {
            invalidFields[key] = t('settings:error-must-be-below-100')
          } else {
            if (hotKeyForm.sizeType === 'percentage') {
              invalidFields[key] = t('settings:error-must-be-below-100')
            }
          }
        }
      }
    }
    const newKeySequence = `${form.baseKey}+${form.triggerKey}`
    const keyExists = hotKeys.find((k) => k.keySequence === newKeySequence)
    if (keyExists) {
      invalidFields.triggerKey = t('settings:error-key-in-use')
    }
    if (Object.keys(invalidFields).length) {
      setFormErrors(invalidFields)
    }
    return invalidFields
  }

  const handleSave = () => {
    const invalidFields = isFormValid(hotKeyForm)
    if (Object.keys(invalidFields).length) {
      return
    }
    const newHotKey = {
      keySequence: `${hotKeyForm.baseKey}+${hotKeyForm.triggerKey}`,
      orderSide: hotKeyForm.side,
      orderSizeType: hotKeyForm.sizeType,
      orderSize: hotKeyForm.size,
      orderType: hotKeyForm.orderType,
      orderPrice: hotKeyForm.price,
      ioc: hotKeyForm.ioc,
      margin: hotKeyForm.margin,
      postOnly: hotKeyForm.post,
      reduceOnly: hotKeyForm.reduce,
    }
    setHotKeys([...hotKeys, newHotKey])
    onClose()
  }

  return (
    <Modal isOpen={isOpen} onClose={onClose}>
      <>
        <h2 className="mb-4 text-center">{t('settings:new-hot-key')}</h2>
        <div className="mb-4">
          <Label text={t('settings:base-key')} />
          <ButtonGroup
            activeValue={hotKeyForm.baseKey}
            onChange={(key) => handleSetForm('baseKey', key)}
            values={['shift', 'ctrl']}
          />
        </div>
        <div className="mb-4">
          <Label text={t('settings:trigger-key')} />
          <Input
            hasError={formErrors.triggerKey !== undefined}
            type="text"
            value={hotKeyForm.triggerKey}
            onChange={(e) =>
              handleSetForm('triggerKey', e.target.value.toLowerCase())
            }
          />
          {formErrors.triggerKey ? (
            <div className="mt-1">
              <InlineNotification
                type="error"
                desc={formErrors.triggerKey}
                hideBorder
                hidePadding
              />
            </div>
          ) : null}
        </div>
        <div className="mb-4">
          <Label text={t('settings:order-side')} />
          <ButtonGroup
            activeValue={hotKeyForm.side}
            names={[t('buy'), t('sell')]}
            onChange={(side) => handleSetForm('side', side)}
            values={['buy', 'sell']}
          />
        </div>
        <div className="mb-4">
          <Label text={t('trade:order-type')} />
          <ButtonGroup
            activeValue={hotKeyForm.orderType}
            names={[t('trade:limit'), t('market')]}
            onChange={(type) => handleSetForm('orderType', type)}
            values={['limit', 'market']}
          />
        </div>
        <div className="mb-4">
          <Label text={t('settings:order-size-type')} />
          <ButtonGroup
            activeValue={hotKeyForm.sizeType}
            names={[t('settings:percentage'), t('settings:notional')]}
            onChange={(type) => handleSetForm('sizeType', type)}
            values={['percentage', 'notional']}
          />
        </div>
        <div className="flex items-start space-x-4">
          <div className="w-full">
            <Tooltip
              content={
                hotKeyForm.sizeType === 'notional'
                  ? t('settings:tooltip-hot-key-notional-size')
                  : t('settings:tooltip-hot-key-percentage-size')
              }
            >
              <Label className="tooltip-underline" text={t('trade:size')} />
            </Tooltip>
            <Input
              hasError={formErrors.size !== undefined}
              type="text"
              value={hotKeyForm.size}
              onChange={(e) => handleSetForm('size', e.target.value)}
              suffix={hotKeyForm.sizeType === 'percentage' ? '%' : 'USD'}
            />
            {formErrors.size ? (
              <div className="mt-1">
                <InlineNotification
                  type="error"
                  desc={formErrors.size}
                  hideBorder
                  hidePadding
                />
              </div>
            ) : null}
          </div>
          {hotKeyForm.orderType === 'limit' ? (
            <div className="w-full">
              <Tooltip content={t('settings:tooltip-hot-key-price')}>
                <Label className="tooltip-underline" text={t('price')} />
              </Tooltip>
              <Input
                hasError={formErrors.price !== undefined}
                type="text"
                value={hotKeyForm.price}
                onChange={(e) => handleSetForm('price', e.target.value)}
                placeholder="e.g. 1%"
                suffix="%"
              />
              {formErrors.price ? (
                <div className="mt-1">
                  <InlineNotification
                    type="error"
                    desc={formErrors.price}
                    hideBorder
                    hidePadding
                  />
                </div>
              ) : null}
            </div>
          ) : null}
        </div>
        <div className="flex flex-wrap md:flex-nowrap">
          {hotKeyForm.orderType === 'limit' ? (
            <div className="flex">
              <div className="mr-3 mt-4" id="trade-step-six">
                <Tooltip
                  className="hidden md:block"
                  delay={100}
                  content={t('trade:tooltip-post')}
                >
                  <Checkbox
                    checked={hotKeyForm.post}
                    onChange={(e) => handlePostOnlyChange(e.target.checked)}
                  >
                    {t('trade:post')}
                  </Checkbox>
                </Tooltip>
              </div>
              <div className="mr-3 mt-4" id="trade-step-seven">
                <Tooltip
                  className="hidden md:block"
                  delay={100}
                  content={t('trade:tooltip-ioc')}
                >
                  <div className="flex items-center text-xs text-th-fgd-3">
                    <Checkbox
                      checked={hotKeyForm.ioc}
                      onChange={(e) => handleIocChange(e.target.checked)}
                    >
                      IOC
                    </Checkbox>
                  </div>
                </Tooltip>
              </div>
            </div>
          ) : null}
          <div className="mr-3 mt-4" id="trade-step-eight">
            <Tooltip
              className="hidden md:block"
              delay={100}
              content={t('trade:tooltip-enable-margin')}
            >
              <Checkbox
                checked={hotKeyForm.margin}
                onChange={(e) => handleSetForm('margin', e.target.checked)}
              >
                {t('trade:margin')}
              </Checkbox>
            </Tooltip>
          </div>
          <div className="mr-3 mt-4">
            <Tooltip
              className="hidden md:block"
              delay={100}
              content={
                'Reduce will only decrease the size of an open position. This is often used for closing a position.'
              }
            >
              <div className="flex items-center text-xs text-th-fgd-3">
                <Checkbox
                  checked={hotKeyForm.reduce}
                  onChange={(e) => handleSetForm('reduce', e.target.checked)}
                >
                  {t('trade:reduce-only')}
                </Checkbox>
              </div>
            </Tooltip>
          </div>
        </div>
        <Button className="mt-6 w-full" onClick={handleSave}>
          {t('settings:save-hot-key')}
        </Button>
      </>
    </Modal>
  )
}

export default HotKeyModal
