<template>
    <view class="im-input" :class="[
        `im-input--${size}`,
        `im-input--${type}`,
        {
            'im-input--focused': focused,
            'im-input--disabled': disabled,
            'im-input--readonly': readonly,
            'im-input--bordered': bordered,
            'im-input--round': round,
            'im-input--underline': underline,
            'im-input--shadow': shadow,
            'im-input--error': error,
            'im-input--success': success,
            'im-input--warning': warning,
            'im-input--loading': loading,
            'im-input--with-prefix': hasPrefix,
            'im-input--with-suffix': hasSuffix,
            'im-input--with-prepend': hasPrepend,
            'im-input--with-append': hasAppend
        },
        customClass
    ]" :style="[customStyle, computedStyle]" @click="handleClick">
        <!-- 前置内容 -->
        <view v-if="hasPrepend" class="im-input__prepend" @click.stop="handlePrependClick">
            <slot name="prepend">
                <text class="im-input__prepend-text">{{ prepend }}</text>
            </slot>
        </view>

        <!-- 输入框主体 -->
        <view class="im-input__wrapper">
            <!-- 前置图标 -->
            <view v-if="hasPrefixIcon || $slots.prefix" class="im-input__prefix" @click.stop="handlePrefixClick">
                <slot name="prefix">
                    <text v-if="prefixIcon" class="im-input__prefix-icon" :class="prefixIcon" />
                </slot>
            </view>

            <!-- 前置文本 -->
            <text v-if="prefix" class="im-input__prefix-text">
                {{ prefix }}
            </text>

            <!-- 输入区域 -->
            <view class="im-input__content">
                <!-- 文本输入框 -->
                <input v-if="type !== 'textarea'" class="im-input__inner"
                    :class="{ 'im-input__inner--password': showPassword }" :value="displayValue" :type="inputType"
                    :placeholder="placeholder" :placeholder-class="placeholderClass" :disabled="disabled || readonly"
                    :readonly="readonly" :maxlength="computedMaxlength" :focus="autofocus"
                    :password="isPassword && !passwordVisible" :confirm-type="confirmType"
                    :cursor-spacing="cursorSpacing" :selection-end="selectionEnd" :selection-start="selectionStart"
                    :adjust-position="adjustPosition" :hold-keyboard="holdKeyboard" :cursor="cursor"
                    @input="handleInput" @focus="handleFocus" @blur="handleBlur" @confirm="handleConfirm"
                    @keydown="handleKeydown" @keyup="handleKeyup" @selectionchange="handleSelectionChange" />

                <!-- 文本域 -->
                <textarea v-else class="im-input__textarea" :value="displayValue" :placeholder="placeholder"
                    :placeholder-class="placeholderClass" :disabled="disabled || readonly" :readonly="readonly"
                    :maxlength="computedMaxlength" :focus="autofocus" :auto-height="autoHeight" :fixed="fixed"
                    :cursor-spacing="cursorSpacing" :show-confirm-bar="showConfirmBar" :selection-end="selectionEnd"
                    :selection-start="selectionStart" :adjust-position="adjustPosition" :hold-keyboard="holdKeyboard"
                    :cursor="cursor" :disable-default-padding="disableDefaultPadding" @input="handleTextareaInput"
                    @focus="handleFocus" @blur="handleBlur" @confirm="handleConfirm" @keydown="handleKeydown"
                    @keyup="handleKeyup" @selectionchange="handleSelectionChange" @linechange="handleLinechange" />

                <!-- 清除按钮 -->
                <view v-if="showClear" class="im-input__clear" @click.stop="handleClear">
                    <view class="im-input__clear-icon">
                        <im-icon name="close" :size="size" />
                    </view>
                </view>

                <!-- 密码可见切换 -->
                <view v-if="showPasswordToggle" class="im-input__password-toggle" @click.stop="togglePasswordVisible">
                    <view class="im-input__password-icon">
                        <im-icon :name="passwordVisible ? 'eye' : 'eye-off'" :size="size" />
                    </view>
                </view>

                <!-- 加载状态 -->
                <view v-if="loading" class="im-input__loading">
                    <view class="im-input__loading-icon">
                        <im-icon name="loading" :size="size" spin />
                    </view>
                </view>

                <!-- 字数统计 -->
                <view v-if="showCount" class="im-input__count">
                    <text class="im-input__count-text">
                        {{ currentLength }}{{ computedMaxlength ? `/${computedMaxlength}` : '' }}
                    </text>
                </view>
            </view>

            <!-- 后置文本 -->
            <text v-if="suffix" class="im-input__suffix-text">
                {{ suffix }}
            </text>

            <!-- 后置图标 -->
            <view v-if="hasSuffixIcon || $slots.suffix" class="im-input__suffix" @click.stop="handleSuffixClick">
                <slot name="suffix">
                    <text v-if="suffixIcon" class="im-input__suffix-icon" :class="suffixIcon" />
                </slot>
            </view>
        </view>

        <!-- 后置内容 -->
        <view v-if="hasAppend" class="im-input__append" @click.stop="handleAppendClick">
            <slot name="append">
                <text class="im-input__append-text">{{ append }}</text>
            </slot>
        </view>
    </view>
