<template>
	<view class="guess-you-like-section">
		<view v-if="showTitle" class="guess-header">
			<text class="guess-title">{{ titleText }}</text>
		</view>

		<view v-if="products.length > 0" class="guess-grid">
			<view
				v-for="product in products"
				:key="product.id"
				class="guess-card"
				@click="handleProductClick(product.id)"
			>
				<image class="guess-image" :src="product.image" mode="aspectFill" />
				<view class="guess-body">
					<text class="guess-name" :lines="2">{{ product.name }}</text>
					<view class="guess-price-row">
						<text class="guess-price">¥{{ product.price.toFixed(2) }}</text>
						<text v-if="product.originalPrice > product.price" class="guess-original-price">¥{{ product.originalPrice.toFixed(2) }}</text>
					</view>
					<text v-if="product.salesText !== ''" class="guess-sales">{{ product.salesText }}</text>
				</view>
			</view>
		</view>

		<view v-else-if="!loading && errorText === ''" class="guess-empty">
			<text class="guess-empty-text">暂无推荐商品</text>
		</view>

		<view v-if="loading" class="guess-status-row">
			<text class="guess-status-text">加载中...</text>
		</view>
		<view v-else-if="errorText !== ''" class="guess-status-row">
			<text class="guess-status-text">{{ errorText }}</text>
		</view>
		<view v-else-if="finished && products.length > 0" class="guess-status-row">
			<text class="guess-status-text">没有更多了</text>
		</view>
	</view>
</template>

<script setup lang="uts">
import { computed, onMounted, ref, watch } from 'vue'
import { supabaseService } from '@/utils/supabaseService.uts'

type RecommendProduct = {
	id: string
	name: string
	image: string
	price: number
	originalPrice: number
	salesText: string
	categoryId: string
}

const DEFAULT_IMAGE = '/static/logo.png'

const props = defineProps({
	title: {
		type: String,
		default: '猜你喜欢'
	},
	pageSize: {
		type: Number,
		default: 8
	},
	categoryId: {
		type: String,
		default: ''
	},
	excludeProductIds: {
		type: Array,
		default: () => []
	},
	loadMoreKey: {
		type: Number,
		default: 0
	},
	source: {
		type: String,
		default: ''
	},
	showTitle: {
		type: Boolean,
		default: true
	}
})

const emit = defineEmits<{
	(e: 'productClick', productId: string): void
}>()

const products = ref<Array<RecommendProduct>>([])
const page = ref<number>(1)
const loading = ref<boolean>(false)
const finished = ref<boolean>(false)
const errorText = ref<string>('')

const titleText = computed((): string => {
	return props.title as string
})

const toExcludeProductIds = (): Array<string> => {
	const result: Array<string> = []
	try {
		const normalized = JSON.parse(JSON.stringify(props.excludeProductIds))
		if (Array.isArray(normalized)) {
			for (let i = 0; i < normalized.length; i++) {
				const item = normalized[i]
				if (item != null) {
					const itemText = '' + item
					if (itemText !== '' && result.indexOf(itemText) < 0) {
						result.push(itemText)
					}
				}
			}
		}
	} catch (e) {
	}
	return result
}

const getNumberField = (obj: UTSJSONObject, key: string): number => {
	try {
		const value = obj.getNumber(key)
		if (value != null) {
			return value
		}
	} catch (e) {
	}
	return 0
}

const getStringField = (obj: UTSJSONObject, key: string): string => {
	try {
		const value = obj.getString(key)
		if (value != null) {
			return value
		}
	} catch (e) {
	}
	return ''
}

const formatSalesText = (salesCount: number): string => {
	if (salesCount <= 0) {
		return ''
	}
	if (salesCount >= 10000) {
		const value = Math.floor(salesCount / 100) / 100
		return '已售 ' + value + '万'
	}
	return '已售 ' + salesCount
}

