<template>
	<div class="image-clip" :class="{ 'is-product': isProduct }">
		<div class="image-clip-body" ref="imageClipBody">
			<VueCropper
				ref="cropper"
				:img="url"
				crossOrigin="Anonymous"
				:autoCrop="true"
				:fixedNumber="ratio"
				fixed
				movable
				centerBox
				:fixedBox="fixedBox"
				@realTime="onChange"
				v-bind="$attrs"
				outputType="png"
			></VueCropper>
		</div>
		<div class="clip_opterate">
			<div class="item" @click="rotateLeft()">
				<span class="icon iconfont icon-chexiao operate_icon"></span>
			</div>
			<div class="item" @click="rotateRight()">
				<span class="icon iconfont icon-chexiao operate_icon icon_chexiao_sec"></span>
			</div>
			<div class="item" @click="changeScale(-0.1)">
				<span class="operate_icon icon_font">-</span>
			</div>
			<div class="item" @click="changeScale(0.1)">
				<span class="operate_icon icon_font">+</span>
			</div>
			<div class="item" @click="refreshCrop()">
				<span class="icon iconfont icon-shuaxin operate_icon"></span>
			</div>
		</div>
	</div>
</template>
<script setup>
import { ref, useAttrs, onMounted, onBeforeUnmount } from "vue"
import "vue-cropper/dist/index.css"
import { VueCropper } from "vue-cropper"
const props = defineProps({
	url: {
		type: String,
		default: ""
	},
	ratio: {
		type: Array,
		default: () => [1, 1]
	},
	isProduct: {
		type: Boolean,
		default: false
	},
	fixedBox: {
		type: Boolean,
		default:true
	}
})
const attrs = useAttrs()

const onChange = (data) => {
	if (attrs.onChange) {
		getCropUrl().then((url) => attrs.onChange(url))
	}
}
const cropper = ref(null)
const imageClipBody = ref(null)
const observer = new ResizeObserver((entries) => {
	refreshCrop()
})
onMounted(() => {
	observer.observe(imageClipBody.value)
	injectCropLabel()
})
onBeforeUnmount(() => {
	observer.disconnect()
})
const rotateLeft = () => {
	cropper.value.rotateLeft()
}
const rotateRight = () => {
	cropper.value.rotateRight()
}
const refreshCrop = () => {
	cropper.value.refresh()
}
const changeScale = (num = 1) => {
	cropper.value.changeScale(num)
}
const getCropUrl = () => {
	return new Promise((resolve, reject) => {
		cropper.value.getCropData(resolve)
	})
}
const getCropBlob = () => {
	return new Promise((resolve, reject) => {
		cropper.value.getCropBlob(resolve)
	})
}

const injectCropLabel = () => {
	const cropperBox = imageClipBody.value.querySelector(".cropper-view-box")

	if (cropperBox) {
		// Add crown label
		const crownLabel = document.createElement("div")
		crownLabel.className = "cropper-line-label label-h"
		crownLabel.textContent = "crown"
		crownLabel.style.top = "2.67%"
		crownLabel.style.left = "0"
		crownLabel.style.transform = "translateY(-50%)"
		cropperBox.appendChild(crownLabel)

		// Add hip line label
		const hipLabel = document.createElement("div")
		hipLabel.className = "cropper-line-label label-h"
		hipLabel.textContent = "hip line"
		hipLabel.style.top = "63.47%"
		hipLabel.style.left = "0"
		hipLabel.style.transform = "translateY(-50%)"
		cropperBox.appendChild(hipLabel)

		// Add mid-thigh label
		const thighLabel = document.createElement("div")
		thighLabel.className = "cropper-line-label label-h"
		thighLabel.textContent = "mid-thigh"
		thighLabel.style.top = "92.8%"
		thighLabel.style.left = "0"
		thighLabel.style.transform = "translateY(-50%)"
		cropperBox.appendChild(thighLabel)

		// Add center label
		const centerLabel = document.createElement("div")
		centerLabel.className = "cropper-line-label label-v"
		centerLabel.textContent = "center"
		centerLabel.style.top = "0"
		centerLabel.style.left = "50%"
		centerLabel.style.transform = "translate(-50%, -50%)"
		cropperBox.appendChild(centerLabel)
	}
}