</template>

<script setup lang="ts">
import {
    ref,
    computed,
    watch,
    nextTick,
    useSlots,
    type CSSProperties
} from 'vue'
import type {
    InputProps,
    InputEmits
} from '../../types/components/input'
import {
    SIZE_CONFIG,
    STATUS_COLORS,
    DEFAULT_CONFIG
} from './constants'
import {
    getFormatter,
    parseFormattedValue,
    validateInput,
    debounce
} from './utils'

// 使用Slots
const slots = useSlots()

const props = withDefaults(defineProps<InputProps & {
    // 原生属性
    placeholderClass?: string
    confirmType?: 'send' | 'search' | 'next' | 'go' | 'done'
    cursorSpacing?: number
    selectionStart?: number
    selectionEnd?: number
    adjustPosition?: boolean
    holdKeyboard?: boolean
    cursor?: number
    fixed?: boolean
    showConfirmBar?: boolean
    disableDefaultPadding?: boolean
}>(), {
    modelValue: '',
    type: DEFAULT_CONFIG.TYPE,
    size: DEFAULT_CONFIG.SIZE,
    placeholder: '',
    disabled: false,
    readonly: false,
    clearable: true,
    clearTrigger: DEFAULT_CONFIG.CLEAR_TRIGGER,
    maxlength: undefined,
    showCount: false,
    bordered: DEFAULT_CONFIG.BORDERED,
    autofocus: false,
    autoHeight: true,
    password: false,
    confirmPassword: false,
    formatType: undefined,
    formatter: undefined,
    parser: undefined,
    prefixIcon: '',
    suffixIcon: '',
    prefix: '',
    suffix: '',
    prepend: '',
    append: '',
    showPasswordToggle: true,
    customStyle: () => ({}),
    customClass: '',
    round: DEFAULT_CONFIG.ROUND,
    underline: false,
    shadow: DEFAULT_CONFIG.SHADOW,
    error: false,
    success: false,
    warning: false,
    loading: false,
    // 原生属性默认值
    placeholderClass: 'input-placeholder',
    confirmType: 'done',
    cursorSpacing: 0,
    selectionStart: -1,
    selectionEnd: -1,
    adjustPosition: true,
    holdKeyboard: false,
    cursor: -1,
    fixed: false,
    showConfirmBar: true,
    disableDefaultPadding: false
})

const emit = defineEmits<InputEmits>()

// 响应式数据
const focused = ref(false)
const passwordVisible = ref(false)
const currentLength = ref(0)
const internalValue = ref('')

// 计算属性
const hasPrefix = computed(() => {
    return props.prefix || props.prefixIcon || !!slots.prefix
})

const hasSuffix = computed(() => {
    return props.suffix || props.suffixIcon || !!slots.suffix
})

