import { defineStore } from "pinia";
import { useNotificationStore } from "./notifications-primevue";

/**
 * Enhanced Error Store with Automatic PrimeVue Toast Notifications
 *
 * This store automatically creates PrimeVue Toast notifications when errors are set.
 * No need to import both error and notification stores - just use this one!
 *
 * Usage:
 * import { useErrorStore } from '@/stores/errors'
 * const errorStore = useErrorStore()
 *
 * // These will automatically show toast notifications:
 * errorStore.setGlobalError(new Error("Something went wrong"))
 * errorStore.setComponentError("form", new Error("Validation failed"))
 * errorStore.setApiError("fetch-users", new Error("Network error"))
 *
 * // Convenience methods for non-error notifications:
 * errorStore.setSuccess("Operation completed!")
 * errorStore.setWarning("Please check your input")
 * errorStore.setInfo("Loading data...")
 */
export const useErrorStore = defineStore("errors", {
	state: () => ({
		// Global error state
		hasError: false,
		lastError: null,

		// API-specific errors
		apiErrors: new Map(),

		// Component-specific errors
		componentErrors: {
			dataTable: null,
			form: null,
			clients: null,
			jobs: null,
			timesheets: null,
			warranties: null,
			routes: null,
		},

		// Error history for debugging
		errorHistory: [],

		// Configuration
		maxHistorySize: 50,
		autoNotifyErrors: true,
	}),

	getters: {
		// Check if any error exists
		hasAnyError: (state) => {
			return (
				state.hasError ||
				state.apiErrors.size > 0 ||
				Object.values(state.componentErrors).some((error) => error !== null)
			);
		},

		// Get error for a specific component
		getComponentError: (state) => (componentName) => {
			return state.componentErrors[componentName];
		},

		// Get error for a specific API call
		getApiError: (state) => (apiKey) => {
			return state.apiErrors.get(apiKey);
		},

		// Get recent errors
		getRecentErrors:
			(state) =>
			(limit = 10) => {
				return state.errorHistory.slice(-limit).reverse();
			},
	},

	actions: {
		// Set global error
		setGlobalError(error, showNotification = true) {
			this.hasError = true;
			this.lastError = this._normalizeError(error);
			this._addToHistory(this.lastError, "global");

			if (showNotification && this.autoNotifyErrors) {
				const notificationStore = useNotificationStore();
				notificationStore.addError(this.lastError.message, "Global Error", {
					duration: 5000,
				});
			}
		},

		// Set component-specific error
		setComponentError(componentName, error, showNotification = true) {
			const normalizedError = error ? this._normalizeError(error) : null;

			if (this.componentErrors.hasOwnProperty(componentName)) {
				this.componentErrors[componentName] = normalizedError;
			} else {
				this.componentErrors[componentName] = normalizedError;
			}

			if (normalizedError) {
				this._addToHistory(normalizedError, `component:${componentName}`);

				if (showNotification && this.autoNotifyErrors) {
					const notificationStore = useNotificationStore();
					notificationStore.addError(
						normalizedError.message,
						`${this._formatComponentName(componentName)} Error`,
						{ duration: 5000 },
					);
				}
			}
		},

		// Set API-specific error
		setApiError(apiKey, error, showNotification = true) {
			if (error) {
				const normalizedError = this._normalizeError(error);
				this.apiErrors.set(apiKey, normalizedError);
				this._addToHistory(normalizedError, `api:${apiKey}`);

				if (showNotification && this.autoNotifyErrors) {
					const notificationStore = useNotificationStore();
					notificationStore.addError(normalizedError.message, "API Error", {
						duration: 6000,
					});
				}
			} else {
				this.apiErrors.delete(apiKey);
			}
		},

		// Clear specific errors
		clearGlobalError() {
			this.hasError = false;
			this.lastError = null;
		},

		clearComponentError(componentName) {
			if (this.componentErrors.hasOwnProperty(componentName)) {
				this.componentErrors[componentName] = null;
			}
		},

		clearApiError(apiKey) {
			this.apiErrors.delete(apiKey);
		},

		// Clear all errors
		clearAllErrors() {
			this.hasError = false;
			this.lastError = null;
			this.apiErrors.clear();
			Object.keys(this.componentErrors).forEach((key) => {
				this.componentErrors[key] = null;
			});
		},

		// Handle API call errors with automatic error management
		async handleApiCall(apiKey, apiFunction, options = {}) {
			const {
				showNotification = true,
				retryCount = 0,
				retryDelay = 1000,
				onSuccess = null,
				onError = null,
			} = options;

			// Clear any existing error for this API
			this.clearApiError(apiKey);

			let attempt = 0;
			while (attempt <= retryCount) {
				try {
					const result = await apiFunction();

					if (onSuccess) {
						onSuccess(result);
					}

					return result;
				} catch (error) {
					attempt++;

					if (attempt <= retryCount) {
						// Wait before retry
						await new Promise((resolve) => setTimeout(resolve, retryDelay));
						continue;
					}

					// Final attempt failed
					this.setApiError(apiKey, error, showNotification);

					if (onError) {
						onError(error);
					}

					throw error;
				}
			}
		},

		// Convenience method for handling async operations with error management
		async withErrorHandling(operationKey, asyncOperation, options = {}) {
			const { componentName = null, showNotification = true, rethrow = false } = options;

			try {
				const result = await asyncOperation();

				// Clear any existing errors on success
				if (componentName) {
					this.clearComponentError(componentName);
				}

				return result;
			} catch (error) {
				if (componentName) {
					this.setComponentError(componentName, error, showNotification);
				} else {
					this.setGlobalError(error, showNotification);
				}

				if (rethrow) {
					throw error;
				}

				return null;
			}
		},

		// Private helper methods
		_normalizeError(error) {
			if (typeof error === "string") {
				return {
					message: error,
					type: "string_error",
					timestamp: new Date().toISOString(),
				};
			}

			if (error instanceof Error) {
				return {
					message: error.message,
					name: error.name,
					stack: error.stack,
					type: "javascript_error",
					timestamp: new Date().toISOString(),
				};
			}

			// Handle API response errors
			if (error && error.response) {
				return {
					message:
						error.response.data?.message || error.response.statusText || "API Error",
					status: error.response.status,
					statusText: error.response.statusText,
					data: error.response.data,
					type: "api_error",
					timestamp: new Date().toISOString(),
				};
			}

			// Handle network errors
			if (error && error.request) {
				return {
					message: "Network error - please check your connection",
					type: "network_error",
					timestamp: new Date().toISOString(),
				};
			}

			// Fallback for unknown error types
			return {
				message: error?.message || "An unknown error occurred",
				originalError: error,
				type: "unknown_error",
				timestamp: new Date().toISOString(),
			};
		},

		_addToHistory(normalizedError, source) {
			this.errorHistory.push({
				...normalizedError,
				source,
				id: Date.now() + Math.random(),
			});

			// Trim history if it exceeds max size
			if (this.errorHistory.length > this.maxHistorySize) {
				this.errorHistory = this.errorHistory.slice(-this.maxHistorySize);
			}
		},

		// Success notifications (convenience methods)
		setSuccess(message, title = "Success", options = {}) {
			if (this.autoNotifyErrors) {
				const notificationStore = useNotificationStore();
				notificationStore.addSuccess(message, title, options);
			}
		},

		setWarning(message, title = "Warning", options = {}) {
			if (this.autoNotifyErrors) {
				const notificationStore = useNotificationStore();
				notificationStore.addWarning(message, title, options);
			}
		},

		setInfo(message, title = "Info", options = {}) {
			if (this.autoNotifyErrors) {
				const notificationStore = useNotificationStore();
				notificationStore.addInfo(message, title, options);
			}
		},

		// Configuration methods
		setAutoNotifyErrors(enabled) {
			this.autoNotifyErrors = enabled;
		},

		setMaxHistorySize(size) {
			this.maxHistorySize = size;
			if (this.errorHistory.length > size) {
				this.errorHistory = this.errorHistory.slice(-size);
			}
		},

		// Helper method to format component names nicely
		_formatComponentName(componentName) {
			return componentName
				.split(/[-_]/)
				.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
				.join(" ");
		},
	},
});
