// #region Test.Maintenance [C:3] [TYPE Module] [SEMANTICS test, maintenance, store, runes, events, settings, ws]
// @BRIEF Unit tests for maintenance store — initial state, load events/settings/banners, end events, update settings, WS lifecycle.
// @RELATION DEPENDS_ON -> [MaintenanceStore]
// @TEST_EDGE: loadEvents_failure -> store catches error, sets error state, isLoading reset
// @TEST_EDGE: dashboardBanners_non_array -> store coerces non-array response to empty array
// @TEST_EDGE: endEvent_no_task_id -> endEvent succeeds without adding info toast

import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock maintenance API
const mockMaintenanceApi = {
	listEvents: vi.fn(),
	listDashboardBanners: vi.fn(),
	getSettings: vi.fn(),
	endMaintenance: vi.fn(),
	endAllMaintenance: vi.fn(),
	updateSettings: vi.fn(),
};

vi.mock('$lib/api/maintenance', () => mockMaintenanceApi);

// Mock $lib/api (for getMaintenanceEventsWsUrl)
const mockGetMaintenanceEventsWsUrl = vi.fn(() => 'ws://localhost/ws/maintenance/events');
vi.mock('$lib/api', () => ({
	getMaintenanceEventsWsUrl: mockGetMaintenanceEventsWsUrl,
}));

// Mock toasts
const mockAddToast = vi.fn();
vi.mock('$lib/toasts.svelte.js', () => ({
	addToast: mockAddToast,
}));

