<template>
	<div class="fee-overview">
		<div class="fee-overview__header">
			<h2>Beitragsübersicht</h2>
			<div class="fee-overview__actions">
				<!-- Year selector -->
				<div class="fee-overview__year-selector">
					<label for="fee-year">Jahr:</label>
					<select id="fee-year"
						:value="feesStore.selectedYear"
						class="fee-overview__select"
						@change="onYearChange($event.target.value)">
						<option v-for="year in feesStore.availableYears"
							:key="year"
							:value="year">
							{{ year }}
						</option>
					</select>
				</div>

				<ColumnPicker :columns="allColumns"
					:model-value="visibleKeys"
					@update:model-value="setVisibleKeys" />

				<!-- Batch calculate -->
				<NcButton type="primary"
					:disabled="feesStore.loading"
					@click="showBatchConfirm = true">
					Beiträge berechnen
				</NcButton>
			</div>
		</div>

		<!-- Error / Success messages -->
		<div v-if="feesStore.error" class="fee-overview__message fee-overview__message--error">
			{{ feesStore.error }}
			<NcButton @click="feesStore.clearError()">Schließen</NcButton>
		</div>
		<div v-if="feesStore.success" class="fee-overview__message fee-overview__message--success">
			{{ feesStore.success }}
			<NcButton @click="feesStore.clearSuccess()">Schließen</NcButton>
		</div>

		<!-- Batch calculation confirmation dialog -->
		<div v-if="showBatchConfirm" class="fee-overview__dialog-backdrop">
			<div class="fee-overview__dialog">
				<h3>Beiträge berechnen</h3>
				<p>
					Beiträge für das Jahr <strong>{{ feesStore.selectedYear }}</strong> berechnen?
				</p>
				<ul>
					<li>Neue Beitragspositionen werden erstellt</li>
					<li>Bestehende (nicht manuell angepasste) werden aktualisiert</li>
					<li>Manuell angepasste Positionen werden übersprungen</li>
				</ul>
				<div class="fee-overview__dialog-actions">
					<NcButton @click="showBatchConfirm = false">
						Abbrechen
					</NcButton>
					<NcButton type="primary"
						:disabled="feesStore.loading"
						@click="executeBatchCalculate">
						Berechnen
					</NcButton>
				</div>
			</div>
		</div>

		<!-- Summary bar -->
		<div v-if="feesStore.records.length > 0" class="fee-overview__summary">
			<div class="fee-overview__summary-item">
				<span class="fee-overview__summary-label">Gesamt erwartet</span>
				<span class="fee-overview__summary-value">{{ formatCurrency(feesStore.summary.totalExpected) }}</span>
			</div>
			<div class="fee-overview__summary-item fee-overview__summary-item--paid">
				<span class="fee-overview__summary-label">Bezahlt</span>
				<span class="fee-overview__summary-value">
					{{ formatCurrency(feesStore.summary.totalPaid) }}
					({{ feesStore.summary.countPaid }}/{{ feesStore.summary.total }})
				</span>
			</div>
			<div class="fee-overview__summary-item fee-overview__summary-item--outstanding">
				<span class="fee-overview__summary-label">Ausstehend</span>
				<span class="fee-overview__summary-value">{{ formatCurrency(feesStore.summary.totalOutstanding) }}</span>
			</div>
			<div v-if="feesStore.summary.countManual > 0" class="fee-overview__summary-item fee-overview__summary-item--manual">
				<span class="fee-overview__summary-label">Manuell angepasst</span>
				<span class="fee-overview__summary-value">{{ feesStore.summary.countManual }}</span>
			</div>
		</div>

		<!-- Loading -->
		<NcLoadingIcon v-if="feesStore.recordsLoading && feesStore.records.length === 0"
			:size="64"
			class="fee-overview__loading" />

		<!-- Empty state -->
		<NcEmptyContent v-else-if="!feesStore.recordsLoading && feesStore.records.length === 0"
			name="Keine Beitragspositionen"
			description="Für dieses Jahr wurden noch keine Beiträge berechnet.">
			<template #action>
				<NcButton type="primary" @click="showBatchConfirm = true">
					Beiträge jetzt berechnen
				</NcButton>
			</template>
		</NcEmptyContent>

		<!-- Fee records table -->
		<table v-else class="fee-overview__table">
			<thead>
				<tr>
					<th v-for="col in visibleColumns" :key="col.key"
						class="fee-overview__th"
						:class="{ 'fee-overview__th--sortable': col.sortable }"
						@click="col.sortable && toggleSort(col.sortField || col.key)">
						{{ col.label }}
						<SortIcon v-if="col.sortable"
							:field="col.sortField || col.key"
							:current-sort="sortField"
							:sort-asc="sortAsc" />
					</th>
				</tr>
			</thead>
			<tbody>
				<tr v-for="record in paginatedItems"
					:key="record.id"
					:class="{ 'fee-overview__row--manual': record.manuellAngepasst }">
					<td v-for="col in visibleColumns" :key="col.key"
						class="fee-overview__td"
						:class="{
							'fee-overview__td--amount': col.key === 'amount',
							'fee-overview__td--notes': col.key === 'notes',
							'fee-overview__td--actions': col.key === 'aktionen',
						}">
						<!-- Mitglied column with link -->
						<template v-if="col.key === 'mitglied'">
							<router-link :to="{ name: 'member-detail', params: { id: record.memberId } }"
								class="fee-overview__member-link">
								{{ col.render(record) }}
							</router-link>
						</template>
						<!-- Amount with inline editing -->
						<template v-else-if="col.key === 'amount'">
							<template v-if="editingRecord === record.id">
								<input v-model="editAmount"
									type="number" min="0" step="0.01"
									class="fee-overview__inline-input"
									@keyup.enter="saveOverride(record.id)"
									@keyup.escape="cancelEdit">
							</template>
							<template v-else>{{ col.render(record) }}</template>
						</template>
						<!-- Bezahlt badge -->
						<template v-else-if="col.key === 'paid'">
							<span :class="record.paid ? 'fee-overview__badge--paid' : 'fee-overview__badge--unpaid'"
								class="fee-overview__badge">
								{{ col.render(record) }}
							</span>
						</template>
						<!-- Manuell badge -->
						<template v-else-if="col.key === 'manuell'">
							<span v-if="record.manuellAngepasst" class="fee-overview__badge fee-overview__badge--manual">
								Manuell
							</span>
						</template>
						<!-- Notes with inline editing -->
						<template v-else-if="col.key === 'notes'">
							<template v-if="editingNotes === record.id">
								<input v-model="editNotesText"
									type="text"
									class="fee-overview__inline-input"
									placeholder="Notiz..."
									@keyup.enter="saveNotes(record.id)"
									@keyup.escape="cancelNotesEdit">
							</template>
							<template v-else>{{ col.render(record) }}</template>
						</template>
						<!-- Actions -->
						<template v-else-if="col.key === 'aktionen'">
							<template v-if="editingRecord === record.id">
								<NcButton type="primary" @click="saveOverride(record.id)">Speichern</NcButton>
								<NcButton @click="cancelEdit">Abbrechen</NcButton>
							</template>
							<template v-else>
								<NcButton v-if="!record.paid" type="success" @click="markPaid(record.id)">Bezahlt</NcButton>
								<NcButton @click="startEdit(record)">Betrag ändern</NcButton>
								<NcButton v-if="!editingNotes || editingNotes !== record.id" @click="startNotesEdit(record)">Notiz</NcButton>
								<template v-if="editingNotes === record.id">
									<NcButton type="primary" @click="saveNotes(record.id)">Speichern</NcButton>
									<NcButton @click="cancelNotesEdit">Abbrechen</NcButton>
								</template>
							</template>
						</template>
						<!-- Default -->
						<template v-else>{{ col.render(record) }}</template>
					</td>
				</tr>
			</tbody>
		</table>

		<!-- Pagination -->
		<PaginationControls
			:current-page="currentPage"
			:total-items="totalItems"
			:page-size="pageSize"
			item-label="Positionen"
			@page="goToPage"
			@update:page-size="onPageSizeChange" />
	</div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'
