<!-- components/im-stepper/im-stepper.vue -->
<template>
    <view class="im-stepper" :class="[
        customClass,
        `im-stepper-${theme}`,
        `im-stepper-shape-${shape}`,
        { 'im-stepper-disabled': disabled }
    ]">
        <!-- 减按钮 -->
        <view v-if="showMinus" class="im-stepper-minus" :class="[
            minusClass,
            {
                'im-stepper-button-disabled': isMinusDisabled,
                'im-stepper-button-active': isMinusActive
            }
        ]" :style="[
            buttonStyle,
            isMinusDisabled ? disabledButtonStyle : {},
            isMinusActive ? buttonActiveStyle : {}
        ]" @click="onMinusClick">
            <im-icon v-if="minusIcon" :name="minusIcon" :size="iconSize" :color="buttonTextColorComputed" />
            <text v-else-if="minusText" class="im-stepper-button-text" :style="{ color: buttonTextColorComputed }">
                {{ minusText }}
            </text>
            <text v-else class="im-stepper-button-text" :style="{ color: buttonTextColorComputed }">
                −
            </text>
        </view>

        <!-- 输入框 -->
        <input v-if="showInput" ref="inputRef" class="im-stepper-input" :class="inputClass" :value="displayValue"
            :disabled="disabled || disableInput" :placeholder="placeholder" :style="inputStyle" type="number"
            :readonly="!showInput" @input="onInput" @blur="onBlur" @focus="onFocus" @keypress="onKeyPress" />

        <!-- 加按钮 -->
        <view v-if="showPlus" class="im-stepper-plus" :class="[
            plusClass,
            {
                'im-stepper-button-disabled': isPlusDisabled,
                'im-stepper-button-active': isPlusActive
            }
        ]" :style="[
            buttonStyle,
            isPlusDisabled ? disabledButtonStyle : {},
            isPlusActive ? buttonActiveStyle : {}
        ]" @click="onPlusClick">
            <im-icon v-if="plusIcon" :name="plusIcon" :size="iconSize" :color="buttonTextColorComputed" />
            <text v-else-if="plusText" class="im-stepper-button-text" :style="{ color: buttonTextColorComputed }">
                {{ plusText }}
            </text>
            <text v-else class="im-stepper-button-text" :style="{ color: buttonTextColorComputed }">
                +
            </text>
        </view>
    </view>
</template>

<script lang="ts" setup>
import { ref, computed, watch, nextTick, onMounted } from 'vue'
import type { StepperProps, StepperEmits } from '../../types/components/stepper'
import ImIcon from '../im-icon/im-icon.vue'

const props = withDefaults(defineProps<StepperProps>(), {
    modelValue: 0,
    defaultValue: 0,
    min: -Infinity,
    max: Infinity,
    step: 1,
    inputWidth: 32,
    buttonSize: 28,
    disabled: false,
    disableInput: false,
    disableMinus: false,
    disablePlus: false,
    showLimit: true,
    showInput: true,
    showPlus: true,
    showMinus: true,
    longPress: true,
    longPressInterval: 100,
    autofocus: false,
    placeholder: '',
    integer: false,
    minusIcon: '',
    plusIcon: '',
    minusText: '',
    plusText: '',
    theme: 'default',
    shape: 'circle',
    buttonColor: '#f2f3f5',
    buttonActiveColor: '#e8e8e8',
    buttonTextColor: '#323233',
    inputBgColor: '#ffffff',
    inputTextColor: '#323233',
    disabledColor: '#c8c9cc'
})

const emit = defineEmits<StepperEmits>()

// 响应式数据
const inputValue = ref(props.modelValue || props.defaultValue)
const isMinusActive = ref(false)
const isPlusActive = ref(false)
const longPressTimer = ref<number | null>(null)
const inputRef = ref<HTMLInputElement | null>(null)

// 计算属性
const displayValue = computed(() => {
    return formatValue(inputValue.value)
})

const isMinusDisabled = computed(() => {
    return (
        props.disabled ||
        props.disableMinus ||
        (props.showLimit && inputValue.value <= props.min)
    )
})

const isPlusDisabled = computed(() => {
    return (
        props.disabled ||
        props.disablePlus ||
        (props.showLimit && inputValue.value >= props.max)
    )
})

const buttonStyle = computed(() => {
    const size = props.buttonSize
    const sizeStr = typeof size === 'number' ? `${size}px` : size

    return {
        width: sizeStr,
        height: sizeStr,
        backgroundColor: props.buttonColor,
        color: props.buttonTextColor
    }
})

const buttonActiveStyle = computed(() => ({
    backgroundColor: props.buttonActiveColor
}))

