<template>
	<div class="conflict-resolver">
		<div class="conflict-resolver__header">
			<h4>Konflikt {{ currentIndex + 1 }} von {{ conflicts.length }}</h4>
			<div class="conflict-resolver__nav-btns">
				<NcButton :disabled="currentIndex === 0" @click="currentIndex--">
					Vorheriger
				</NcButton>
				<NcButton :disabled="currentIndex >= conflicts.length - 1" @click="currentIndex++">
					Naechster
				</NcButton>
			</div>
		</div>

		<!-- Progress bar -->
		<div class="conflict-resolver__progress">
			<div class="conflict-resolver__progress-bar"
				:style="{ width: resolvedPercent + '%' }">
			</div>
			<span class="conflict-resolver__progress-text">
				{{ resolvedCount }} / {{ totalFieldConflicts }} Felder geloest
			</span>
		</div>

		<!-- Bulk actions -->
		<div class="conflict-resolver__bulk">
			<NcButton type="tertiary" @click="bulkKeepExisting">
				Alle bestehenden Werte behalten
			</NcButton>
			<NcButton type="tertiary" @click="bulkKeepImported">
				Alle importierten Werte uebernehmen
			</NcButton>
		</div>

		<!-- Field comparison table -->
		<div v-if="currentConflict" class="conflict-resolver__table-scroll">
			<table class="conflict-resolver__table">
				<thead>
					<tr>
						<th>Feld</th>
						<th>Bestehend (Datenbank)</th>
						<th>Importiert (CSV)</th>
						<th>Auswahl</th>
					</tr>
				</thead>
				<tbody>
					<tr v-for="field in currentFields" :key="field.key"
						:class="{
							'conflict-resolver__row--identical': field.identical,
							'conflict-resolver__row--auto': field.autoSelected,
							'conflict-resolver__row--changed': !field.identical && isFieldResolved(field.key),
						}">
						<td class="conflict-resolver__field-name">{{ field.label }}</td>
						<td class="conflict-resolver__value conflict-resolver__value--existing"
							:class="{ 'conflict-resolver__value--selected': getResolution(field.key) === 'existing' }">
							{{ field.existingValue || '(leer)' }}
						</td>
						<td class="conflict-resolver__value conflict-resolver__value--imported"
							:class="{ 'conflict-resolver__value--selected': getResolution(field.key) === 'imported' }">
							{{ field.importedValue || '(leer)' }}
						</td>
						<td class="conflict-resolver__action">
							<template v-if="field.identical">
								<span class="conflict-resolver__identical">identisch</span>
							</template>
							<template v-else>
								<label class="conflict-resolver__radio">
									<input type="radio"
										:name="'conflict-' + currentIndex + '-' + field.key"
										:checked="getResolution(field.key) === 'existing'"
										@change="setResolution(field.key, 'existing')">
									Behalten
								</label>
								<label class="conflict-resolver__radio">
									<input type="radio"
										:name="'conflict-' + currentIndex + '-' + field.key"
										:checked="getResolution(field.key) === 'imported'"
										@change="setResolution(field.key, 'imported')">
									Importieren
								</label>
							</template>
						</td>
					</tr>
				</tbody>
			</table>
		</div>
	</div>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import { NcButton } from '@nextcloud/vue'

const props = defineProps({
	/** @type {Array} Duplicate records with _existingData and imported fields */
	conflicts: { type: Array, required: true },
	/** @type {Array} Field definitions for the entity type */
	fieldDefs: { type: Array, required: true },
})

const emit = defineEmits(['update:resolutions'])

const currentIndex = ref(0)

// resolutions[conflictIdx][fieldKey] = 'existing' | 'imported'
const resolutions = ref({})

// Initialize resolutions for all conflicts
watch(() => props.conflicts, (newConflicts) => {
	const r = {}
	newConflicts.forEach((conflict, cIdx) => {
		r[cIdx] = {}
		const existing = conflict._existingData || {}
		const imported = conflict

		for (const field of props.fieldDefs) {
			if (field.key === 'id') continue
			const existVal = String(existing[field.key] ?? existing[toCamelCase(field.key)] ?? '')
			const importVal = String(imported[field.key] ?? '')

			if (existVal === importVal) {
				r[cIdx][field.key] = 'existing' // identical, default to existing
			} else if (!existVal && importVal) {
				// Auto-select imported when existing is empty
				r[cIdx][field.key] = 'imported'
			} else {
				r[cIdx][field.key] = '' // unresolved
			}
		}
	})
	resolutions.value = r
	emitResolutions()
}, { immediate: true })

const currentConflict = computed(() => props.conflicts[currentIndex.value])

const currentFields = computed(() => {
	if (!currentConflict.value) return []
	const existing = currentConflict.value._existingData || {}
	const imported = currentConflict.value

	return props.fieldDefs
		.filter(f => f.key !== 'id')
		.map(f => {
			const existVal = String(existing[f.key] ?? existing[toCamelCase(f.key)] ?? '')
			const importVal = String(imported[f.key] ?? '')
			const identical = existVal === importVal
			const autoSelected = !existVal && !!importVal

			return {
				key: f.key,
				label: f.label,
				existingValue: existVal,
				importedValue: importVal,
				identical,
				autoSelected,
			}
		})
})