import { NcButton, NcLoadingIcon, NcEmptyContent } from '@nextcloud/vue'
import { useFeesStore } from '../stores/fees.js'
import { useMembersStore } from '../stores/members.js'
import { useColumnVisibility } from '../utils/useColumnVisibility.js'
import { usePageSize } from '../utils/usePageSize.js'
import { useClientPagination } from '../utils/useClientPagination.js'
import ColumnPicker from '../components/ColumnPicker.vue'
import PaginationControls from '../components/PaginationControls.vue'
import SortIcon from '../components/SortIcon.vue'
import { formatDate } from '../utils/dateFormat.js'

const feesStore = useFeesStore()
const membersStore = useMembersStore()
const { pageSize, setPageSize } = usePageSize('mv_fee_pagesize')

const sortField = ref('_memberName')
const sortAsc = ref(true)

const memberNameMap = computed(() => {
	const map = {}
	for (const m of membersStore.members) {
		map[m.id] = `${m.nachname}, ${m.vorname}`
	}
	return map
})

function getMemberName(memberId) {
	return memberNameMap.value[memberId] || `Mitglied #${memberId}`
}

function formatCurrency(value) {
	if (value === null || value === undefined || isNaN(value)) return '--'
	return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(value)
}

const allColumns = [
	{ key: 'mitglied', label: 'Mitglied', sortable: true, sortField: '_memberName', alwaysVisible: true, render: r => getMemberName(r.memberId) },
	{ key: 'amount', label: 'Betrag', sortable: true, sortField: '_amount', render: r => formatCurrency(parseFloat(r.amount)) },
	{ key: 'paid', label: 'Bezahlt', sortable: true, sortField: 'paid', render: r => r.paid ? 'Ja' : 'Nein' },
	{ key: 'paymentDate', label: 'Zahlungsdatum', sortable: true, sortField: 'paymentDate', render: r => formatDate(r.paymentDate) },
	{ key: 'manuell', label: 'Manuell', render: r => r.manuellAngepasst ? 'Ja' : '' },
	{ key: 'notes', label: 'Notizen', render: r => r.notes || '--' },
	{ key: 'aktionen', label: 'Aktionen', render: () => '' },
]