const disabledButtonStyle = computed(() => ({
    backgroundColor: props.disabledColor,
    cursor: 'not-allowed',
    opacity: 0.5
}))

const inputStyle = computed(() => {
    const width = props.inputWidth
    const widthStr = typeof width === 'number' ? `${width}px` : width

    return {
        width: widthStr,
        backgroundColor: props.inputBgColor,
        color: props.inputTextColor
    }
})

const buttonTextColorComputed = computed(() => {
    // if (isMinusDisabled.value || isPlusDisabled.value) {
    //     return props.disabledColor
    // }
    return props.buttonTextColor
})

const iconSize = computed(() => {
    const size = typeof props.buttonSize === 'number'
        ? props.buttonSize * 0.6
        : 16
    return Math.max(size, 12)
})

// 格式化值
const formatValue = (value: number | string) => {
    let num = Number(value)

    // 处理NaN
    if (isNaN(num)) {
        num = props.defaultValue
    }

    // 处理整数模式
    if (props.integer) {
        num = Math.round(num)
    }

    // 处理最小值
    if (num < props.min) {
        num = props.min
    }

    // 处理最大值
    if (num > props.max) {
        num = props.max
    }

    // 处理小数精度
    const decimal = (props.step.toString().split('.')[1] || '').length
    if (decimal > 0) {
        num = Number(num.toFixed(decimal))
    }

    return num
}

// 设置值
const setValue = (value: number | string, emitChange = true) => {
    const oldValue = inputValue.value
    const newValue = formatValue(value)

    if (newValue !== oldValue) {
        inputValue.value = newValue

        if (emitChange) {
            emit('update:modelValue', newValue)
            emit('change', newValue)
        }
    }

    return newValue
}

// 减少值
const minus = () => {
    if (isMinusDisabled.value) {
        emit('overlimit', 'minus')
        return
    }

    const newValue = setValue(inputValue.value - props.step)
    emit('minus', newValue)
}

// 增加值
const plus = () => {
    if (isPlusDisabled.value) {
        emit('overlimit', 'plus')
        return
    }

    const newValue = setValue(inputValue.value + props.step)
    emit('plus', newValue)
}

// 处理减按钮点击
const onMinusClick = () => {
    if (props.disabled || isMinusDisabled.value) return
    minus()
}

// 处理加按钮点击
const onPlusClick = () => {
    if (props.disabled || isPlusDisabled.value) return
    plus()
}

// 处理输入框输入
const onInput = (event: Event) => {
    const target = event.target as HTMLInputElement
    const value = target.value

    // 过滤非数字字符
    let cleanValue = value.replace(/[^\d.-]/g, '')

    // 处理整数模式
    if (props.integer) {
        cleanValue = cleanValue.replace(/\./g, '')
    }

    // 处理多个小数点
    const parts = cleanValue.split('.')
    if (parts.length > 2) {
        cleanValue = parts[0] + '.' + parts.slice(1).join('')
    }

    // 处理负号
    if (cleanValue.startsWith('-') && props.min >= 0) {
        cleanValue = cleanValue.substring(1)
    }

    // 更新输入框值
    target.value = cleanValue

    // 设置值
    const newValue = setValue(cleanValue || 0, false)
    emit('input', newValue)
}

// 处理输入框失去焦点
const onBlur = (event: Event) => {
    const target = event.target as HTMLInputElement
    const value = target.value

    if (value === '') {
        setValue(props.defaultValue)
    } else {
        setValue(value)
    }

    emit('blur', inputValue.value)
}

// 处理输入框获得焦点
const onFocus = () => {
    emit('focus', inputValue.value)
}

// 处理键盘输入
const onKeyPress = (event: KeyboardEvent) => {
    // 阻止输入非数字字符
    const allowedKeys = [
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        '.', '-', 'Backspace', 'Delete', 'ArrowLeft', 'ArrowRight',
        'Tab', 'Enter'
    ]

    if (!allowedKeys.includes(event.key) && !event.ctrlKey && !event.metaKey) {
        event.preventDefault()
    }
}

// // 长按处理
// const startLongPress = (type: 'minus' | 'plus') => {
//     if (!props.longPress) return

//     const action = type === 'minus' ? minus : plus

//     // 立即执行一次
//     action()

//     // 设置定时器
//     longPressTimer.value = setInterval(() => {
//         action()
//     }, props.longPressInterval) as unknown as number
// }

// const stopLongPress = () => {
//     if (longPressTimer.value) {
//         clearInterval(longPressTimer.value)
//         longPressTimer.value = null
//     }
// }

// // 减按钮触摸开始
// const onMinusTouchStart = () => {
//     if (props.disabled || isMinusDisabled.value || !props.longPress) return
//     isMinusActive.value = true
//     startLongPress('minus')
// }

