<template>
	<view v-if="visible" class="bottom-sheet-wrapper" @touchmove.stop.prevent>
		<view class="mask" :class="{ 'mask-active': animating }" @click="handleMaskClick" @touchmove.stop.prevent></view>
		<view class="sheet" :class="{ 'sheet-up': animating }" :style="sheetStyle">
			<view class="handle-bar"></view>
			<view class="header" :style="headerStyle">
				<text class="title" :style="titleStyle">{{ title }}</text>
				<view
					v-if="showClose"
					class="close-btn btn btn--icon"
					@click="handleClose"
					hover-class="close-btn-hover"
				>
					<text class="close-icon">×</text>
				</view>
			</view>
			<scroll-view scroll-y class="body">
				<slot></slot>
			</scroll-view>
			<view class="footer" :style="footerStyle">
				<slot name="footer"></slot>
			</view>
		</view>
	</view>
</template>

<script>
import themeMixin from '@/mixins/themeMixin.js'

export default {
	name: 'BottomSheet',
	mixins: [themeMixin],
	props: {
		visible: { type: Boolean, default: false },
		title: { type: String, default: '' },
		height: { type: String, default: '85vh' },
		showClose: { type: Boolean, default: true },
		maskClosable: { type: Boolean, default: true }
	},
	data() {
		return {
			animating: false,
			closeTimer: null
		}
	},
	computed: {
		sheetStyle() {
			return {
				maxHeight: this.height,
				background: this.themeConfig.cardBgColor
			}
		},
		headerStyle() {
			return {
				borderBottom: `2rpx solid ${this.themeConfig.borderLight}`
			}
		},
		closeBtnStyle() {
			return {
				background: this.themeConfig.borderLight
			}
		},
		titleStyle() {
			return {
				color: this.themeConfig.textPrimary
			}
		},
		footerStyle() {
			return {
				borderTop: `2rpx solid ${this.themeConfig.borderLight}`
			}
		}
	},
	watch: {
		visible(val) {
			if (val) {
				this.animating = false
				this.$nextTick(() => {
					setTimeout(() => {
						this.animating = true
					}, 30)
				})
			}
		}
	},
	created() {
		this.syncThemeConfig()
		this.watchThemeChange()
	},
	beforeUnmount() {
		if (this.themeChangeHandler) {
			uni.$off('themeChanged', this.themeChangeHandler)
		}
		if (this.closeTimer) {
			clearTimeout(this.closeTimer)
		}
	},
	methods: {
		handleMaskClick() {
			if (!this.maskClosable) return
			this.handleClose()
		},
		handleClose() {
			this.animating = false
			this.closeTimer = setTimeout(() => {
				this.$emit('update:visible', false)
				this.$emit('close')
			}, 300)
		},
		watchThemeChange() {
			this.themeChangeHandler = ({ key, config }) => {
				if (key && config) {
					this.themeConfig = config
				}
			}
			uni.$on('themeChanged', this.themeChangeHandler)
		}
	}
}
</script>

<style scoped>
.bottom-sheet-wrapper {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 99999;
}

.mask {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(0, 0, 0, 0);
	transition: background 0.3s ease;
}

.mask-active {
	background: rgba(0, 0, 0, 0.5);
}

.sheet {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	border-radius: 24rpx 24rpx 0 0;
	transform: translateY(100%);
	transition: transform 0.3s ease;
	padding-bottom: constant(safe-area-inset-bottom);
	padding-bottom: env(safe-area-inset-bottom);
}

.sheet-up {
	transform: translateY(0);
}

.handle-bar {
	width: 80rpx;
	height: 8rpx;
	background: #cccccc;
	border-radius: 4rpx;
	margin: 16rpx auto 0;
}

.header {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding: 24rpx 32rpx;
}

.title {
	font-size: 32rpx;
	font-weight: 700;
	flex: 1;
}

.close-btn {
	transition: transform 0.2s ease;
}

.close-btn-hover {
	transform: scale(0.9);
}

.close-icon {
	font-size: 32rpx;
	color: var(--textSecondary);
	line-height: 1;
}

.body {
	padding: 24rpx 32rpx;
	max-height: 60vh;
	box-sizing: border-box;
}

.footer {
	padding: 24rpx 32rpx;
}
</style>