<template>
	<view class="container">
		<div style="display: flex;flex-direction: column;">
			<div style="display: flex;">
				<button type="primary" style="width:100%;margin-bottom: 10px;" @click="switchRoles">
					交换
				</button>
				<button type="primary" style="width:100%;margin-bottom: 10px;" @click="calculateBestMatch">
					计算最佳配对
				</button>
			</div>

			<uni-table border stripe emptyText="暂无更多数据">
				<uni-tr>
					<uni-th width="55px">角色</uni-th>
					<uni-th align="left" width="55px">数量</uni-th>
					<uni-th align="left" width="55px">性别</uni-th>
					<uni-th align="left" width="120px">势力</uni-th>
					<uni-th align="left" width="37px">操作</uni-th>
				</uni-tr>


				<uni-tr v-for="(item, index) in inputData" :key="index">
					<uni-td rowspan="1">{{ item.role }}</uni-td>


					<uni-td>{{ item.num }}</uni-td>
					<uni-td>{{ item.gender }}</uni-td>
					<uni-td class="text-power">
						<view>{{ item.power }}</view>
					</uni-td>


					<uni-td>
						<uni-icons class="edit-button" type="compose" size="16"
							@click="editRow(item.gender, item.role, index)" />
					</uni-td>
				</uni-tr>
			</uni-table>
		</div>

		<!-- 输出表格 -->
		<view class="section" v-if="outputData.length > 0">
			<div style="display: flex;justify-content: space-between;margin-top:10px">
				<text class="section-title">输出， 计算时间 {{ time }} ms </text>
				<span>差额: {{ powerDifference }}</span>
			</div>

			<uni-table border stripe emptyText="暂无更多数据">
				<uni-tr>
					<uni-th width="60px" rowspan="2">顺序</uni-th>
					<uni-th align="left" colspan="2" width="120px">目标</uni-th>
					<uni-th align="left" colspan="2" width="120px">备选</uni-th>
				</uni-tr>

				<uni-tr>
					<uni-th align="left" width="60px">目标</uni-th>
					<uni-th align="left" width="60px">备选</uni-th>
					<uni-th align="left" width="60px">目标</uni-th>
					<uni-th align="left" width="60px">备选</uni-th>
				</uni-tr>

				<uni-tr v-for="(item, index) in outputData" :key="index">
					<uni-td>{{ index + 1 }}</uni-td>
					<uni-td>{{ item.targetMale }}</uni-td>
					<uni-td>{{ item.targetFemale }}</uni-td>
					<uni-td>{{ item.backupMale }}</uni-td>
					<uni-td>{{ item.backupFemale }}</uni-td>
				</uni-tr>

				<uni-tr>
					<uni-td>合计</uni-td>
					<uni-td colspan="2">{{ totalTarget }}</uni-td>
					<uni-td colspan="2">{{ totalBackup }}</uni-td>
				</uni-tr>
			</uni-table>
		</view>


		<uni-popup ref="batchRef" :is-mask-click="false">
			<div
				style="display: flex;flex-direction: column;justify-content: center;padding: 10px; width: 95%;background: #fff;border-radius: 10px;padding: 10px;">
				<div style="display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;">
					<span></span>
					<h4 style="margin-bottom: 10px"> 编辑{{ role }}</h4>
					<uni-icons type="closeempty" size="18" @click="batchRef.close()"></uni-icons>
				</div>


				<div style="display: flex;justify-content: space-between; align-items: center;" v-if="gender === '公'">
					<span class="dialog-title">猫咪势力(公)</span>
					<uni-icons type="close" size="18" @click="malePowers = ''"></uni-icons>
				</div>

				<textarea v-model="powers" placeholder="用逗号或顿号隔开，如:200,10,100"
					style="height: 70px;border: 1px solid #dfe2e5" v-if="gender === '公'" />

				<div style="display: flex;justify-content: space-between; align-items: center;" v-if="gender === '母'">
					<span class="dialog-title">猫咪势力(母)</span>
					<uni-icons type="close" size="18" @click="feMalePowers = ''"></uni-icons>
				</div>

				<textarea v-model="powers" placeholder="用逗号或顿号隔开，如:200,10,100"
					style="height: 70px;border: 1px solid #dfe2e5" v-if="gender === '母'" />

				<button size='mini' type="primary" @click="handleConfirm">保存</button>
			</div>
		</uni-popup>


		<uni-popup ref="messageRef" type="message">
			<uni-popup-message type="error" :message="messageText" :duration="5000"></uni-popup-message>
		</uni-popup>
	</view>
</template>

<script setup>
import { ref } from 'vue';



const messageText = ref('')
const messageRef = ref(null)


const total = ref(0)

const index = ref(-1)
const time = ref("")
const role = ref("")
const type = ref('')
const gender = ref("")
const powers = ref("")
const malePowers = ref('')
const feMalePowers = ref('')