// // 减按钮触摸结束
// const onMinusTouchEnd = () => {
//     isMinusActive.value = false
//     stopLongPress()
// }

// // 加按钮触摸开始
// const onPlusTouchStart = () => {
//     if (props.disabled || isPlusDisabled.value || !props.longPress) return
//     isPlusActive.value = true
//     startLongPress('plus')
// }

// // 加按钮触摸结束
// const onPlusTouchEnd = () => {
//     isPlusActive.value = false
//     stopLongPress()
// }

// 监听外部值变化
watch(() => props.modelValue, (newVal) => {
    if (newVal !== undefined && newVal !== inputValue.value) {
        setValue(newVal, false)
    }
})

// 监听最小值最大值变化
watch([() => props.min, () => props.max], () => {
    setValue(inputValue.value, false)
})

// 初始化
onMounted(() => {
    // 设置初始值
    if (props.modelValue !== undefined) {
        setValue(props.modelValue, false)
    } else if (props.defaultValue !== undefined) {
        setValue(props.defaultValue, false)
    }

    // 自动聚焦
    if (props.autofocus && inputRef.value) {
        nextTick(() => {
            inputRef.value?.focus()
        })
    }
})

// 暴露方法
defineExpose({
    focus: () => {
        inputRef.value?.focus()
    },
    blur: () => {
        inputRef.value?.blur()
    },
    minus,
    plus,
    getValue: () => inputValue.value,
    setValue
})
</script>

<style lang="scss" scoped>
.im-stepper {
    display: inline-flex;
    align-items: center;
    font-size: 0;
    user-select: none;

    // 默认主题
    &.im-stepper-default {

        .im-stepper-minus,
        .im-stepper-plus {
            border: 1px solid #ebedf0;
        }

        .im-stepper-input {
            // border-top: 1px solid #ebedf0;
            // border-bottom: 1px solid #ebedf0;
            margin: 0 2px;
        }
    }

    // 圆角主题
    &.im-stepper-round {
        .im-stepper-minus {
            border-radius: 20px 0 0 20px;
        }

        .im-stepper-plus {
            border-radius: 0 20px 20px 0;
        }

        .im-stepper-input {
            border-radius: 0;
        }
    }

    // 方形主题
    &.im-stepper-square {

        .im-stepper-minus,
        .im-stepper-plus,
        .im-stepper-input {
            border-radius: 0;
        }
    }

    // 按钮形状
    &.im-stepper-shape-circle {

        .im-stepper-minus,
        .im-stepper-plus {
            border-radius: 50%;
        }
    }

    &.im-stepper-shape-square {

        .im-stepper-minus,
        .im-stepper-plus {
            border-radius: 4px;
        }
    }

    // 禁用状态
    &.im-stepper-disabled {
        opacity: 0.5;
        cursor: not-allowed;

        .im-stepper-minus,
        .im-stepper-plus,
        .im-stepper-input {
            cursor: not-allowed;
        }
    }
}

.im-stepper-minus,
.im-stepper-plus {
    display: flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    cursor: pointer;
    transition: all 0.2s;

    &:active {
        opacity: 0.8;
    }

    &.im-stepper-button-disabled {
        cursor: not-allowed;
        opacity: 0.5;

        &:active {
            opacity: 0.5;
        }
    }

    &.im-stepper-button-active {
        opacity: 0.8;
    }
}

.im-stepper-button-text {
    font-size: 16px;
    font-weight: 500;
    line-height: 1;
}

.im-stepper-input {
    min-height: 28px;
    box-sizing: border-box;
    border: none;
    font-size: 14px;
    text-align: center;
    vertical-align: middle;
    outline: none;
    -webkit-appearance: none;
    appearance: none;

    &:disabled {
        background-color: #f2f3f5;
        color: #c8c9cc;
        cursor: not-allowed;
    }

    // 隐藏数字输入框的箭头
    &::-webkit-outer-spin-button,
    &::-webkit-inner-spin-button {
        -webkit-appearance: none;
        margin: 0;
    }

    &[type="number"] {
        -moz-appearance: textfield;
    }
}

// 响应式适配
@media (max-width: 768px) {
    .im-stepper {
        .im-stepper-button-text {
            font-size: 14px;
        }

        .im-stepper-input {
            font-size: 12px;
        }
    }
}

// 深色模式适配
@media (prefers-color-scheme: dark) {
    .im-stepper {
        &.im-stepper-default {

            .im-stepper-minus,
            .im-stepper-plus {
                border-color: #333;
            }

            .im-stepper-input {
                border-color: #333;
                background-color: #1a1a1a;
                color: #fff;
            }
        }
    }
}
</style>