/**
 * Pinia store for report generation state management.
 *
 * Handles fetching report types, previewing data, and downloading
 * PDF/CSV/encrypted exports via the /api/v1/reports REST API.
 *
 * Part of Issue #49.
 */
import { defineStore } from 'pinia'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'

export const useReportsStore = defineStore('reports', {
	state: () => ({
		/** @type {Array} Available report types */
		reportTypes: [],
		/** @type {string|null} Currently selected report type */
		selectedType: null,
		/** @type {object} Current filter parameters */
		filters: {},
		/** @type {object|null} Preview data {title, headers, rows} */
		previewData: null,
		/** @type {boolean} Loading state for report types */
		loading: false,
		/** @type {boolean} Loading state for preview */
		previewLoading: false,
		/** @type {boolean} Loading state for download */
		downloadLoading: false,
		/** @type {string|null} Error message */
		error: null,
		/** @type {string|null} Success message */
		success: null,
	}),

	getters: {
		/**
		 * Get the currently selected report type definition.
		 */
		currentReport: (state) => {
			if (!state.selectedType) return null
			return state.reportTypes.find(r => r.id === state.selectedType) || null
		},

		/**
		 * Whether the current report is a sensitive one (needs encryption).
		 */
		isSensitive: (state) => {
			if (!state.selectedType) return false
			const report = state.reportTypes.find(r => r.id === state.selectedType)
			return report?.sensitive || false
		},
	},

	actions: {
		/**
		 * Fetch available report types from the API.
		 */
		async fetchReportTypes() {
			this.loading = true
			this.error = null

			try {
				const url = generateUrl('/apps/mitgliederverwaltung/api/v1/reports')
				const response = await axios.get(url)
				this.reportTypes = response.data.reports || []
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Laden der Berichtstypen'
				console.error('Failed to fetch report types:', err)
			} finally {
				this.loading = false
			}
		},

		/**
		 * Select a report type and reset filters/preview.
		 *
		 * @param {string} typeId - Report type identifier
		 */
		selectType(typeId) {
			this.selectedType = typeId
			this.filters = {}
			this.previewData = null
			this.error = null
			this.success = null
		},

		/**
		 * Update a filter parameter.
		 *
		 * @param {string} key - Filter key
		 * @param {*} value - Filter value
		 */
		setFilter(key, value) {
			this.filters[key] = value
		},

		/**
		 * Fetch preview data for the selected report.
		 */
		async fetchPreview() {
			if (!this.selectedType) return

			this.previewLoading = true
			this.error = null

			try {
				const url = generateUrl(
					`/apps/mitgliederverwaltung/api/v1/reports/${this.selectedType}/preview`,
				)
				const response = await axios.get(url, {
					params: this.filters,
				})
				this.previewData = response.data
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim Laden der Vorschau'
				console.error('Failed to fetch report preview:', err)
			} finally {
				this.previewLoading = false
			}
		},

		/**
		 * Download the report as PDF.
		 */
		async downloadPdf() {
			if (!this.selectedType) return

			this.downloadLoading = true
			this.error = null

			try {
				const url = generateUrl(
					`/apps/mitgliederverwaltung/api/v1/reports/${this.selectedType}/pdf`,
				)
				const response = await axios.get(url, {
					params: this.filters,
					responseType: 'blob',
				})

				this._triggerDownload(response.data, this._getFilename(response, 'pdf'))
				this.success = 'PDF-Download gestartet'
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim PDF-Download'
				console.error('Failed to download PDF:', err)
			} finally {
				this.downloadLoading = false
			}
		},

		/**
		 * Download the report as CSV (plain export).
		 */
		async downloadCsv() {
			if (!this.selectedType) return

			this.downloadLoading = true
			this.error = null

			try {
				// Map report types to CSV export endpoints where available
				const csvEndpoints = {
					mitgliederliste: '/apps/mitgliederverwaltung/api/v1/export/members',
					beitragsliste: '/apps/mitgliederverwaltung/api/v1/export/fees',
					geburtstagsliste: '/apps/mitgliederverwaltung/api/v1/export/birthdays',
				}

				const endpoint = csvEndpoints[this.selectedType]
				if (!endpoint) {
					this.error = 'CSV-Export für diesen Berichtstyp nicht verfügbar'
					return
				}

				const url = generateUrl(endpoint)
				const response = await axios.get(url, {
					params: this.filters,
					responseType: 'blob',
				})

				this._triggerDownload(response.data, this._getFilename(response, 'csv'))
				this.success = 'CSV-Download gestartet'
			} catch (err) {
				this.error = err.response?.data?.error || 'Fehler beim CSV-Download'
				console.error('Failed to download CSV:', err)
			} finally {
				this.downloadLoading = false
			}
		},

		/**
		 * Download the report as encrypted ZIP (password-protected).
		 *
		 * @param {string} password - User-provided password
		 */
		async downloadEncrypted(password) {
			if (!this.selectedType) return

			this.downloadLoading = true
			this.error = null

			try {
				const url = generateUrl(
					`/apps/mitgliederverwaltung/api/v1/reports/${this.selectedType}/encrypted`,
				)
				const response = await axios.post(url, {
					...this.filters,
					password,
				}, {
					responseType: 'blob',
				})

				this._triggerDownload(response.data, this._getFilename(response, 'zip'))
				this.success = 'Verschlüsselter Download gestartet'
			} catch (err) {
				if (err.response?.status === 422) {
					this.error = 'Passwort muss mindestens 8 Zeichen lang sein'
				} else if (err.response?.status === 403) {
					this.error = 'Keine Berechtigung für diesen Export'
				} else {
					this.error = err.response?.data?.error || 'Fehler beim verschlüsselten Download'
				}
				console.error('Failed to download encrypted report:', err)
			} finally {
				this.downloadLoading = false
			}
		},

		/**
		 * Trigger a file download in the browser.
		 *
		 * @param {Blob} blob - File content
		 * @param {string} filename - Suggested filename
		 */
		_triggerDownload(blob, filename) {
			const url = window.URL.createObjectURL(blob)
			const link = document.createElement('a')
			link.href = url
			link.setAttribute('download', filename)
			document.body.appendChild(link)
			link.click()
			link.remove()
			window.URL.revokeObjectURL(url)
		},

		/**
		 * Extract filename from Content-Disposition or generate a default.
		 *
		 * @param {object} response - Axios response
		 * @param {string} ext - File extension
		 * @returns {string}
		 */
		_getFilename(response, ext) {
			const disposition = response.headers['content-disposition']
			if (disposition) {
				const match = disposition.match(/filename="?([^";\n]+)"?/)
				if (match) return match[1]
			}
			const date = new Date().toISOString().slice(0, 10)
			return `Bericht_${this.selectedType}_${date}.${ext}`
		},

		clearError() {
			this.error = null
		},

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