/**
 * Pinia store for member state management.
 *
 * Handles fetching, caching, and CRUD operations against the
 * /api/v1/members REST API.
 */
import { defineStore } from 'pinia'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'

export const useMembersStore = defineStore('members', {
	state: () => ({
		/** @type {Array} List of members */
		members: [],
		/** @type {Object|null} Currently selected member */
		currentMember: null,
		/** @type {number} Total member count */
		total: 0,
		/** @type {boolean} Loading state */
		loading: false,
		/** @type {string|null} Error message */
		error: null,
		/** @type {number} Current page (0-indexed offset) */
		offset: 0,
		/** @type {number} Items per page */
		limit: 20,
		/** @type {Object} Active filters (additive, combined with AND) */
		activeFilters: {
			status: null,
			rolle: null,
			birthdayThisMonth: false,
			unpaidFees: false,
		},
	}),

	getters: {
		/**
		 * Check if there are more pages to load.
		 */
		hasMore: (state) => state.offset + state.limit < state.total,

		/**
		 * Current page number (1-indexed).
		 */
		currentPage: (state) => Math.floor(state.offset / state.limit) + 1,

		/**
		 * Total number of pages.
		 */
		totalPages: (state) => Math.ceil(state.total / state.limit),
	},

	actions: {
		/**
		 * Fetch members with pagination.
		 */
		async fetchMembers(offset = 0) {
			this.loading = true
			this.error = null
			this.offset = offset

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/members')
				const response = await axios.get(url, {
					params: {
						limit: this.limit,
						offset: this.offset,
					},
				})

				this.members = response.data.data
				this.total = response.data.total
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Laden der Mitglieder'
				console.error('Failed to fetch members:', err)
			} finally {
				this.loading = false
			}
		},

		/**
		 * Fetch a single member by ID with all sub-entities.
		 */
		async fetchMember(id) {
			this.loading = true
			this.error = null

			try {
				const url = generateUrl(`/apps/mitgliederverwaltung/api/v1/members/${id}`)
				const response = await axios.get(url)
				this.currentMember = response.data
				return response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Laden des Mitglieds'
				console.error('Failed to fetch member:', err)
				throw err
			} finally {
				this.loading = false
			}
		},

		/**
		 * Fetch members with combinable additive filters.
		 *
		 * @param {{ status: string|null, rolle: string|null, birthdayThisMonth: boolean, unpaidFees: boolean }} filters
		 */
		async fetchWithFilters(filters) {
			this.loading = true
			this.error = null
			this.activeFilters = { ...filters }

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/members')
				const params = {}

				const hasAny = filters.status || filters.rolle || filters.birthdayThisMonth || filters.unpaidFees

				if (hasAny) {
					if (filters.status) params.status = filters.status
					if (filters.rolle) params.rolle = filters.rolle
					if (filters.birthdayThisMonth) params.birthday_this_month = '1'
					if (filters.unpaidFees) params.unpaid_fees = '1'
				} else {
					params.limit = this.limit
					params.offset = 0
				}

				const response = await axios.get(url, { params })
				this.members = response.data.data
				this.total = response.data.total
				this.offset = 0
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Filtern der Mitglieder'
				console.error('Failed to fetch with filter:', err)
			} finally {
				this.loading = false
			}
		},

		/**
		 * Search members by name.
		 */
		async searchMembers(query) {
			this.loading = true
			this.error = null

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/members')
				const response = await axios.get(url, {
					params: { search: query },
				})

				this.members = response.data.data
				this.total = response.data.total
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler bei der Suche'
				console.error('Failed to search members:', err)
			} finally {
				this.loading = false
			}
		},

		/**
		 * Create a new member.
		 */
		async createMember(data) {
			this.loading = true
			this.error = null

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/members')
				const response = await axios.post(url, data)
				return response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Erstellen des Mitglieds'
				throw err
			} finally {
				this.loading = false
			}
		},

		/**
		 * Update an existing member.
		 */
		async updateMember(id, data) {
			this.loading = true
			this.error = null

			try {
				const url = generateUrl(`/apps/mitgliederverwaltung/api/v1/members/${id}`)
				const response = await axios.put(url, data)
				this.currentMember = response.data
				return response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Aktualisieren des Mitglieds'
				throw err
			} finally {
				this.loading = false
			}
		},

		/**
		 * Soft-delete a member.
		 */
		async deleteMember(id) {
			this.loading = true
			this.error = null

			try {
				const url = generateUrl(`/apps/mitgliederverwaltung/api/v1/members/${id}`)
				await axios.delete(url)

				// Remove from local list
				this.members = this.members.filter(m => m.id !== id)
				this.total = Math.max(0, this.total - 1)

				if (this.currentMember?.id === id) {
					this.currentMember = null
				}
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Löschen des Mitglieds'
				throw err
			} finally {
				this.loading = false
			}
		},

		/**
		 * Navigate to a specific page.
		 */
		async goToPage(page) {
			const newOffset = (page - 1) * this.limit
			await this.fetchMembers(newOffset)
		},

		/**
		 * Change page size and reload from page 1.
		 */
		async setLimit(newLimit) {
			this.limit = newLimit
			await this.fetchMembers(0)
		},

		/**
		 * Clear the current error.
		 */
		clearError() {
			this.error = null
		},
	},
})