const hasPrepend = computed(() => {
    return props.prepend || !!slots.prepend
})

const hasAppend = computed(() => {
    return props.append || !!slots.append
})

const hasPrefixIcon = computed(() => {
    return !!props.prefixIcon
})

const hasSuffixIcon = computed(() => {
    return !!props.suffixIcon
})

const isPassword = computed(() => {
    return props.type === 'password' || props.password || props.confirmPassword
})

const showPassword = computed(() => {
    return isPassword.value && !passwordVisible.value
})

const showClear = computed(() => {
    if (!props.clearable || props.disabled || props.readonly) {
        return false
    }

    if (props.clearTrigger === 'never') {
        return false
    }

    if (props.clearTrigger === 'always') {
        return !!internalValue.value
    }

    return !!internalValue.value
})

const showPasswordToggle = computed(() => {
    return isPassword.value && props.showPasswordToggle
})

const inputType = computed(() => {
    if (isPassword.value) {
        return 'text'
    }
    return props.type
})

const computedMaxlength = computed(() => {
    if (props.maxlength === undefined) {
        return props.type === 'textarea' ? 140 : 20
    }
    return props.maxlength
})

// 格式化显示值
const displayValue = computed(() => {
    const rawValue = String(internalValue.value || '')

    if (props.formatType) {
        const formatter = getFormatter(props.formatType)
        return formatter(rawValue)
    }

    if (props.formatter) {
        return props.formatter(rawValue)
    }

    return rawValue
})

// 计算样式
const computedStyle = computed(() => {
    const style: CSSProperties = {}
    const sizeConfig = SIZE_CONFIG[props.size]

    // 设置高度
    if (props.type === 'textarea' && props.autoHeight) {
        style.minHeight = sizeConfig.height
    } else {
        style.height = sizeConfig.height
    }

    // 设置字体大小
    style.fontSize = sizeConfig.fontSize

    // 设置状态颜色
    if (props.error) {
        style.borderColor = STATUS_COLORS.error
        style.color = STATUS_COLORS.error
    } else if (props.success) {
        style.borderColor = STATUS_COLORS.success
        style.color = STATUS_COLORS.success
    } else if (props.warning) {
        style.borderColor = STATUS_COLORS.warning
        style.color = STATUS_COLORS.warning
    } else if (props.loading) {
        style.borderColor = STATUS_COLORS.loading
        style.color = STATUS_COLORS.loading
    }

    return style
})

// 初始化值
watch(() => props.modelValue, (newValue) => {
    internalValue.value = String(newValue || '')
    currentLength.value = internalValue.value.length
}, { immediate: true })

// 处理输入
const handleInput = (event: any) => {
    const value = event.detail.value

    // 解析格式化值
    let rawValue = value
    if (props.formatType) {
        rawValue = parseFormattedValue(value, props.formatType)
    } else if (props.parser) {
        rawValue = props.parser(value)
    }

    // 验证输入
    const validation = validateInput(rawValue, props.type, props.maxlength)
    if (!validation.valid) {
        // 验证失败，可以显示错误信息
        console.warn('输入验证失败:', validation.message)
    }

    // 更新内部值
    internalValue.value = rawValue
    currentLength.value = rawValue.length

    // 触发事件
    emit('update:modelValue', rawValue)
    emit('input', rawValue)

    // 防抖处理 change 事件
    debouncedChange(rawValue, event)
}

// 处理文本域输入
const handleTextareaInput = (event: any) => {
    handleInput(event)

    // 文本域特殊处理
    if (props.autoHeight) {
        nextTick(() => {
            // 调整高度
        })
    }
}

// 防抖的 change 事件
const debouncedChange = debounce((value: string, event: any) => {
    emit('change', value)
}, 300)

// 处理焦点事件
const handleFocus = (event: any) => {
    focused.value = true
    emit('focus', event)
}

// 处理失焦事件
const handleBlur = (event: any) => {
    focused.value = false
    emit('blur', event)
}