const parseProducts = (rows: Array<UTSJSONObject>): Array<RecommendProduct> => {
	const result: Array<RecommendProduct> = []
	for (let i = 0; i < rows.length; i++) {
		const row = rows[i]
		const productId = getStringField(row, 'id')
		if (productId === '') {
			continue
		}
		const price = getNumberField(row, 'base_price') > 0 ? getNumberField(row, 'base_price') : getNumberField(row, 'price')
		const originalPrice = getNumberField(row, 'market_price') > 0 ? getNumberField(row, 'market_price') : getNumberField(row, 'original_price')
		const image = getStringField(row, 'main_image_url') !== ''
			? getStringField(row, 'main_image_url')
			: (getStringField(row, 'image_url') !== '' ? getStringField(row, 'image_url') : DEFAULT_IMAGE)
		const salesCount = getNumberField(row, 'sale_count')
		const name = getStringField(row, 'name') !== '' ? getStringField(row, 'name') : '精选商品'
		result.push({
			id: productId,
			name,
			image,
			price: price > 0 ? price : 0,
			originalPrice: originalPrice > 0 ? originalPrice : 0,
			salesText: formatSalesText(salesCount),
			categoryId: getStringField(row, 'category_id')
		})
	}
	return result
}

const loadProducts = async (reset: boolean): Promise<void> => {
	if (loading.value) {
		return
	}
	if (!reset && finished.value) {
		return
	}

	if (reset) {
		products.value = []
		page.value = 1
		finished.value = false
		errorText.value = ''
	}

	loading.value = true
	try {
		const requestParams = new UTSJSONObject()
		requestParams.set('limit', props.pageSize as number)
		requestParams.set('offset', (page.value - 1) * (props.pageSize as number))
		requestParams.set('categoryId', props.categoryId as string)
		requestParams.set('source', props.source as string)
		requestParams.set('excludeProductIds', toExcludeProductIds())

		const rows = await supabaseService.getRecommendProducts(requestParams)
		const parsed = parseProducts(rows)
		if (reset) {
			products.value = parsed
		} else {
			const merged = products.value.slice()
			for (let i = 0; i < parsed.length; i++) {
				let exists = false
				for (let j = 0; j < merged.length; j++) {
					if (merged[j].id === parsed[i].id) {
						exists = true
						break
					}
				}
				if (!exists) {
					merged.push(parsed[i])
				}
			}
			products.value = merged
		}

		if (parsed.length < (props.pageSize as number)) {
			finished.value = true
		} else {
			page.value = page.value + 1
		}
		if (parsed.length === 0 && products.value.length === 0) {
			finished.value = true
		}
	} catch (error) {
		console.error('加载猜你喜欢失败:', error)
		errorText.value = '推荐商品加载失败'
	} finally {
		loading.value = false
	}
}

const handleProductClick = (productId: string): void => {
	emit('productClick', productId)
}

watch(() => props.loadMoreKey, (newValue: number, oldValue: number) => {
	if (newValue !== oldValue) {
		loadProducts(false)
	}
})

watch(() => props.categoryId, (newValue: string, oldValue: string) => {
	if (newValue !== oldValue) {
		loadProducts(true)
	}
})

watch(() => JSON.stringify(props.excludeProductIds), (newValue: string, oldValue: string) => {
	if (newValue !== oldValue) {
		loadProducts(true)
	}
})

onMounted(() => {
	loadProducts(true)
})
</script>

<style scoped>
.guess-you-like-section {
	display: flex;
	flex-direction: column;
	margin-top: 12px;
}

.guess-header {
	padding: 0 4px 10px;
}

.guess-title {
	font-size: 16px;
	font-weight: bold;
	color: #222222;
}

.guess-grid {
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	justify-content: space-between;
}

.guess-card {
	width: 48.5%;
	background-color: #ffffff;
	border-radius: 12px;
	overflow: hidden;
	margin-bottom: 12px;
}

.guess-image {
	width: 100%;
	height: 148px;
	background-color: #f2f2f2;
}

.guess-body {
	padding: 10px;
	display: flex;
	flex-direction: column;
}

.guess-name {
	font-size: 13px;
	line-height: 19px;
	color: #222222;
	height: 38px;
	margin-bottom: 8px;
}

.guess-price-row {
	display: flex;
	flex-direction: row;
	align-items: baseline;
	flex-wrap: wrap;
}

.guess-price {
	font-size: 16px;
	font-weight: bold;
	color: #ff4d4f;
	margin-right: 6px;
}

.guess-original-price {
	font-size: 11px;
	color: #999999;
	text-decoration: line-through;
}

.guess-sales {
	font-size: 11px;
	color: #999999;
	margin-top: 6px;
}

.guess-empty,
.guess-status-row {
	padding: 14px 0;
	display: flex;
	justify-content: center;
	align-items: center;
}

.guess-empty-text,
.guess-status-text {
	font-size: 12px;
	color: #999999;
}
</style>
