<template>
	<u-popup 
		:show="show" 
		mode="bottom" 
		:closeOnClickOverlay="closeOnClickOverlay"
		:zIndex="zIndex"
		:closeable="closeable"
		:safeAreaInsetBottom="safeAreaInsetBottom"
		:bgColor="bgColor"
		:round="round"
		@close="onClose"
	>
		<view class="u-cascader">
			<!-- 头部 -->
			<view class="u-cascader__header">
				<text class="u-cascader__title" :style="[{
					color: titleColor,
					fontSize: titleFontSize
				}]">{{ title }}</text>
			</view>
			
			<!-- 标签页 -->
			<view class="u-cascader__tabs">
				<u-tabs 
					:list="tabsList"
					:current="activeTabIndex"
					:scrollable="true"
					:activeStyle="{ color: activeColor, fontWeight: '600' }"
					:inactiveStyle="{ color: color }"
					:lineColor="activeColor"
					:keyName="'name'"
					@change="switchTab"
				></u-tabs>
			</view>
			
			<!-- 选项列表 -->
			<scroll-view class="u-cascader__content" scroll-y>
				<view class="u-cascader__list">
					<view 
						v-for="(item, index) in currentOptions" 
						:key="index"
						class="u-cascader__item"
						:class="{ 'u-cascader__item--selected': isSelected(item) }"
						:style="[{
							backgroundColor: isSelected(item) ? activeBgColor : '',
							height: $u.addUnit(itemHeight), 
						}]"
						@tap="selectItem(item)"
					>
						<text class="u-cascader__item-text" :style="[{ 
							fontWeight: isSelected(item) && activeBold ? '800' : '400',
							fontSize: $u.addUnit(fontSize)
						}]">
							{{ getLabel(item) }}
						</text>
						<view v-if="isSelected(item)"  class="u-cascader__item-right">
							<u-icon name="checkmark" size="18" :color="iconColor || activeColor"></u-icon>
						</view>
					</view>
				</view>
			</scroll-view>
		</view>
	</u-popup>
</template>

<script>
import props from './props.js';
import mixin from '../../libs/mixin/mixin';
import mpMixin from '../../libs/mixin/mpMixin';

/**
 * Cascader 级联选择器
 * @description 级联选择器，用于多级数据的选择，支持单选和多选模式
 * @tutorial https://uview.d3u.cn/components/cascader.html
 * @property {Boolean}		show				是否显示级联选择器（默认 false ）
 * @property {String}		title				选择器标题（默认 '请选择' ）
 * @property {Array}		options				选项数据（默认 [] ）
 * @property {String|Number|Array} modelValue	当前选中值
 * @property {String}		placeholder			占位符文本（默认 '请选择' ）
 * @property {Object}		field			自定义字段名（默认 {text: 'text', value: 'value', children: 'children'} ）
 * @property {Boolean}		closeable			是否显示关闭按钮（默认 true ）
 * @property {Boolean}		closeOnClickOverlay	是否点击遮罩关闭（默认 true ）
 * @property {String}		bgColor				背景色（默认 '#ffffff' ）
 * @property {String}		activeColor			主题色（默认 '#3c9cff' ）
 * @property {String}		color				文本色（默认 '#303133' ）
 * @property {String}		fontSize			字体大小（默认 '16px' ）
 * @property {String}		titleFontSize		标题字体大小（默认 '18px' ）
 * @property {String}		borderRadius		圆角（默认 '12px' ）
 * @property {String|Number} zIndex			层级（默认 10075 ）
 * @property {Boolean}		safeAreaInsetBottom	是否安全区域（默认 true ）
 * @property {String}		itemHeight			选项高度（默认 '50px' ）
 * 
 * @event {Function} change 选择改变时触发
 * @event {Function} close 关闭时触发
 * @event {Function} confirm 确认选择时触发
 * @event {Function} selected 选择时触发
 * @example <u-cascader :show="show" :options="options" @change="onChange"></u-cascader>
 */