const { visibleKeys, visibleColumns, setVisibleKeys } = useColumnVisibility(
	'mv_fee_columns',
	allColumns,
	['mitglied', 'amount', 'paid', 'paymentDate', 'manuell', 'notes', 'aktionen'],
)

const sortedRecords = computed(() => {
	const records = [...feesStore.records]
	const field = sortField.value
	const asc = sortAsc.value

	return records.sort((a, b) => {
		let valA, valB
		if (field === '_memberName') {
			valA = getMemberName(a.memberId).toLowerCase()
			valB = getMemberName(b.memberId).toLowerCase()
		} else if (field === '_amount') {
			valA = parseFloat(a.amount) || 0
			valB = parseFloat(b.amount) || 0
		} else {
			valA = a[field] ?? ''
			valB = b[field] ?? ''
			if (typeof valA === 'string') {
				valA = valA.toLowerCase()
				valB = String(valB).toLowerCase()
			}
		}

		if (valA < valB) return asc ? -1 : 1
		if (valA > valB) return asc ? 1 : -1
		return 0
	})
})

const { currentPage, totalItems, paginatedItems, goToPage, resetPage } = useClientPagination(sortedRecords, pageSize)

function onPageSizeChange(size) {
	setPageSize(size)
	resetPage()
}

function toggleSort(field) {
	if (sortField.value === field) {
		sortAsc.value = !sortAsc.value
	} else {
		sortField.value = field
		sortAsc.value = true
	}
}

const showBatchConfirm = ref(false)
const editingRecord = ref(null)
const editAmount = ref('')
const editingNotes = ref(null)
const editNotesText = ref('')

onMounted(async () => {
	const savedLimit = membersStore.limit
	membersStore.limit = 9999
	await Promise.all([
		feesStore.fetchRules(),
		feesStore.fetchRecords(),
		membersStore.fetchMembers(0),
	])
	membersStore.limit = savedLimit
})

function onYearChange(year) {
	feesStore.fetchRecords(parseInt(year))
}

async function executeBatchCalculate() {
	try { await feesStore.batchCalculate(feesStore.selectedYear) } catch { /* store shows error */ }
	showBatchConfirm.value = false
}

async function markPaid(recordId) {
	const today = new Date().toISOString().split('T')[0]
	try { await feesStore.markAsPaid(recordId, today) } catch { /* store shows error */ }
}

function startEdit(record) {
	editingRecord.value = record.id
	editAmount.value = record.amount || ''
	editingNotes.value = null
}

function cancelEdit() {
	editingRecord.value = null
	editAmount.value = ''
}

async function saveOverride(recordId) {
	if (!editAmount.value || parseFloat(editAmount.value) < 0) return
	try { await feesStore.manualOverride(recordId, String(editAmount.value), null) } catch { /* store shows error */ }
	editingRecord.value = null
	editAmount.value = ''
}