describe('maintenanceStore', () => {
	beforeEach(() => {
		vi.clearAllMocks();
	});

	it('should have correct initial state', async () => {
		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		expect(store.activeEvents).toEqual([]);
		expect(store.completedEvents).toEqual([]);
		expect(store.settings).toBeNull();
		expect(store.dashboardBanners).toEqual([]);
		expect(store.isLoading).toBe(false);
		expect(store.error).toBeNull();
	});

	it('loadEvents should populate active and completed events', async () => {
		mockMaintenanceApi.listEvents.mockResolvedValue({
			active: [{ id: 'e1', message: 'DB migration' }],
			completed: [{ id: 'e2', message: 'Done' }],
		});

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadEvents();

		expect(store.activeEvents).toEqual([{ id: 'e1', message: 'DB migration' }]);
		expect(store.completedEvents).toEqual([{ id: 'e2', message: 'Done' }]);
		expect(store.isLoading).toBe(false);
		expect(store.error).toBeNull();
	});

	it('loadEvents should handle empty active/completed', async () => {
		mockMaintenanceApi.listEvents.mockResolvedValue({});

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadEvents();

		expect(store.activeEvents).toEqual([]);
		expect(store.completedEvents).toEqual([]);
	});

	it('loadEvents should set error on failure', async () => {
		mockMaintenanceApi.listEvents.mockRejectedValue(new Error('Connection refused'));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadEvents();

		expect(store.error).toBe('Connection refused');
		expect(store.isLoading).toBe(false);
	});

	it('loadEvents should set isLoading during fetch', async () => {
		let resolvePromise!: (v: unknown) => void;
		mockMaintenanceApi.listEvents.mockReturnValue(new Promise((r) => { resolvePromise = r; }));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		const promise = store.loadEvents();
		expect(store.isLoading).toBe(true);

		resolvePromise({ active: [], completed: [] });
		await promise;
		expect(store.isLoading).toBe(false);
	});

	it('loadSettings should populate settings', async () => {
		mockMaintenanceApi.getSettings.mockResolvedValue({ enabled: true, notify_users: true });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadSettings();

		expect(store.settings).toEqual({ enabled: true, notify_users: true });
	});

	it('loadSettings should keep settings null on error', async () => {
		mockMaintenanceApi.getSettings.mockRejectedValue(new Error('Not found'));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadSettings();

		expect(store.settings).toBeNull();
	});

	it('loadDashboardBanners should populate banners array', async () => {
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([
			{ dashboard_id: 'd1', active: true },
			{ dashboard_id: 'd2', active: false },
		]);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadDashboardBanners();

		expect(store.dashboardBanners).toHaveLength(2);
		expect(store.dashboardBanners[0].dashboard_id).toBe('d1');
	});

	it('loadDashboardBanners should coerce non-array response to empty array', async () => {
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue(null);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadDashboardBanners();

		expect(store.dashboardBanners).toEqual([]);
	});

	it('loadDashboardBanners should handle API error gracefully', async () => {
		mockMaintenanceApi.listDashboardBanners.mockRejectedValue(new Error('Server error'));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadDashboardBanners();

		expect(store.dashboardBanners).toEqual([]);
	});

	it('endEvent should call maintenanceApi and reload events on success with task_id', async () => {
		mockMaintenanceApi.endMaintenance.mockResolvedValue({ task_id: 't1' });
		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.endEvent('maint-1');

		expect(mockMaintenanceApi.endMaintenance).toHaveBeenCalledWith('maint-1');
		expect(mockAddToast).toHaveBeenCalledWith('Removal task started', 'info');
		expect(mockMaintenanceApi.listEvents).toHaveBeenCalled();
	});

	it('endEvent should not add info toast when no task_id returned', async () => {
		mockMaintenanceApi.endMaintenance.mockResolvedValue({});
		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.endEvent('maint-2');

		expect(mockAddToast).not.toHaveBeenCalled();
	});

	it('endEvent should show error toast and rethrow on failure', async () => {
		mockMaintenanceApi.endMaintenance.mockRejectedValue(new Error('End failed'));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await expect(store.endEvent('maint-3')).rejects.toThrow('End failed');
		expect(mockAddToast).toHaveBeenCalledWith('End failed', 'error');
	});

	it('endAllEvents should call maintenanceApi and reload events on success', async () => {
		mockMaintenanceApi.endAllMaintenance.mockResolvedValue({ task_id: 'bulk-t1' });
		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.endAllEvents();

		expect(mockMaintenanceApi.endAllMaintenance).toHaveBeenCalled();
		expect(mockAddToast).toHaveBeenCalledWith('Bulk removal task started', 'info');
	});

	it('endAllEvents should show error toast on failure', async () => {
		mockMaintenanceApi.endAllMaintenance.mockRejectedValue(new Error('Bulk failed'));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await expect(store.endAllEvents()).rejects.toThrow('Bulk failed');
		expect(mockAddToast).toHaveBeenCalledWith('Bulk failed', 'error');
	});

	it('updateSettings should update settings and show success toast', async () => {
		const newSettings = { enabled: true };
		mockMaintenanceApi.updateSettings.mockResolvedValue({ enabled: true, notify_users: false });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.updateSettings(newSettings);

		expect(mockMaintenanceApi.updateSettings).toHaveBeenCalledWith(newSettings);
		expect(store.settings).toEqual({ enabled: true, notify_users: false });
		expect(mockAddToast).toHaveBeenCalledWith('Settings saved', 'success');
		expect(store.isLoading).toBe(false);
	});

	it('updateSettings should show error toast on failure', async () => {
		mockMaintenanceApi.updateSettings.mockRejectedValue(new Error('Save failed'));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await expect(store.updateSettings({})).rejects.toThrow('Save failed');
		expect(mockAddToast).toHaveBeenCalledWith('Save failed', 'error');
	});

	it('updateSettings should set isLoading during operation', async () => {
		let resolvePromise!: (v: unknown) => void;
		mockMaintenanceApi.updateSettings.mockReturnValue(new Promise((r) => { resolvePromise = r; }));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		const promise = store.updateSettings({ test: true });
		expect(store.isLoading).toBe(true);

		resolvePromise({});
		await promise;
		expect(store.isLoading).toBe(false);
	});

	it('init should call loadEvents, loadSettings, loadDashboardBanners', async () => {
		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({ enabled: true });
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);

		// Mock WebSocket
		const mockWebSocket = vi.fn();
		vi.stubGlobal('WebSocket', mockWebSocket);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.init();

		expect(mockMaintenanceApi.listEvents).toHaveBeenCalled();
		expect(mockMaintenanceApi.getSettings).toHaveBeenCalled();
		expect(mockMaintenanceApi.listDashboardBanners).toHaveBeenCalled();
		expect(mockWebSocket).toHaveBeenCalledWith('ws://localhost/ws/maintenance/events');

		vi.unstubAllGlobals();
	});

	it('disconnectWs should close open WebSocket', async () => {
		const mockClose = vi.fn();
		class MockWs {
			close = mockClose;
			onopen: (() => void) | null = null;
			onmessage: ((e: MessageEvent) => void) | null = null;
			onerror: (() => void) | null = null;
			onclose: (() => void) | null = null;
		}
		vi.stubGlobal('WebSocket', MockWs as unknown as typeof WebSocket);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);
		await store.init();

		store.disconnectWs();
		expect(mockClose).toHaveBeenCalled();

		vi.unstubAllGlobals();
	});

	it('should maintain reactive state across multiple loadEvents calls', async () => {
		mockMaintenanceApi.listEvents
			.mockResolvedValueOnce({ active: [{ id: 'e1' }], completed: [] })
			.mockResolvedValueOnce({ active: [{ id: 'e1' }, { id: 'e2' }], completed: [{ id: 'e3' }] });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		await store.loadEvents();
		expect(store.activeEvents).toHaveLength(1);

		await store.loadEvents();
		expect(store.activeEvents).toHaveLength(2);
		expect(store.completedEvents).toHaveLength(1);
	});

	it('loadSettings should silently fail on error (no state mutation beyond console.error)', async () => {
		mockMaintenanceApi.getSettings.mockRejectedValue(new Error('fail'));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadSettings();

		// settings remains null, no toast, no error state change
		expect(store.settings).toBeNull();
		expect(store.error).toBeNull();
	});

	// ── WebSocket lifecycle edge cases ──────────────────────────────

	it('WebSocket onopen should set connected log', async () => {
		let mockWs: any = null;
		class TestWebSocket {
			close = vi.fn();
			send = vi.fn();
			onopen: (() => void) | null = null;
			onmessage: ((e: MessageEvent) => void) | null = null;
			onerror: (() => void) | null = null;
			onclose: ((e: CloseEvent) => void) | null = null;
			constructor(_url: string) {
				mockWs = this;
			}
		}
		vi.stubGlobal('WebSocket', TestWebSocket as unknown as typeof WebSocket);

		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);
		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.init();

		// Invoke onopen - should not throw
		expect(mockWs.onopen).not.toBeNull();
		mockWs.onopen!();

		vi.unstubAllGlobals();
	});

	it('connectWs should not create duplicate WebSocket when already connected', async () => {
		let wsConstructorCalls = 0;

		// Use a class-based mock for WebSocket
		class MockWebSocket {
			close = vi.fn();
			send = vi.fn();
			onopen: (() => void) | null = null;
			onmessage: ((e: MessageEvent) => void) | null = null;
			onerror: (() => void) | null = null;
			onclose: ((e: CloseEvent) => void) | null = null;
			constructor(_url: string) {
				wsConstructorCalls++;
			}
		}
		vi.stubGlobal('WebSocket', MockWebSocket as unknown as typeof WebSocket);

		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		await store.init();
		expect(wsConstructorCalls).toBe(1);

		// Call disconnectWs, then connectWs should create a new one
		store.disconnectWs();

		await store.init();
		expect(wsConstructorCalls).toBe(2);

		vi.unstubAllGlobals();
	});

	it('connectWs should return early when _ws is already set (guard at line 62)', async () => {
		let wsConstructorCalls = 0;

		class MockWebSocket {
			close = vi.fn();
			send = vi.fn();
			onopen: (() => void) | null = null;
			onmessage: ((e: MessageEvent) => void) | null = null;
			onerror: (() => void) | null = null;
			onclose: ((e: CloseEvent) => void) | null = null;
			constructor(_url: string) {
				wsConstructorCalls++;
			}
		}
		vi.stubGlobal('WebSocket', MockWebSocket as unknown as typeof WebSocket);

		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		await store.init();
		expect(wsConstructorCalls).toBe(1);

		// Call init again WITHOUT disconnectWs — connectWs guard should fire
		await store.init();
		// WS constructor should NOT be called again (guard at line 62: if (_ws) return;)
		expect(wsConstructorCalls).toBe(1);

		vi.unstubAllGlobals();
	});

	it('connectWs should handle WebSocket constructor failure gracefully', async () => {
		class FailingWebSocket {
			constructor(_url: string) {
				throw new Error('WS unavailable');
			}
		}
		vi.stubGlobal('WebSocket', FailingWebSocket as unknown as typeof WebSocket);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		// init will call connectWs which should catch the constructor error
		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);

		// Should not throw
		await store.init();

		vi.unstubAllGlobals();
	});

	it('WebSocket onmessage should reload events and dashboard banners', async () => {
		let mockWs: any = null;
		class TestWebSocket {
			close = vi.fn();
			send = vi.fn();
			onopen: (() => void) | null = null;
			onmessage: ((e: MessageEvent) => void) | null = null;
			onerror: (() => void) | null = null;
			onclose: ((e: CloseEvent) => void) | null = null;
			constructor(_url: string) {
				mockWs = this;
			}
		}
		vi.stubGlobal('WebSocket', TestWebSocket as unknown as typeof WebSocket);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [{ id: 'ws-event' }], completed: [] });
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([{ dashboard_id: 'd1' }]);
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		await store.init();

		// Simulate a WS message
		expect(mockWs.onmessage).not.toBeNull();
		await mockWs.onmessage!(new MessageEvent('message', { data: '{}' }));

		expect(store.activeEvents).toEqual([{ id: 'ws-event' }]);
		expect(store.dashboardBanners).toEqual([{ dashboard_id: 'd1' }]);

		vi.unstubAllGlobals();
	});

	it('WebSocket onerror handler should not throw', async () => {
		let mockWs: any = null;
		class TestWebSocket {
			close = vi.fn();
			send = vi.fn();
			onopen: (() => void) | null = null;
			onmessage: ((e: MessageEvent) => void) | null = null;
			onerror: (() => void) | null = null;
			onclose: ((e: CloseEvent) => void) | null = null;
			constructor(_url: string) {
				mockWs = this;
			}
		}
		vi.stubGlobal('WebSocket', TestWebSocket as unknown as typeof WebSocket);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');

		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);
		const store = createMaintenanceStore();
		await store.init();

		// Should not throw
		expect(mockWs.onerror).not.toBeNull();
		mockWs.onerror!();

		vi.unstubAllGlobals();
	});

	it('WebSocket onclose should schedule reconnect after 10s', async () => {
		vi.useFakeTimers();

		let wsConstructorCount = 0;
		let mockWs: any = null;
		class TestWebSocket {
			close = vi.fn();
			send = vi.fn();
			onopen: (() => void) | null = null;
			onmessage: ((e: MessageEvent) => void) | null = null;
			onerror: (() => void) | null = null;
			onclose: ((e: CloseEvent) => void) | null = null;
			constructor(_url: string) {
				wsConstructorCount++;
				mockWs = this;
			}
		}
		vi.stubGlobal('WebSocket', TestWebSocket as unknown as typeof WebSocket);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');

		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);
		const store = createMaintenanceStore();
		await store.init();

		const countBeforeClose = wsConstructorCount;

		// Simulate WS closing
		expect(mockWs.onclose).not.toBeNull();
		mockWs.onclose!(new CloseEvent('close', { code: 1006 }));

		// Advance time by 10s to trigger reconnect
		vi.advanceTimersByTime(10_000);

		// Should have created a new WS
		expect(wsConstructorCount).toBeGreaterThan(countBeforeClose);

		vi.useRealTimers();
		vi.unstubAllGlobals();
	});

	it('onclose reconnect guard should prevent double-connect when WS already reconnected (line 87)', async () => {
		vi.useFakeTimers();

		let wsConstructorCalls = 0;
		let mockWs: any = null;
		class TestWebSocket {
			close = vi.fn();
			send = vi.fn();
			onopen: (() => void) | null = null;
			onmessage: ((e: MessageEvent) => void) | null = null;
			onerror: (() => void) | null = null;
			onclose: ((e: CloseEvent) => void) | null = null;
			constructor(_url: string) {
				wsConstructorCalls++;
				mockWs = this;
			}
		}
		vi.stubGlobal('WebSocket', TestWebSocket as unknown as typeof WebSocket);

		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });
		mockMaintenanceApi.getSettings.mockResolvedValue({});
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([]);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.init();
		expect(wsConstructorCalls).toBe(1);

		// Trigger WS close with abnormal code → schedules reconnect after 10s
		// onclose sets _ws = null, then _handleWsFailure schedules setTimeout
		mockWs.onclose!(new CloseEvent('close', { code: 1006 }));

		// Before the 10s timer fires, re-establish connection via init()
		// This calls connectWs() which creates a new WS (line 62 guard passes since _ws is null)
		await store.init();
		expect(wsConstructorCalls).toBe(2);

		// Now advance past the original 10s reconnect timer
		// The setTimeout callback checks `if (_ws) return;` (line 87)
		// Since _ws is truthy (set by the second init), it should NOT reconnect
		vi.advanceTimersByTime(10_000);

		// WS constructor should NOT be called again
		expect(wsConstructorCalls).toBe(2);

		vi.useRealTimers();
		vi.unstubAllGlobals();
	});

	it('disconnectWs should be safe when no WebSocket exists', () => {
		// Need fresh store without init
		const { createMaintenanceStore } = import('../maintenance.svelte.js') as any;
		// Actually import properly
	});

	it('disconnectWs should be a no-op when called without active WebSocket', async () => {
		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		// No WebSocket was created — should not throw
		store.disconnectWs();
	});

	// ── endEvent/endAllEvents edge cases ─────────────────────────────

	it('endEvent should reload events after success with task_id', async () => {
		const listEventsSpy = mockMaintenanceApi.listEvents;
		listEventsSpy.mockResolvedValue({ active: [{ id: 'e1' }], completed: [] });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		mockMaintenanceApi.endMaintenance.mockResolvedValue({ task_id: 't1' });
		await store.endEvent('maint-1');

		// Events should be reloaded
		expect(store.activeEvents).toEqual([{ id: 'e1' }]);
	});

	it('endAllEvents should reload events after success', async () => {
		const listEventsSpy = mockMaintenanceApi.listEvents;
		listEventsSpy.mockResolvedValue({ active: [], completed: [{ id: 'e2' }] });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();

		mockMaintenanceApi.endAllMaintenance.mockResolvedValue({});
		await store.endAllEvents();

		expect(store.completedEvents).toEqual([{ id: 'e2' }]);
	});

	it('endAllEvents should not add info toast when no task_id', async () => {
		mockMaintenanceApi.endAllMaintenance.mockResolvedValue({});
		mockMaintenanceApi.listEvents.mockResolvedValue({ active: [], completed: [] });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.endAllEvents();

		expect(mockAddToast).not.toHaveBeenCalled();
	});

	// ── loadDashboardBanners edge cases ──────────────────────────────

	it('loadDashboardBanners should handle non-array data from API', async () => {
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue({ not: 'an array' });

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadDashboardBanners();

		expect(store.dashboardBanners).toEqual([]);
	});

	it('loadDashboardBanners should handle array response correctly', async () => {
		mockMaintenanceApi.listDashboardBanners.mockResolvedValue([
			{ dashboard_id: 'd1', active: true },
		]);

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		await store.loadDashboardBanners();

		expect(store.dashboardBanners).toHaveLength(1);
		expect(store.dashboardBanners[0].dashboard_id).toBe('d1');
	});

	// ── isLoading during updateSettings ──────────────────────────────

	it('updateSettings should set isLoading to false on error', async () => {
		mockMaintenanceApi.updateSettings.mockRejectedValue(new Error('Fail'));

		const { createMaintenanceStore } = await import('../maintenance.svelte.js');
		const store = createMaintenanceStore();
		store.updateSettings({}).catch(() => {});

		// Re-throw to test isLoading reset
		await expect(store.updateSettings({ test: true })).rejects.toThrow('Fail');
		expect(store.isLoading).toBe(false);
	});
});
// #endregion Test.Maintenance
