<template>
	<view class="auto-width-input-container" :class="{ 'is-textarea': type === 'textarea' }">
		<!-- 测量层：用于计算宽度的影藏文本，必须保持与 input 相同的字体样式 -->
		<text v-if="type !== 'textarea'" class="measure-text" :style="[inputStyle, { visibility: 'hidden', position: 'absolute', whiteSpace: 'nowrap' }]">
			{{ modelValue || placeholder }}
		</text>

		<!-- 输入层 -->
		<template v-if="type !== 'textarea'">
			<input v-if="!disabled" class="auto-input" :type="type" :value="modelValue" :placeholder="placeholder"
				:placeholder-style="placeholderStyle" :style="[inputStyle, { width: finalInputWidth }]" @input="onInput"
				:maxlength="maxlength" :focus="isFocus" @blur="onBlur" :readonly="readonly" />
			<view v-else class="auto-input flex-align-center"
				:style="[inputStyle, { width: finalInputWidth }, !modelValue ? placeholderStyleObject : {}]">
				{{ modelValue || placeholder }}
			</view>
		</template>
		<template v-else>
			<textarea v-if="!disabled" class="auto-textarea" :value="modelValue" :placeholder="placeholder"
				:placeholder-style="placeholderStyle" :style="[inputStyle]" @input="onInput" :maxlength="maxlength"
				auto-height :focus="isFocus" @blur="onBlur" :readonly="readonly" />
			<view v-else class="auto-textarea" :style="[inputStyle, !modelValue ? placeholderStyleObject : {}]">
				{{ modelValue || placeholder }}
			</view>
		</template>

		<!-- 编辑图标 -->
		<image v-if="showEdit" class="edit-icon" src="/static/image/common/edit.png" @click="handleFocusIcon"></image>
	</view>
</template>

<script setup>
import { ref, computed, watch, nextTick, getCurrentInstance, onMounted } from 'vue';

const props = defineProps({
	modelValue: {
		type: [String, Number],
		default: ''
	},
	type: {
		type: String,
		default: 'text' // 支持所有原生类型如 'number', 'tel', 'digit' 或 'textarea'
	},
	placeholder: {
		type: String,
		default: '请输入'
	},
	placeholderStyle: {
		type: String,
		default: 'color: #999;'
	},
	fontSize: {
		type: String,
		default: '28rpx'
	},
	fontWeight: {
		type: String,
		default: 'normal'
	},
	color: {
		type: String,
		default: '#1A1A1A'
	},
	maxlength: {
		type: Number,
		default: 140
	},
	minWidth: {
		type: String,
		default: '20rpx'
	},
	extraWidth: {
		type: Number,
		default: 10 // 额外的缓冲像素，防止文字抖动
	},
	showEdit: {
		type: Boolean,
		default: false
	},
	readonly: {
		type: Boolean,
		default: false
	},
	disabled: {
		type: Boolean,
		default: false
	}
});

const emit = defineEmits(['update:modelValue', 'change']);
const instance = getCurrentInstance();
const inputWidth = ref(props.minWidth);
// 最终应用的宽度样式
const finalInputWidth = computed(() => {
	// 如果是 textarea 或者设置了填满父级，则不使用测量出的宽度
	if (props.type === 'textarea') return '100%';
	// 尝试检测 class 中是否包含撑开逻辑
	const classStr = instance.proxy.$attrs.class || '';
	if (classStr.includes('flex-1') || classStr.includes('w100')) {
		return '100%';
	}
	return inputWidth.value;
});
const isFocus = ref(false);

const placeholderStyleObject = computed(() => {
	const style = {};
	if (!props.placeholderStyle) return style;
	const parts = props.placeholderStyle.split(';');
	parts.forEach(part => {
		const [key, value] = part.split(':');
		if (key && value) {
			const camelKey = key.trim().replace(/-([a-z])/g, (g) => g[1].toUpperCase());
			style[camelKey] = value.trim();
		}
	});
	return style;
});

const inputStyle = computed(() => ({
	fontSize: props.fontSize,
	fontWeight: props.fontWeight,
	color: props.color,
	fontFamily: 'inherit'
}));

/**
 * 点击图标触发聚焦
 */
const handleFocusIcon = () => {
	isFocus.value = false;
	nextTick(() => {
		isFocus.value = true;
	});
};

/**
 * 失去焦点处理
 */
const onBlur = () => {
	isFocus.value = false;
};

/**
 * 核心逻辑：测量隐藏文本的物理宽度
 */
const updateWidth = () => {
	if (props.type === 'textarea') return;
	// 如果是强制撑开模式，理论上不需要测量，但为了防止切换状态时的布局闪烁，我们仍保持测量
	nextTick(() => {
		const query = uni.createSelectorQuery().in(instance.proxy);
		query.select('.measure-text').boundingClientRect(data => {
			if (data && data.width) {
				heatWidth(data.width);
			}
		}).exec();
	});
};

const heatWidth = (width) => {
	// 加上一点额外的空间，避免在某些平台上因为小数点或字体渲染导致的文字换行
	inputWidth.value = (width + props.extraWidth) + 'px';
};

const onInput = (e) => {
	const val = e.detail.value;
	emit('update:modelValue', val);
	emit('change', val);
};

// 监听值的变化实时更新宽度
watch(() => props.modelValue, () => {
	updateWidth();
});

// 初始化
onMounted(() => {
	updateWidth();
});
</script>

<style lang="less" scoped>
.auto-width-input-container {
	position: relative;
	display: inline-flex; // 默认维持自适应宽度
	align-items: center;
	vertical-align: middle;
	max-width: 100%;
	flex-wrap: nowrap;
	
	// 当父级赋予 flex-1 或手动设置 width: 100% 时，转为标准 flex 布局
	&.flex-1, &.w100 {
		display: flex !important;
		width: 100% !important;
	}

	&.is-textarea {
		display: flex !important;
		width: 100%;
		align-items: flex-start;
		flex-direction: row !important;
	}

	.measure-text {
		left: -9999rpx;
		top: -9999rpx;
		pointer-events: none;
	}

	.auto-input {
		min-width: v-bind('props.minWidth');
		padding: 0;
		margin: 0;
		text-align: inherit;
		height: 1.4em;
		line-height: 1.4em;
		flex-shrink: 0;
		
		// 如果容器是撑开的，input 也应该撑开
		& {
			flex: 1;
		}
	}

	.auto-textarea {
		flex: 1 !important;
		width: 0 !important;
		min-width: 0;
		min-height: 1.4em;
		padding: 0;
		margin: 0;
		line-height: 1.4em;
		display: block;
	}

	.edit-icon {
		width: 28rpx;
		height: 28rpx;
		margin-left: 8rpx;
		flex-shrink: 0;
		margin-top: 4rpx;
	}
}
</style>
