// #region MaintenanceStore [C:4] [TYPE Store] [SEMANTICS store, maintenance, svelte, runes, websocket]
// @BRIEF Svelte 5 (Runes) store for maintenance banner state. Uses WebSocket for real-time events.
// @LAYER Frontend
// @RELATION DEPENDS_ON -> [MaintenanceApi]
// @RELATION DEPENDS_ON -> [ToastsModule]
// @RELATION DEPENDS_ON -> [ApiModule.getMaintenanceEventsWsUrl]
// @UX_STATE Idle -> events loaded, settings loaded, banners loaded
// @UX_STATE Loading -> isLoading = true during fetches
// @UX_STATE Error -> error state populated with message
// @UX_REACTIVITY $state for events/settings/banners. WebSocket for real-time updates.
// @UX_RECOVERY WebSocket reconnect after 10s on disconnect. Fallback to HTTP init().
// @RATIONALE Replaced 30s polling with WebSocket for instant maintenance banner updates
//            on the dashboard hub page and maintenance events page.

import { addToast } from "$lib/toasts.svelte.js";
import { getMaintenanceEventsWsUrl } from "$lib/api";
import * as maintenanceApi from "$lib/api/maintenance";

export interface MaintenanceApiEvent {
	active?: unknown[];
	completed?: unknown[];
}

export interface MaintenanceBanner {
	dashboard_id?: string;
	active?: boolean;
	[k: string]: unknown;
}

export interface MaintenanceSettings {
	[k: string]: unknown;
}

export interface MaintenanceStore {
	readonly activeEvents: unknown[];
	readonly completedEvents: unknown[];
	readonly settings: MaintenanceSettings | null;
	readonly dashboardBanners: MaintenanceBanner[];
	readonly isLoading: boolean;
	readonly error: string | null;
	loadEvents: () => Promise<void>;
	loadSettings: () => Promise<void>;
	loadDashboardBanners: () => Promise<void>;
	endEvent: (maintenanceId: string) => Promise<void>;
	endAllEvents: () => Promise<void>;
	updateSettings: (newSettings: MaintenanceSettings) => Promise<void>;
	init: () => Promise<void>;
	disconnectWs: () => void;
}

export function createMaintenanceStore(): MaintenanceStore {
	let activeEvents = $state<unknown[]>([]);
	let completedEvents = $state<unknown[]>([]);
	let settings = $state<MaintenanceSettings | null>(null);
	let dashboardBanners = $state<MaintenanceBanner[]>([]);
	let isLoading = $state(false);
	let error = $state<string | null>(null);
	let _ws: WebSocket | null = null;

	function connectWs(): void {
		if (_ws) return;
		try {
			const url = getMaintenanceEventsWsUrl();
			_ws = new WebSocket(url);

			_ws.onopen = () => {
				console.log("[MaintenanceStore][WS] Connected");
			};

			_ws.onmessage = async (_event: MessageEvent) => {
				try {
					await Promise.all([loadEvents(), loadDashboardBanners()]);
				} catch (_e) {
					// Ignore parse errors
				}
			};

			_ws.onerror = () => {
				console.warn("[MaintenanceStore][WS] Error");
			};

			_ws.onclose = () => {
				console.log("[MaintenanceStore][WS] Disconnected — reconnecting in 10s");
				_ws = null;
				setTimeout(() => {
					if (_ws) return;
					connectWs();
				}, 10000);
			};
		} catch (_e) {
			_ws = null;
		}
	}

	function disconnectWs(): void {
		if (_ws) {
			_ws.onclose = null;
			_ws.close();
			_ws = null;
		}
	}

	async function loadEvents(): Promise<void> {
		isLoading = true;
		error = null;
		try {
			const data = (await maintenanceApi.listEvents()) as MaintenanceApiEvent;
			activeEvents = data.active || [];
			completedEvents = data.completed || [];
		} catch (e: unknown) {
			const msg = (e as Error)?.message || "Failed to load events";
			error = msg;
			console.error("[MaintenanceStore] loadEvents error:", msg);
		} finally {
			isLoading = false;
		}
	}

	async function loadDashboardBanners(): Promise<void> {
		try {
			const data = await maintenanceApi.listDashboardBanners<MaintenanceBanner[]>();
			dashboardBanners = Array.isArray(data) ? data : [];
		} catch (e: unknown) {
			console.error("[MaintenanceStore] loadDashboardBanners error:", (e as Error)?.message);
			dashboardBanners = [];
		}
	}

	async function loadSettings(): Promise<void> {
		try {
			settings = await maintenanceApi.getSettings<MaintenanceSettings>();
		} catch (e: unknown) {
			console.error("[MaintenanceStore] loadSettings error:", (e as Error)?.message);
		}
	}

	async function endEvent(maintenanceId: string): Promise<void> {
		try {
			const data = await maintenanceApi.endMaintenance<{ task_id?: string }>(maintenanceId);
			if (data?.task_id) {
				addToast("Removal task started", "info");
			}
			await loadEvents();
		} catch (e: unknown) {
			const msg = (e as Error)?.message || "Failed to end maintenance event";
			addToast(msg, "error");
			throw e;
		}
	}

	async function endAllEvents(): Promise<void> {
		try {
			const data = await maintenanceApi.endAllMaintenance<{ task_id?: string }>();
			if (data?.task_id) {
				addToast("Bulk removal task started", "info");
			}
			await loadEvents();
		} catch (e: unknown) {
			const msg = (e as Error)?.message || "Failed to end all events";
			addToast(msg, "error");
			throw e;
		}
	}

	async function updateSettingsFun(newSettings: MaintenanceSettings): Promise<void> {
		isLoading = true;
		try {
			settings = await maintenanceApi.updateSettings<MaintenanceSettings>(newSettings);
			addToast("Settings saved", "success");
		} catch (e: unknown) {
			const msg = (e as Error)?.message || "Failed to update settings";
			addToast(msg, "error");
			throw e;
		} finally {
			isLoading = false;
		}
	}

	async function init(): Promise<void> {
		await Promise.all([loadEvents(), loadSettings(), loadDashboardBanners()]);
		connectWs();
	}

	return {
		get activeEvents() { return activeEvents; },
		get completedEvents() { return completedEvents; },
		get settings() { return settings; },
		get dashboardBanners() { return dashboardBanners; },
		get isLoading() { return isLoading; },
		get error() { return error; },
		loadEvents,
		loadSettings,
		loadDashboardBanners,
		endEvent,
		endAllEvents,
		updateSettings: updateSettingsFun,
		init,
		disconnectWs,
	};
}

export const maintenanceStore: MaintenanceStore = createMaintenanceStore();
// #endregion MaintenanceStore