// 处理确认事件
const handleConfirm = (event: any) => {
    emit('enter', event)
}

// 处理键盘事件
const handleKeydown = (event: any) => {
    emit('keydown', event)
}

const handleKeyup = (event: any) => {
    emit('keyup', event)
}

// 处理选择变化
const handleSelectionChange = (event: any) => {
    // 可以保存选择位置
}

// 处理行变化（textarea）
const handleLinechange = (event: any) => {
    // 处理行数变化
}

// 清除输入
const handleClear = () => {
    internalValue.value = ''
    currentLength.value = 0
    emit('update:modelValue', '')
    emit('clear')
}

// 切换密码可见性
const togglePasswordVisible = () => {
    passwordVisible.value = !passwordVisible.value
}

// 点击事件
const handleClick = (event: any) => {
    emit('click', event)
}

const handlePrefixClick = () => {
    emit('clickPrefix')
}

const handleSuffixClick = () => {
    emit('clickSuffix')
}

const handlePrependClick = () => {
    emit('clickPrepend')
}

const handleAppendClick = () => {
    emit('clickAppend')
}

// 暴露方法
defineExpose({
    focus: () => {
        // 触发聚焦
    },
    blur: () => {
        // 触发失焦
    },
    clear: handleClear,
    getValue: () => internalValue.value,
    setValue: (value: string) => {
        internalValue.value = value
        emit('update:modelValue', value)
    },
    validate: () => {
        return validateInput(internalValue.value, props.type, props.maxlength)
    }
})
</script>

