<script lang="tsx">
import {
  defineComponent, type PropType,
  ref, watch,
} from 'vue'

/**
 * Компонент фильтрации по диапазону чисел
 */
export default defineComponent({
  props: {
    /**
     * Функция на ввод значений в инпуты
     */
    addValue: {
      type: Function as PropType<(values: { from: number | undefined, to: number | undefined }) => void>,
      required: true,
    },
    /**
     * Вариант отображения фильтра (filter, form)
     */
    appearance: {
      type: String as PropType<'filter'|'form'>,
      default: 'filter',
    },
    /**
     * Значение фильтра
     */
    modelValue: {
      type: Object as PropType<{ from?: number, to?: number }>,
      required: true,
    },
    /**
     * Заголовок фильтра
     */
    label: {
      type: String,
      default: '',
    },
    /**
     * Функция сброса значений фильтра
     */
    removeValues: {
      type: Function as PropType<() => void>,
      default: () => () => ({}),
    },
    /**
     * Тип используемого числа
     */
    type: {
      type: String as PropType<'Integer'|'Float'>,
      default: 'Float',
    },
    /**
     * Разрешать ли вводить отрицательные числа
     */
    allowNegative: {
      type: Boolean,
      default: false,
    },
  },

  setup(props) {
    const fromInput = ref(String(props.modelValue.from ?? ''))
    const toInput = ref(String(props.modelValue.to ?? ''))

    watch(() => props.modelValue.from, (nv) => {
      fromInput.value = nv === undefined ? '' : String(nv)
    })
    watch(() => props.modelValue.to, (nv) => {
      toInput.value = nv === undefined ? '' : String(nv)
    })

    const setValues = (valRaw: string | number | undefined, isTo: boolean): string => {
      let val = String(valRaw ?? '')

      let pattern: RegExp
      if (props.type === 'Float') {
        pattern = props.allowNegative ? /[^0-9.-]/g : /[^0-9.]/g
      } else {
        pattern = props.allowNegative ? /[^0-9-]/g : /[^0-9]/g
      }
      val = val.replaceAll(pattern, '')

      if (props.allowNegative) {
        if (val.startsWith('-')) {
          val = `-${val.slice(1).replace(/-/g, '')}`
        } else {
          val = val.replace(/-/g, '')
        }
      } else {
        val = val.replace(/-/g, '')
      }

      if (val.startsWith('.')) val = `0${val}`
      if (val === '-.') val = '-0.' // если ввели '-.'

      // оставить только первую точку
      if (props.type === 'Float') {
        const parts = val.split('.')
        if (parts.length > 2) {
          const intPart = parts.shift() || ''
          val = `${intPart}.${parts.join('')}`
        }
      } else {
        if (val.includes('.')) {
          const [intPart] = val.split('.')
          val = intPart
        }
      }

      const inputReady = val

      const parsedNum = parseFloat(inputReady)
      const parsed: number | undefined = Number.isNaN(parsedNum) ? undefined : parsedNum

      // Если число === 0, но строка начинается с '-', это 'отрицательный ноль' — не отправляем его родителю,
      // чтобы не получить String(-0) => '0' и тем самым не перезаписать ввод пользователя.
      const isNegativeZero = parsed === 0 && inputReady.startsWith('-')

      const sendNumber: number | undefined = (parsed === undefined || isNegativeZero) ? undefined : parsed

      const from: number | undefined = !isTo ? sendNumber : (props.modelValue.from)
      const to: number | undefined = isTo ? sendNumber : (props.modelValue.to)

      props.addValue({ from, to })

      if (!isTo) fromInput.value = inputReady
      else toInput.value = inputReady

      return inputReady
    }

    const onChange = (currentInput: 'from' | 'to') => {
      if (!props.modelValue.from || !props.modelValue.to) return
      if (props.modelValue.to < props.modelValue.from) {
        props.addValue({
          from: currentInput === 'from' ? props.modelValue.from : undefined,
          to: currentInput === 'to' ? props.modelValue.to : undefined,
        })
      }
    }

    return () => {
      if (props.appearance === 'form') {
        return (
          <div class="ark-ui-filterbar-range-number-filter">
            {props.label && (
              <div class="ark-ui-filterbar-range-number-filter-label">{props.label}</div>
            )}

            <div class="ark-ui-filterbar-range-number-filter-body ark-ui-input-box">
              <div class="ark-ui-input">
                <div class="ark-ui-filterbar-range-number-filter-input-placeholder">от</div>
                <input
                  type='text'
                  class="ark-ui-input-element"onInput={(evt) => {
                    if (!evt?.target) return
                    const target = evt.target as HTMLInputElement
                    const val = target.value
                    target.value = setValues(val, false)
                  }}
                  value={String(props.modelValue.from ?? '')}
                  onChange={() => onChange('from')}
                />
                {Boolean(props.modelValue.from) && (
                  <div class="ark-ui-filterbar-range-number-filter-input-clear" onClick={() => setValues(undefined, false)} />
                )}
              </div>
              <div class="ark-ui-input">
                <div class="ark-ui-filterbar-range-number-filter-input-placeholder">до</div>
                <input
                  type='text'
                  class="ark-ui-input-element"
                  onInput={(evt) => {
                    if (!evt?.target) return
                    const target = evt.target as HTMLInputElement
                    const val = target.value
                    target.value = setValues(val, true)
                  }}
                  value={String(props.modelValue.to ?? '')}
                  onChange={() => onChange('to')}
                />
                {Boolean(props.modelValue.to) && (
                  <div class="ark-ui-filterbar-range-number-filter-input-clear" onClick={() => setValues(undefined, true)} />
                )}
              </div>
            </div>
          </div>
        )
      }

      return <div class='ark-ui-table-range-number-header-body active'>
        <input
          value={props.modelValue.from}
          onInput={(evt) => {
            if (!evt?.target) return
            const target = evt.target as HTMLInputElement
            const val = target.value
            target.value = setValues(val, false)
          }}

          class="ark-ui-table-range-number-header-input ark-ui-input-element"
          type='text'
          placeholder="от"
          onChange={() => onChange('from')}
        />
        <svg width="80" height="8" viewBox="0 0 8 7" fill="none" xmlns="http://www.w3.org/2000/svg">
          {/* eslint-disable-next-line max-len */}
          <path fill-rule="evenodd" clip-rule="evenodd" d="M3.03646e-05 3.49997C3.03823e-05 3.22383 0.223888 2.99997 0.50003 2.99997L6.29292 2.99997L4.14644 0.853494C3.95118 0.658232 3.95118 0.341649 4.14644 0.146387C4.34171 -0.048875 4.65829 -0.0488755 4.85355 0.146387L7.85358 3.14642C7.94735 3.24018 8.00003 3.36736 8.00003 3.49997C8.00003 3.63258 7.94735 3.75976 7.85358 3.85352L4.85355 6.85355C4.65829 7.04882 4.34171 7.04882 4.14645 6.85355C3.95118 6.65829 3.95118 6.34171 4.14645 6.14645L6.29292 3.99997L0.50003 3.99997C0.223888 3.99997 3.03767e-05 3.77611 3.03646e-05 3.49997Z" fill="#A3A7B9" />
        </svg>
        <input
          value={props.modelValue.to}
          onInput={(evt) => {
            if (!evt?.target) return
            const target = evt.target as HTMLInputElement
            const val = target.value
            target.value = setValues(val, true)
          }}

          class="ark-ui-table-range-number-header-input ark-ui-input-element"
          type='text'
          placeholder="до"
          onChange={() => onChange('to')}
        />
        <button onClick={() => props.removeValues()} class="ark-ui-table-range-number-header-reset">
          <svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
            {/* eslint-disable-next-line max-len */}
            <path d="M0.146721 0.146447C0.341983 -0.0488155 0.658566 -0.0488155 0.853828 0.146447L4.00027 3.29289L7.14672 0.146447C7.34198 -0.0488155 7.65857 -0.0488155 7.85383 0.146447C8.04909 0.341709 8.04909 0.658291 7.85383 0.853553L4.70738 4L7.85383 7.14645C8.04909 7.34171 8.04909 7.65829 7.85383 7.85355C7.65857 8.04882 7.34198 8.04882 7.14672 7.85355L4.00027 4.70711L0.853828 7.85355C0.658566 8.04882 0.341983 8.04882 0.146721 7.85355C-0.0485409 7.65829 -0.0485409 7.34171 0.146721 7.14645L3.29317 4L0.146721 0.853553C-0.0485409 0.658291 -0.0485409 0.341709 0.146721 0.146447Z" fill="#A3A7B9" />
          </svg>
        </button>
      </div>
    }
  },
})
</script>