const totalTarget = ref(0)
const totalBackup =  ref(0)



const mockData = [
	{
	   role: '目标',
	   num: 0,
	   gender: '公',
	   power: ''
	},
	{
	   role: '目标',
		num: 0,
	   gender: '母',
	   power: ''
	},
	{
	   role: '备选',
		num: 0,
	   gender: '公',
	   power: ''
	},
	{
	   role: '备选',
		num: 0,
	   gender: '母',
	   power: ''
	}
]

const inputData = ref(mockData);
const outputData = ref([]);

const batchRef =  ref(null)

function editRow(_gender, _role, _index) {
	type.value = 'edit'
	gender.value = _gender
	role.value = _role
	index.value = _index
	const { power } = inputData.value[_index]
	powers.value = power
	batchRef.value.open()
}


function switchRoles(){
	outputData.value = []
	const [t1, t2, b1, b2] = inputData.value
	inputData.value[0] = { ...b1 }
	inputData.value[1] = { ...b2 }
	inputData.value[2] = { ...t1 }
	inputData.value[3] = { ...t2 }
}

const powerDifference = ref(0)

function isPositiveInteger(str) {
    return /^[1-9]\d*$/.test(str);
}

function generatePowers(_powers){
	_powers = _powers.replace(/，|、|,/g, ',')
	const powerSet = _powers.split(',').map(item => item.trim()).filter(item => item !== '')
	const isOk = powerSet.every(num => isPositiveInteger(num))
	if (!isOk && powerSet.length !== 0) return false
	inputData.value[index.value].num = powerSet.length; 
	inputData.value[index.value].power = powerSet.join(',')


	const [t1, t2] = inputData.value

	const t1ps = t1.power.split(',')
	const t2ps = t2.power.split(',')


}


function handleConfirm(){	
	messageRef.value.close()

	const isOk = generatePowers(powers.value, '公')
	if (typeof isOk === 'boolean' && !isOk){
		messageRef.value.close()
		messageRef.value.open()
		messageText.value = '势力必须为数字'
		return
	}


	batchRef.value.close()
}

// 生成数组的所有组合（辅助函数，用于生成指定个数元素的组合情况）
function getCombinations(arr, num) {
    const result = [];
	if (num === 0) { return [[]]; }

    for (let i = 0; i < arr.length; i++) {
        const element = arr[i];

        const remainingCombos = getCombinations(arr.slice(i + 1), num - 1);

		for (const combo of remainingCombos) {
            result.push([element].concat(combo));
        }
    }

    return result;
}