function startNotesEdit(record) {
	editingNotes.value = record.id
	editNotesText.value = record.notes || ''
	editingRecord.value = null
}

function cancelNotesEdit() {
	editingNotes.value = null
	editNotesText.value = ''
}

async function saveNotes(recordId) {
	try {
		const record = feesStore.records.find(r => r.id === recordId)
		const amount = record ? record.amount : '0'
		await feesStore.manualOverride(recordId, amount, editNotesText.value)
	} catch { /* store shows error */ }
	editingNotes.value = null
	editNotesText.value = ''
}
</script>

<style scoped>
.fee-overview { padding: 20px; }
.fee-overview__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 12px; }
.fee-overview__header h2 { margin: 0; }
.fee-overview__actions { display: flex; gap: 12px; align-items: center; }
.fee-overview__year-selector { display: flex; align-items: center; gap: 6px; }
.fee-overview__year-selector label { font-weight: 500; }
.fee-overview__select { padding: 6px 8px; border: 1px solid var(--color-border); border-radius: var(--border-radius); background: var(--color-main-background); color: var(--color-text); }
.fee-overview__message { display: flex; align-items: center; gap: 12px; padding: 8px 12px; border-radius: var(--border-radius); margin-bottom: 12px; color: white; }
.fee-overview__message--error { background: var(--color-error); }
.fee-overview__message--success { background: var(--color-success); }
.fee-overview__dialog-backdrop { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: flex; align-items: center; justify-content: center; z-index: 1000; }
.fee-overview__dialog { background: var(--color-main-background); padding: 24px; border-radius: var(--border-radius-large); max-width: 480px; width: 90%; box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2); }
.fee-overview__dialog h3 { margin: 0 0 12px 0; }
.fee-overview__dialog ul { margin: 8px 0 16px 0; padding-left: 20px; }
.fee-overview__dialog li { margin-bottom: 4px; color: var(--color-text-lighter); }
.fee-overview__dialog-actions { display: flex; gap: 8px; justify-content: flex-end; }
.fee-overview__summary { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 20px; padding: 12px 16px; background: var(--color-background-dark); border-radius: var(--border-radius); }
.fee-overview__summary-item { display: flex; flex-direction: column; gap: 2px; }
.fee-overview__summary-label { font-size: 0.8em; color: var(--color-text-lighter); font-weight: 500; }
.fee-overview__summary-value { font-size: 1.1em; font-weight: 600; }
.fee-overview__summary-item--paid .fee-overview__summary-value { color: var(--color-success); }
.fee-overview__summary-item--outstanding .fee-overview__summary-value { color: var(--color-warning); }
.fee-overview__summary-item--manual .fee-overview__summary-value { color: var(--color-primary); }
.fee-overview__loading { display: flex; justify-content: center; margin-top: 60px; }
.fee-overview__table { width: 100%; border-collapse: collapse; }
.fee-overview__th { text-align: left; padding: 12px 12px; border-bottom: 2px solid var(--color-border-dark); font-weight: bold; white-space: nowrap; font-size: 0.9em; }
.fee-overview__th--sortable { cursor: pointer; user-select: none; }
.fee-overview__th--sortable:hover { background-color: var(--color-background-hover); }
.fee-overview__td { padding: 10px 12px; border-bottom: 1px solid var(--color-border); vertical-align: middle; }
.fee-overview__td--amount { font-variant-numeric: tabular-nums; }
.fee-overview__td--notes { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fee-overview__td--actions { white-space: normal; }
.fee-overview__td--actions :deep(.button-vue) { display: inline-flex; margin: 2px; }
.fee-overview__row--manual { background: var(--color-primary-element-light); }
.fee-overview__member-link { color: var(--color-primary); text-decoration: none; font-weight: 500; }
.fee-overview__member-link:hover { text-decoration: underline; }
.fee-overview__badge { display: inline-block; padding: 2px 8px; border-radius: var(--border-radius-pill); font-size: 0.85em; font-weight: 500; }
.fee-overview__badge--paid { background-color: var(--color-success); color: white; }
.fee-overview__badge--unpaid { background-color: var(--color-warning); color: white; }
.fee-overview__badge--manual { background-color: var(--color-primary); color: white; }
.fee-overview__inline-input { padding: 4px 6px; border: 1px solid var(--color-primary); border-radius: var(--border-radius); background: var(--color-main-background); color: var(--color-text); width: 100px; }
</style>