const totalFieldConflicts = computed(() => {
	let total = 0
	for (const cIdx of Object.keys(resolutions.value)) {
		for (const field of Object.values(resolutions.value[cIdx])) {
			if (field !== '') total++ // Count resolved fields (including identical)
		}
	}
	return Object.keys(resolutions.value).length > 0
		? Object.values(resolutions.value).reduce((sum, fields) => {
			return sum + Object.values(fields).filter(v => v !== 'existing' || !isIdenticalField(parseInt(Object.keys(resolutions.value).find(k => resolutions.value[k] === fields)), '')).length
		}, 0)
		: 0
})

const resolvedCount = computed(() => {
	let resolved = 0
	for (const fields of Object.values(resolutions.value)) {
		for (const val of Object.values(fields)) {
			if (val !== '') resolved++
		}
	}
	return resolved
})

const resolvedPercent = computed(() => {
	const total = resolvedCount.value
	let allFields = 0
	for (const fields of Object.values(resolutions.value)) {
		allFields += Object.keys(fields).length
	}
	return allFields > 0 ? Math.round((total / allFields) * 100) : 0
})

function getResolution(fieldKey) {
	return resolutions.value[currentIndex.value]?.[fieldKey] || ''
}

function setResolution(fieldKey, value) {
	if (!resolutions.value[currentIndex.value]) {
		resolutions.value[currentIndex.value] = {}
	}
	resolutions.value[currentIndex.value][fieldKey] = value
	emitResolutions()
}

function isFieldResolved(fieldKey) {
	return getResolution(fieldKey) !== ''
}

function bulkKeepExisting() {
	for (const cIdx of Object.keys(resolutions.value)) {
		for (const fKey of Object.keys(resolutions.value[cIdx])) {
			if (resolutions.value[cIdx][fKey] === '') {
				resolutions.value[cIdx][fKey] = 'existing'
			}
		}
	}
	emitResolutions()
}

function bulkKeepImported() {
	for (const cIdx of Object.keys(resolutions.value)) {
		for (const fKey of Object.keys(resolutions.value[cIdx])) {
			if (resolutions.value[cIdx][fKey] === '') {
				resolutions.value[cIdx][fKey] = 'imported'
			}
		}
	}
	emitResolutions()
}

function emitResolutions() {
	// Build resolved conflicts array for the backend
	const result = props.conflicts.map((conflict, cIdx) => {
		const fieldResolutions = resolutions.value[cIdx] || {}
		const existing = conflict._existingData || {}
		const imported = conflict
		const mergedFields = {}

		for (const [fieldKey, choice] of Object.entries(fieldResolutions)) {
			if (choice === 'imported') {
				mergedFields[fieldKey] = imported[fieldKey] ?? ''
			}
			// 'existing' means keep DB value, no change needed
		}

		return {
			existingId: conflict._existingId,
			mergedFields,
			hasUnresolved: Object.values(fieldResolutions).some(v => v === ''),
		}
	})

	emit('update:resolutions', result)
}

/**
 * Convert snake_case to camelCase for matching entity jsonSerialize keys.
 */
function toCamelCase(str) {
	return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase())
}
</script>

<style scoped>
.conflict-resolver {
	margin-bottom: 20px;
}

.conflict-resolver__header {
	display: flex;
	justify-content: space-between;
	align-items: center;
	margin-bottom: 12px;
}

.conflict-resolver__header h4 {
	margin: 0;
}

.conflict-resolver__nav-btns {
	display: flex;
	gap: 8px;
}

.conflict-resolver__progress {
	position: relative;
	height: 24px;
	background: var(--color-background-dark);
	border-radius: var(--border-radius-pill);
	margin-bottom: 12px;
	overflow: hidden;
}

.conflict-resolver__progress-bar {
	height: 100%;
	background: var(--color-primary);
	transition: width 0.3s;
	border-radius: var(--border-radius-pill);
}

.conflict-resolver__progress-text {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	font-size: 0.8em;
	font-weight: 500;
}

.conflict-resolver__bulk {
	display: flex;
	gap: 8px;
	margin-bottom: 16px;
}

.conflict-resolver__table-scroll {
	overflow-x: auto;
}

.conflict-resolver__table {
	width: 100%;
	border-collapse: collapse;
	font-size: 0.9em;
}

.conflict-resolver__table th {
	text-align: left;
	padding: 8px 10px;
	font-weight: 600;
	font-size: 0.85em;
	border-bottom: 2px solid var(--color-border);
	white-space: nowrap;
}

.conflict-resolver__table td {
	padding: 8px 10px;
	border-bottom: 1px solid var(--color-border);
}

.conflict-resolver__field-name {
	font-weight: 500;
	white-space: nowrap;
}

.conflict-resolver__value {
	max-width: 200px;
	overflow: hidden;
	text-overflow: ellipsis;
}

.conflict-resolver__value--selected {
	background: var(--color-primary-element-light);
	font-weight: 500;
}

.conflict-resolver__action {
	display: flex;
	gap: 12px;
	white-space: nowrap;
}

.conflict-resolver__radio {
	display: flex;
	align-items: center;
	gap: 4px;
	cursor: pointer;
	font-size: 0.9em;
}

.conflict-resolver__identical {
	color: var(--color-text-lighter);
	font-style: italic;
}

.conflict-resolver__row--identical {
	opacity: 0.6;
}

.conflict-resolver__row--auto td:nth-child(3) {
	background: #f0fdf4;
}

.conflict-resolver__row--changed {
	background: var(--color-primary-element-light);
}
</style>
