<template>
	<view class="cl-pagination">
		<view
			class="cl-pagination__prev"
			:class="[
				{
					'is-disabled': value == 1,
					'is-dark': isDark
				},
				pt.item?.className,
				pt.prev?.className
			]"
			@tap="prev"
		>
			<slot name="prev" :disabled="value == 1">
				<cl-icon
					:name="pt.prevIcon?.name ?? 'arrow-left-s-line'"
					:size="pt.prevIcon?.size"
					:color="pt.prevIcon?.color"
					:pt="{
						className: pt.prevIcon?.className
					}"
				></cl-icon>
			</slot>
		</view>

		<view
			v-for="(item, index) in list"
			:key="index"
			class="cl-pagination__item"
			:class="[
				{
					'is-active': item == value,
					'is-dark': isDark
				},
				pt.item?.className
			]"
			@tap="toPage(item)"
		>
			<cl-text
				:pt="{
					className: parseClass([
						'cl-pagination__item-text',
						{
							'text-white': item == value
						},
						pt.itemText?.className
					])
				}"
				>{{ item }}</cl-text
			>
		</view>

		<view
			class="cl-pagination__next"
			:class="[
				{
					'is-disabled': value == totalPage,
					'is-dark': isDark
				},
				pt.item?.className,
				pt.next?.className
			]"
			@tap="next"
		>
			<slot name="next" :disabled="value == totalPage">
				<cl-icon
					:name="pt.nextIcon?.name ?? 'arrow-right-s-line'"
					:size="pt.nextIcon?.size"
					:color="pt.nextIcon?.color"
					:pt="{
						className: pt.nextIcon?.className
					}"
				></cl-icon>
			</slot>
		</view>
	</view>
</template>

<script setup lang="ts">
import type { PassThroughProps } from "../../types";
import { isDark, parseClass, parsePt } from "@/cool";
import { computed, ref, watch } from "vue";
import type { ClIconProps } from "../cl-icon/props";

defineOptions({
	name: "cl-pagination"
});

const props = defineProps({
	pt: {
		type: Object,
		default: () => ({})
	},
	modelValue: {
		type: Number,
		default: 1
	},
	total: {
		type: Number,
		default: 0
	},
	size: {
		type: Number,
		default: 10
	}
});

const emit = defineEmits(["update:modelValue", "change"]);

// 透传样式类型定义
type PassThrough = {
	className?: string;
	item?: PassThroughProps;
	itemText?: PassThroughProps;
	prev?: PassThroughProps;
	prevIcon?: ClIconProps;
	next?: PassThroughProps;
	nextIcon?: ClIconProps;
};

// 解析透传样式配置
const pt = computed(() => parsePt<PassThrough>(props.pt));

// 计算总页数，根据总数和每页大小向上取整
const totalPage = computed(() => {
	if (props.total == 0) return 1;

	return Math.ceil(props.total / props.size);
});

// 绑定值
const value = ref(props.modelValue);

// 计算分页列表，根据当前页码和总页数生成显示的分页按钮
const list = computed(() => {
	const total = totalPage.value;
	const list: (number | string)[] = [];

	if (total <= 7) {
		// 总页数小于等于7，显示所有页码
		for (let i = 1; i <= total; i++) {
			list.push(i);
		}
	} else {
		// 总是显示第一页
		list.push(1);

		if (value.value <= 4) {
			// 当前页在前面: 1 2 3 4 5 ... 100
			for (let i = 2; i <= 5; i++) {
				list.push(i);
			}
			list.push("...");
			list.push(total);
		} else if (value.value >= total - 3) {
			// 当前页在后面: 1 ... 96 97 98 99 100
			list.push("...");
			for (let i = total - 4; i <= total; i++) {
				list.push(i);
			}
		} else {
			// 当前页在中间: 1 ... 4 5 6 ... 100
			list.push("...");
			for (let i = value.value - 1; i <= value.value + 1; i++) {
				list.push(i);
			}
			list.push("...");
			list.push(total);
		}
	}

	return list;
});

// 跳转到指定页面，处理页码点击事件
function toPage(item: number | string) {
	// 忽略省略号点击
	if (item == "..." || typeof item !== "number") return;

	// 边界检查，确保页码在有效范围内
	if (typeof item == "number") {
		if (item > totalPage.value) return;
		if ((item as number) < 1) return;
	}

	value.value = item;

	// 触发双向绑定更新和变化事件
	emit("update:modelValue", item);
	emit("change", item);
}

// 跳转到上一页
function prev() {
	toPage(value.value - 1);
}

// 跳转到下一页
function next() {
	toPage(value.value + 1);
}

watch(
	computed(() => props.modelValue),
	(val: number) => {
		value.value = val;
	},
	{
		immediate: true
	}
);

defineExpose({
	prev,
	next
});
</script>

<style lang="scss" scoped>
.cl-pagination {
	@apply flex flex-row justify-center w-full;

	&__prev,
	&__next,
	&__item {
		@apply flex flex-row items-center justify-center bg-surface-100 rounded-lg;
		height: 60rpx;
		width: 60rpx;

		&.is-disabled {
			@apply opacity-50;
		}

		&.is-dark {
			@apply bg-surface-700;
		}
	}

	&__item {
		margin: 0 5rpx;

		&.is-active {
			@apply bg-primary-500;
		}
	}

	&__prev {
		margin-right: 5rpx;
	}

	&__next {
		margin-left: 5rpx;
	}
}
</style>