defineExpose({
	getCropUrl,
	getCropBlob
})
</script>
<style lang="less" scoped>
.image-clip {
	width: 100%;
	height: 100%;
	display: flex;
	flex-direction: column;
	// height: 100%;
	background: #fff;
	border-radius: calc(2rem * 1.2);
	padding: calc(1.3rem * 1.2) calc(1.3rem * 1.2) calc(2rem * 1.2);
	box-sizing: border-box;

	.image-clip-body {
		width: 100%;
		height: calc(40rem * 1.2);
		// height: 53rem;
		background: yellow;
		:deep(.cropper-box) {
			.cropper-box-canvas {
				background-color: #ffffff;

				img {
					height: 100%;
				}
			}
		}
	}

	.clip_opterate {
		margin: calc(2.7rem * 1.2) auto 0;
		border-radius: calc(1.6rem * 1.2);
		display: flex;
		overflow: hidden;
		border: 1px solid #e2e2e4;
		width: calc(24rem * 1.2);

		.item {
			width: calc(4.7rem * 1.2);
			height: calc(4rem * 1.2);
			display: flex;
			align-items: center;
			justify-content: center;
			border-right: 0.1rem solid #e6e8ea;
			cursor: pointer;

			.icon_chexiao_sec {
				transform: rotateY(180deg); /* 垂直镜像翻转 */
			}

			.operate_icon {
				font-size: calc(1.8rem * 1.2);
				color: rgba(102, 102, 102, 1);
				font-weight: bold;
			}

			.icon_font {
				font-size: calc(2.5rem * 1.2);
				position: relative;
				top: calc(-0.3rem * 1.2);
				user-select: none;
			}

			.icon-shuaxin {
				font-size: calc(1.4rem * 1.2);
			}

			&:last-child {
				border: none;
			}
		}
	}

	&.is-product {
		.image-clip-body {
			width: 45.7rem;
			height: 45.7rem;
			:deep(.cropper-modal) {
				background: transparent;
			}
			:deep(.vue-cropper .cropper-view-box) {
				position: relative;
				overflow: visible !important;
				/* 原有的蓝色边框（outline）由组件控制，这里不干涉 */
			}

			:deep(.vue-cropper .cropper-view-box::after) {
				content: "";
				position: absolute;
				top: 0;
				left: 0;
				width: 100%;
				height: 100%;
				pointer-events: none;
				z-index: 9; /* 位于图片之上，但在控制点之下 */

				/* 绘制 4 条 #4BA5FF 的虚线 */
				background-image:
					linear-gradient(to right, #4ba5ff 50%, transparent 50%),
					/* Crown */ linear-gradient(to right, #4ba5ff 50%, transparent 50%),
					/* Hip line */ linear-gradient(to right, #4ba5ff 50%, transparent 50%),
					/* Mid-thigh */ linear-gradient(to bottom, #4ba5ff 50%, transparent 50%); /* Center */

				background-repeat: repeat-x, repeat-x, repeat-x, repeat-y;
				background-size:
					8px 1px,
					8px 1px,
					8px 1px,
					1px 8px; /* 虚线间距 */

				background-position:
					0 2.67%,
					0 63.47%,
					0 92.8%,
					50% 0;
			}
		}
	}
}
</style>

<style lang="less">
.cropper-line-label {
	position: absolute;
	color: #4ba5ff; /* 统一颜色 */
	font-size: 11px;
	font-weight: bold;
	background: rgba(255, 255, 255); /* 浅色背景确保在深色图片上可见 */
	// padding: 0 4px;
	border-radius: 2px;
	white-space: nowrap;
	pointer-events: none;
	z-index: 10;
	line-height: 1.2;
}

/* 水平线名称：放在线段上方 2px */
.label-h {
	transform: translateY(-100%);
	margin-top: -2px;
	left: 4px;
}

/* 垂直线名称：放在裁剪框顶部边缘上方 */
.label-v {
	transform: translateX(-50%);
	top: -20px;
	left: 50%;
}
</style>