<style lang="scss" scoped>
.ark-ui-filterbar-range-number-filter {
  &-label {
    margin-bottom: 8px;
    color: #585B69;
    font-size: 12px;
    font-weight: 400;
  }
  &-body {
    gap: 8px;
    display: flex;
    width: 100%;
    justify-content: space-between;
  }
  &-input-placeholder {
    margin-right: 8px;
    font-size: 14px;
    color: #A3A7B9;
  }
  &-input-clear {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    cursor: pointer;
    background: url('./../../assets/check-cyan.svg') center center no-repeat;
  }
  .ark-ui-input {
    min-width: 0;
  }
}

.ark-ui-input-element {
  -moz-appearance: textfield;
  &::-webkit-inner-spin-button,
  &::-webkit-outer-spin-button {
    -webkit-appearance: none;
    margin: 0;
  }
}

.ark-storybook {
  .ark-ui-table-range-number-header-body {
    position: static;
  }
}

.ark-ui-table-range-number-header-body {
  width: calc(100% + 28px);
  display: flex;
  align-items: center;
  padding: 12px 16px;
  position: absolute;
  box-sizing: border-box;

  background-color: #fff;
  box-shadow: 0 8px 16px rgba(75, 77, 89, 0.08);

  * {
    margin: 0 6px;
  }
}

.ark-ui-table-range-number-header-input {
  width: 100%;
  border: none;
  outline: none;
  background: none;

  font-size: 14px;
  color: #585B69;
  font-weight: 500;
  line-height: 16px;

  &::placeholder {
    color: #A3A7B9;
    font-weight: 400;
  }

  &:focus {
    border-bottom: 1px solid #30C1CF;
  }
}

.ark-ui-table-range-number-header-reset {
  width: 16px;
  height: 16px;
  margin-left: 8px;
  padding: 0;
  border: none;
  cursor: pointer;
  background: transparent;
}
</style>
