/**
 * Pinia store for fee rules and records state management.
 *
 * Handles fetching, creating, and listing fee rules and records
 * against the /api/v1/fees REST API.
 *
 * Part of Issues #43 and #44.
 */
import { defineStore } from 'pinia'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'

export const useFeesStore = defineStore('fees', {
	state: () => ({
		/** @type {Array} List of fee rules, newest first */
		rules: [],
		/** @type {Array} Fee records for the selected year */
		records: [],
		/** @type {number} Currently selected year */
		selectedYear: new Date().getFullYear(),
		/** @type {boolean} Loading state */
		loading: false,
		/** @type {boolean} Records loading state */
		recordsLoading: false,
		/** @type {string|null} Error message */
		error: null,
		/** @type {string|null} Success message */
		success: null,
	}),

	getters: {
		/**
		 * Get the most recent (current) rule.
		 */
		currentRule: (state) => {
			if (state.rules.length === 0) return null
			return state.rules[0]
		},

		/**
		 * Summary statistics for the current year's records.
		 */
		summary: (state) => {
			const total = state.records.length
			let totalExpected = 0
			let totalPaid = 0
			let countPaid = 0
			let countManual = 0

			for (const record of state.records) {
				const amount = parseFloat(record.amount) || 0
				totalExpected += amount
				if (record.paid) {
					totalPaid += amount
					countPaid++
				}
				if (record.manuellAngepasst) {
					countManual++
				}
			}

			return {
				total,
				totalExpected,
				totalPaid,
				totalOutstanding: totalExpected - totalPaid,
				countPaid,
				countManual,
			}
		},

		/**
		 * Available years for selection (from rules).
		 */
		availableYears: (state) => {
			const currentYear = new Date().getFullYear()
			const years = new Set()

			// Add years from rules
			for (const rule of state.rules) {
				years.add(rule.yearFrom)
			}

			// Always include current and previous year
			years.add(currentYear)
			years.add(currentYear - 1)

			return [...years].sort((a, b) => b - a)
		},
	},

	actions: {
		/**
		 * Fetch all fee rules.
		 */
		async fetchRules() {
			this.loading = true
			this.error = null

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/fees/rules')
				const response = await axios.get(url)
				this.rules = response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Laden der Beitragsregeln'
				console.error('Failed to fetch fee rules:', err)
			} finally {
				this.loading = false
			}
		},

		/**
		 * Create a new fee rule.
		 * Rules are versioned -- creating a new one does not edit existing ones.
		 *
		 * @param {object} data - Rule data
		 * @param {number} data.yearFrom - Year the rule takes effect
		 * @param {string} data.baseRate - Base rate as decimal string
		 * @param {object} data.familyRules - Family rules object
		 */
		async createRule(data) {
			this.loading = true
			this.error = null
			this.success = null

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/fees/rules')
				const payload = {
					yearFrom: data.yearFrom,
					baseRate: data.baseRate,
					familyRules: data.familyRules,
				}
				const response = await axios.post(url, payload)

				// Add to beginning of list (newest first)
				this.rules.unshift(response.data)
				this.success = 'Beitragsregel erfolgreich gespeichert'
				return response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Erstellen der Beitragsregel'
				throw err
			} finally {
				this.loading = false
			}
		},

		// ── Fee records ─────────────────────────────────────────────

		/**
		 * Fetch fee records for the selected year.
		 */
		async fetchRecords(year) {
			if (year !== undefined) {
				this.selectedYear = year
			}

			this.recordsLoading = true
			this.error = null

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/fees/records')
				const response = await axios.get(url, {
					params: { year: this.selectedYear },
				})
				this.records = response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Laden der Beitragspositionen'
				console.error('Failed to fetch fee records:', err)
			} finally {
				this.recordsLoading = false
			}
		},

		/**
		 * Trigger batch calculation for a year.
		 *
		 * @returns {object} Result with created/updated/skipped counts
		 */
		async batchCalculate(year) {
			this.loading = true
			this.error = null
			this.success = null

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/fees/batch-calculate')
				const response = await axios.post(url, { year })

				this.success = `Berechnung abgeschlossen: ${response.data.created} erstellt, `
					+ `${response.data.updated} aktualisiert, ${response.data.skipped} übersprungen`

				// Refresh records after batch
				await this.fetchRecords(year)
				return response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler bei der Beitragsberechnung'
				throw err
			} finally {
				this.loading = false
			}
		},

		/**
		 * Mark a fee record as paid.
		 *
		 * @param {number} recordId - The record ID
		 * @param {string} paymentDate - ISO date string
		 */
		async markAsPaid(recordId, paymentDate) {
			this.error = null

			try {
				const url = generateUrl(`/apps/mitgliederverwaltung/api/v1/fees/records/${recordId}/paid`)
				const response = await axios.put(url, { paymentDate })

				// Update local record
				const index = this.records.findIndex(r => r.id === recordId)
				if (index !== -1) {
					this.records[index] = response.data
				}
				return response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Markieren als bezahlt'
				throw err
			}
		},

		/**
		 * Manual override of a fee record amount.
		 *
		 * @param {number} recordId - The record ID
		 * @param {string} amount - New amount
		 * @param {string|null} notes - Optional notes
		 */
		async manualOverride(recordId, amount, notes) {
			this.error = null

			try {
				const url = generateUrl(`/apps/mitgliederverwaltung/api/v1/fees/records/${recordId}/override`)
				const response = await axios.put(url, { amount, notes })

				// Update local record
				const index = this.records.findIndex(r => r.id === recordId)
				if (index !== -1) {
					this.records[index] = response.data
				}
				return response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim manuellen Anpassen'
				throw err
			}
		},

		clearError() {
			this.error = null
		},

		clearSuccess() {
			this.success = null
		},
	},
})