function calculateBestMatch() {
	let startTime = new Date().getTime()
	let endTime = null
			
	outputData.value = []

	const targetMale = inputData.value[0].power.split(',').filter(item => item !== '').map(Number)
	const targetFemale = inputData.value[1].power.split(',').filter(item => item !== '').map(Number)
	const backupMale = inputData.value[2].power.split(',').filter(item => item !== '').map(Number)
	const backupFemale = inputData.value[3].power.split(',').filter(item => item !== '').map(Number)

	if (targetFemale.length === 0 && targetFemale.length === 0) {
		messageRef.value.open()
		messageText.value = '目标公数据与母数据不能同时为空'
		return
	}

	if(targetFemale.length + targetFemale.length > 20){
		messageRef.value.open()
		messageText.value = '目标公数据与母数据的和不能超过20条'
		return
	}
	
	if(backupMale.length > 20){
		messageRef.value.open()
		messageText.value = '备选的公数据不能超过20条'
		return
	}
	
	if(backupFemale.length > 20){
		messageRef.value.open()
		messageText.value = '备选的母数据不能超过20条'
		return
	}
	

	if (targetFemale.length > backupMale.length && backupMale.length !== 0){
		messageRef.value.open()
		messageText.value = '备选的公数据长度必须大于或等于目标的母数据'
		return
	}

	if (targetMale.length > backupFemale.length && backupFemale.length !== 0) {
		messageRef.value.open()
		messageText.value = '备选的母数据长度必须或等于大于目标的公数据'
		return
	}

	const targetMaleLen = targetMale.length;
	const targetFemaleLen = targetFemale.length;


	let targetWeight = 0
	if (backupMale.length === 0){
		targetWeight =  targetMale.reduce((acc, val) => acc + val, 0);
	} else if(backupFemale.length === 0){
		targetWeight = targetFemale.reduce((acc, val) => acc + val, 0)
	} else if(backupMale.length !== 0 && backupFemale.length !== 0){
		targetWeight = targetMale.reduce((acc, val) => acc + val, 0) + targetFemale.reduce((acc, val) => acc + val, 0);
	}

	let minDifference = Infinity; 
    let bestfemaleCombination = null;
    let bestMaleCombination = null;
	const femaleCombinations = getCombinations(backupFemale, targetMaleLen);
	const maleCombinations = getCombinations(backupMale, targetFemaleLen);

	if (femaleCombinations.length !== 0 && maleCombinations.length !== 0){
		for (const femaleComb of femaleCombinations) {
			for (const maleComb of maleCombinations) {
				const totalWeight = femaleComb.reduce((acc, val) => acc + val, 0) + maleComb.reduce((acc, val) => acc + val, 0);
				const difference = Math.abs(totalWeight - targetWeight);
				if (difference < minDifference) {
					minDifference = difference;
					bestfemaleCombination = femaleComb;
					bestMaleCombination = maleComb;
					if (minDifference == 0) {
						break;
					}
				}
			}
		}
	}


	// 备选数据的母为空
	if (femaleCombinations.length === 0 && maleCombinations.length !== 0) {
		for (const maleComb of maleCombinations) {
			const totalWeight = maleComb.reduce((acc, val) => acc + val , 0);
			const difference = Math.abs(totalWeight - targetWeight);
			if (difference < minDifference) {
				minDifference = difference;
				bestMaleCombination = maleComb;
				if (minDifference == 0) {
					break;
				}
			}
		}
	}

	// 备选数据的公为空
	if (femaleCombinations.length !== 0 && maleCombinations.length === 0) {
		for (const femaleComb of femaleCombinations) {
				const totalWeight = femaleComb.reduce((acc, val) => acc + val, 0)
				const difference = Math.abs(totalWeight - targetWeight);
				if (difference < minDifference) {
					minDifference = difference;
					bestfemaleCombination = femaleComb;
					// bestMaleCombination = maleComb;
					if (minDifference == 0) {
						break;
					}
				}
		}
	}

	bestMaleCombination && bestMaleCombination.sort((a, b) => b - a)
	bestfemaleCombination && bestfemaleCombination.sort((a, b) => b - a)
	targetMale.sort((a, b) =>  b - a)
	targetFemale.sort((a, b) =>  b - a)

	if (!bestMaleCombination && !bestfemaleCombination){ return }


	bestfemaleCombination && targetMale.forEach((_, index) => {
		outputData.value.push({
			targetMale: targetMale[index],
			targetFemale: null,
			backupMale: null,
			backupFemale: bestfemaleCombination[index]
		})
	})
	
	
	const fl = targetFemale.length
	
	for(let index = 0; index < fl; index ++){
		if(outputData.value[index]){
			outputData.value[index].targetFemale = targetFemale[index]
			outputData.value[index].backupMale = bestMaleCombination[index]
		} else {
			outputData.value.push({
				targetMale: null,
				targetFemale: targetFemale[index],
				backupMale: bestMaleCombination[index],
				backupFemale: null
			})
			
		}
	}


	 totalTarget.value = outputData.value.reduce((prev, current) => prev + current.targetMale, 0) + outputData.value.reduce((prev, current) => prev + current.targetFemale, 0)
	 totalBackup.value = outputData.value.reduce((prev, current) => prev + current.backupMale, 0) + outputData.value.reduce((prev, current) => prev + current.backupFemale, 0)

	powerDifference.value = totalTarget.value - totalBackup.value
	endTime = new Date().getTime()
	time.value = endTime - startTime
}
</script>

<style>
.text-power {
	width: 120px;
	max-width: 120px;
	overflow: hidden;
	text-overflow: ellipsis;
	text-wrap: nowrap;
	/* white-space: pre-wrap; */
}

.edit-button {
	color: #409eff !important;
	cursor: pointer;
}

textarea {
	font-size: 13px;
	padding: 8px;
}
</style>

<style lang="scss" scoped>


button {
	height: 30px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 14px;
}


.dialog-title {
	line-height: 30px;
	padding-left: 10px;
	font-size: 14px;
}


.table-wrapper {
	font-size: 14px !important;
}


.custom-picker {
    border: 1px solid #e3e3e3;
    padding: 3px 5px;
    text-align: center;
	width: 100%;
	
    
    div {
        display: flex;
        justify-content: space-between;
        
        text {
            overflow: hidden;
            white-space: nowrap;
            text-overflow: ellipsis;
        }
    }
}

.container {
    padding: 10px 20px;
}

.section {
    margin-bottom: 20px;
}

.section-title {
    font-size: 18px;
    font-weight: bold;
    margin-bottom: 10px;
}

.input {
    width: 100%;
    text-align: center;
    border: 1px solid #ddd;
    padding: 5px;
}

button {
    margin: 5px;
}

.add-btn,
.calculate-btn {
    background-color: #007bff;
    color: white;
    padding: 10px;
    font-size: 16px;
    text-align: center;
    border-radius: 5px;
}

.delete-btn {
    background-color: #ff4d4f;
    color: white;
    padding: 5px;
    font-size: 14px;
    border-radius: 5px;
}

.summary {
    margin-top: 20px;
    font-size: 14px;
    text-align: right;
    font-weight: bold;
}
</style>