export default {
	name: "u-cascader",
	mixins: [mpMixin, mixin, props],
	data() {
		return {
			selectedPath: [], // 选择路径
			tabs: [], // 标签页数据
			activeTabIndex: 0, // 当前激活的标签页索引
			currentOptions: [], // 当前层级的选项
			optionsStack: [] // 选项栈，存储每一级的选项
		}
	},
	
	computed: {
		// 获取字段名配置
		fieldConfig() {
			return {
				label: this.field.text || this.field.label || 'label',
				value: this.field.value || 'value',
				children: this.field.children || 'children'
			}
		},
		
		// 当前选中的值
		currentValue() {
			// #ifdef VUE2
			return this.value
			// #endif

			// #ifdef VUE3
			return this.modelValue || this.value
			// #endif
		},
		
		// 是否可以添加新标签页
		canAddTab() {
			if (this.selectedPath.length === 0) return false
			const lastSelected = this.selectedPath[this.selectedPath.length - 1]
			return this.hasChildren(lastSelected)
		},

		// 标签页列表数据
		tabsList() {
			const list = this.tabs.map(tab => ({
				name: tab.label,
				label: tab.label
			}))
			
			// 首次打开或者有子项时显示占位符
			// 首次打开：tabs为空时
			// 有子项：选择了某项且该项有子项时
			if (this.tabs.length === 0 || this.canAddTab) {
				list.push({
					name: this.placeholder,
					label: this.placeholder
				})
			}
			
			return list
		}
	},
	
	watch: {
		show: {
			handler(newVal) {
				if (newVal) {
					this.init()
				}
			},
			immediate: true
		},
		
		options: {
			handler() {
				if (this.show) {
					this.init()
				}
			},
			deep: true
		},
		
		currentValue: {
			handler() {
				if (this.show) {
					this.init()
				}
			}
		}
	},
	
	// #ifdef VUE3
	emits: ['update:modelValue', 'change', 'close', 'confirm', 'selected'],
	// #endif
	
	methods: {
		// 初始化
		init() {
			this.selectedPath = []
			this.tabs = []
			this.activeTabIndex = 0
			this.optionsStack = []
			this.currentOptions = this.options || []
			this.optionsStack.push(this.currentOptions)
			
			// 如果有初始值，则定位到对应的层级
			if (this.currentValue) {
				this.initWithValue()
			}
		},
		
		// 根据初始值初始化选择状态
		initWithValue() {
			const value = Array.isArray(this.currentValue) ? this.currentValue : [this.currentValue]
			let currentOptions = this.options || []
			
			for (let i = 0; i < value.length; i++) {
				const targetValue = value[i]
				const item = currentOptions.find(option => this.getValue(option) === targetValue)
				
				if (item) {
					this.selectedPath.push(item)
					this.tabs.push({
						label: this.getLabel(item),
						level: i
					})
					
					if (this.hasChildren(item)) {
						currentOptions = this.getChildren(item)
						this.optionsStack.push(currentOptions)
					} else {
						break
					}
				} else {
					break
				}
			}
			
			this.activeTabIndex = this.tabs.length > 0 ? this.tabs.length - 1 : 0
			this.currentOptions = this.optionsStack[this.activeTabIndex] || []
		},
		
		// 选择项目
		selectItem(item) {
			const currentLevel = this.activeTabIndex
			
			// 更新选择路径
			this.selectedPath = this.selectedPath.slice(0, currentLevel)
			this.selectedPath.push(item)
			
			// 更新标签页
			this.tabs = this.tabs.slice(0, currentLevel)
			this.tabs.push({
				label: this.getLabel(item),
				level: currentLevel
			})
			
			// 清理选项栈后续数据
			this.optionsStack = this.optionsStack.slice(0, currentLevel + 1)
			
			// 触发选择事件
			this.emitSelected(item)
			
			if (this.hasChildren(item)) {
				// 有子项，添加新的选项到栈中
				const childOptions = this.getChildren(item)
				this.optionsStack.push(childOptions)
				
				// 自动切换到下一个标签页
				this.activeTabIndex = currentLevel + 1
				this.currentOptions = childOptions
			} else {
				// 没有子项，完成选择，直接触发confirm并关闭
				this.emitChange()
				this.emitConfirm()
				this.onClose()
			}
		},
		
		// 切换标签页
		switchTab(event) {
			// u-tabs组件的change事件传递的是对象 {item, index}
			const index = event.index
			this.activeTabIndex = index
			this.currentOptions = this.optionsStack[index] || []
		},
		
		// 获取选项的显示文本
		getLabel(item) {
			return item[this.fieldConfig.label] || ''
		},
		
		// 获取选项的值
		getValue(item) {
			return item[this.fieldConfig.value]
		},
		
		// 获取选项的子项
		getChildren(item) {
			return item[this.fieldConfig.children] || []
		},
		
		// 判断是否有子项
		hasChildren(item) {
			const children = this.getChildren(item)
			return Array.isArray(children) && children.length > 0
		},
		
		// 判断选项是否被选中
		isSelected(item) {
			if (this.selectedPath.length <= this.activeTabIndex) {
				return false
			}
			const selectedItem = this.selectedPath[this.activeTabIndex]
			return selectedItem && this.getValue(selectedItem) === this.getValue(item)
		},
		
		// 获取选中的值数组
		getSelectedValues() {
			return this.selectedPath.map(item => this.getValue(item))
		},
		
		// 获取选中的标签数组
		getSelectedLabels() {
			return this.selectedPath.map(item => this.getLabel(item))
		},
		
		// 触发change事件
		emitChange() {
			const values = this.getSelectedValues()
			const labels = this.getSelectedLabels()
			const selectedItems = [...this.selectedPath]
			
			const result = {
				value: values,
				label: labels,
				selectedItems
			}
			
			// #ifdef VUE2
			this.$emit('input', values)
			// #endif

			// #ifdef VUE3
			this.$emit('update:modelValue', values)
			// #endif
			
			this.$emit('change', result)
		},
		
		// 触发selected事件
		emitSelected(item) {
			this.$emit('selected', {
				item,
				level: this.activeTabIndex,
				selectedPath: [...this.selectedPath]
			})
		},
		
		// 触发confirm事件
		emitConfirm() {
			const values = this.getSelectedValues()
			const labels = this.getSelectedLabels()
			const selectedItems = [...this.selectedPath]
			
			this.$emit('confirm', {
				value: values,
				label: labels,
				selectedItems
			})
		},
		
		// 关闭选择器
		onClose() {
			this.$emit('close')
		}
	}
}
</script>

<style lang="scss" scoped>
@import "../../libs/css/components.scss";

.u-cascader {
	@include flex(column);
	
	&__header {
		position: relative;
		padding-top: 15px;
		padding-bottom: 5px;
	}
	
	&__title {
		text-align: center;
	}
	
	&__tabs {
		
	}
	
	&__content {
		flex: 1;
		// #ifndef APP-NVUE
		min-height: 0;
		// #endif
	}
	
	&__list {
		padding: 0;
		height: 320px;
	}
	
	&__item {
		@include flex(row);
		align-items: center;
		justify-content: space-between;
		padding: 0 15px;
	}
	
	&__item-text {
		flex: 1;
		overflow: hidden;
		text-overflow: ellipsis;
		font-size: 15px;
		// #ifndef APP-NVUE
		white-space: nowrap;
		// #endif
	}
	
	&__item-right {
		@include flex(row);
		align-items: center;
		margin-left: 10px;
	}
}
</style>