<style lang="scss" scoped>
.im-input {
    display: flex;
    align-items: center;
    width: 100%;
    box-sizing: border-box;
    transition: all 0.2s ease;

    // 基础样式
    &__wrapper {
        display: flex;
        align-items: center;
        flex: 1;
        position: relative;
    }

    &__content {
        display: flex;
        align-items: center;
        flex: 1;
        position: relative;
    }

    &__inner,
    &__textarea {
        flex: 1;
        width: 100%;
        border: none;
        outline: none;
        background: transparent;
        color: inherit;
        font-family: inherit;
        font-size: inherit;
        line-height: 1.5;

        &::placeholder {
            color: #999999;
        }
    }

    &__inner {
        height: 100%;
        padding: 0;

        &--password {
            letter-spacing: 2rpx;
        }
    }

    &__textarea {
        min-height: 120rpx;
        resize: none;

        .im-input--auto-height & {
            min-height: auto;
        }
    }

    // 尺寸样式
    &--small {
        .im-input__inner {
            height: 64rpx;
            font-size: 24rpx;
        }

        &.im-input--bordered .im-input__inner {
            padding: 0 20rpx;
        }

        &.im-input--bordered .im-input__textarea {
            padding: 10rpx;
        }
    }

    &--medium {
        .im-input__inner {
            height: 80rpx;
            font-size: 28rpx;
        }

        &.im-input--bordered .im-input__inner {
            padding: 0 24rpx;
        }

        &.im-input--bordered .im-input__textarea {
            padding: 24rpx;
        }
    }

    &--large {
        .im-input__inner {
            height: 96rpx;
            font-size: 32rpx;
        }

        &.im-input--bordered .im-input__inner {
            padding: 0 32rpx;
        }

        &.im-input--bordered .im-input__textarea {
            padding: 28rpx;
        }
    }

    // 边框
    &--bordered {
        background-color: #ffffff;
        border: 2rpx solid #dcdee0;
        border-radius: 10rpx;
        overflow: hidden;

        &.im-input--focused {
            border-color: #c9cacb;
            box-shadow: 0 0 0 2rpx rgba(109, 108, 108, 0.1);
        }
    }

    // 圆角
    &--round {
        border-radius: 500rpx;
    }

    // 下划线
    &--underline {

        .im-input__inner,
        .im-input__textarea {
            text-decoration: underline;
        }
    }

    // 阴影
    &--shadow {
        box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
    }

    // 状态
    &--error {
        border-color: #e64340 !important;
        color: #e64340;

        &.im-input--focused {
            box-shadow: 0 0 0 2rpx rgba(230, 67, 64, 0.1);
        }
    }

    &--success {
        border-color: #07c160 !important;
        color: #07c160;
    }

    &--warning {
        border-color: #f0a020 !important;
        color: #f0a020;

        &.im-input--focused {
            box-shadow: 0 0 0 2rpx rgba(240, 160, 32, 0.1);
        }
    }

    &--loading {
        border-color: #1989fa !important;
        color: #1989fa;
    }

    // 禁用和只读
    &--disabled {
        opacity: 0.6;
        cursor: not-allowed;
        background-color: #f5f5f5;

        .im-input__inner,
        .im-input__textarea {
            cursor: not-allowed;
        }
    }

    &--readonly {
        cursor: default;
        background-color: #f9f9f9;
    }

    // 前置/后置内容
    &__prepend,
    &__append {
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0 24rpx;
        background-color: #f5f5f5;
        border: 2rpx solid #dcdee0;
        color: #666666;
        white-space: nowrap;
        height: 100%;

        &:active:not(.im-input--disabled) {
            opacity: 0.8;
        }
    }

    &__prepend {
        border: none;
        // border-top-left-radius: 8rpx;
        // border-bottom-left-radius: 8rpx;
    }

    &__append {
        border: none;
        // border-top-right-radius: 8rpx;
        // border-bottom-right-radius: 8rpx;
    }

    &__prepend-text,
    &__append-text {
        font-size: inherit;
    }

    // 前缀/后缀
    &__prefix,
    &__suffix {
        display: flex;
        align-items: center;
        justify-content: center;
        color: #999999;
        flex-shrink: 0;

        &:active:not(.im-input--disabled) {
            opacity: 0.8;
        }
    }

    &__prefix-text,
    &__suffix-text {
        color: #666666;
        font-size: inherit;
        flex-shrink: 0;
    }

    &__prefix-text {
        margin-left: 16rpx;
    }

    &__suffix-text {
        margin-right: 16rpx;
    }

    &__prefix-icon,
    &__suffix-icon {
        font-size: inherit;
    }

    // 操作图标
    &__clear,
    &__password-toggle,
    &__loading {
        display: flex;
        align-items: center;
        justify-content: center;
        margin-left: 12rpx;
        color: #999999;
        flex-shrink: 0;

        &:active:not(.im-input--disabled) {
            opacity: 0.8;
        }
    }

    &__password-toggle {
        margin-left: -16rpx;
    }

    &__clear-icon,
    &__loading-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 32rpx;
        height: 32rpx;
        transition: all 0.2s ease;
        margin-right: 16rpx;
    }

    &__clear-icon {
        border-radius: 50%;
        background-color: #f0f0f0;

        &:hover:not(.im-input--disabled) {
            background-color: #e0e0e0;
        }
    }

    &__password-icon {
        margin-right: 8rpx;
    }

    &__loading-icon {
        margin-left: -16rpx;
        // animation: rotating 1s linear infinite;
    }

    @keyframes rotating {
        from {
            transform: rotate(0deg);
        }

        to {
            transform: rotate(360deg);
        }
    }

    // 字数统计
    &__count {
        margin-left: 12rpx;
        color: #999999;
        font-size: 90%;
        flex-shrink: 0;
        margin-right: 12rpx;
    }

    &__count-text {
        font-size: inherit;
    }

    // 类型特定样式
    &--textarea {
        align-items: flex-start;

        .im-input__content {
            align-items: flex-start;
        }

        .im-input__clear,
        .im-input__password-toggle,
        .im-input__loading {
            margin-top: 24rpx;
        }

        .im-input__count {
            position: absolute;
            right: 0;
            bottom: 8rpx;
        }
    }

    &--search {
        .im-input__prefix-icon {
            color: #07c160;
        }
    }
}
</style>