// #region MaintenanceStoreTests [C:2] [TYPE Module] [SEMANTICS test, store, maintenance]
// @BRIEF Unit tests for MaintenanceStore runes-based store.
// @RELATION DEPENDS_ON -> [MaintenanceStore]

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

// Use vi.hoisted to create mock functions before the mock factories
const { mockListEvents, mockGetSettings, mockUpdateSettings, mockEndMaintenance, mockEndAllMaintenance, mockListDashboardBanners } = vi.hoisted(() => ({
    mockListEvents: vi.fn(),
    mockGetSettings: vi.fn(),
    mockUpdateSettings: vi.fn(),
    mockEndMaintenance: vi.fn(),
    mockEndAllMaintenance: vi.fn(),
    mockListDashboardBanners: vi.fn(),
}));

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

// Mock i18n
vi.mock('$lib/i18n/index.svelte.js', () => ({
    t: { maintenance: {} }
}));

vi.mock('$lib/api/maintenance.js', () => ({
    listEvents: mockListEvents,
    getSettings: mockGetSettings,
    updateSettings: mockUpdateSettings,
    endMaintenance: mockEndMaintenance,
    endAllMaintenance: mockEndAllMaintenance,
    listDashboardBanners: mockListDashboardBanners,
}));

import { createMaintenanceStore } from '$lib/stores/maintenance.svelte.js';

describe('MaintenanceStore', () => {
    let store;

    beforeEach(() => {
        vi.clearAllMocks();
        mockListEvents.mockResolvedValue({ active: [], completed: [] });
        mockGetSettings.mockResolvedValue({
            target_environment_id: 'prod',
            display_timezone: 'UTC',
            banner_template: 'test template',
            dashboard_scope: 'published_only',
            excluded_dashboard_ids: [],
            forced_dashboard_ids: [],
            updated_at: null
        });
        mockListDashboardBanners.mockResolvedValue([]);
        store = createMaintenanceStore();
    });

    it('initializes with empty state', () => {
        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 calls API and updates state', async () => {
        mockListEvents.mockResolvedValue({
            active: [{ id: 'ev-1', tables: ['raw.sales'], status: 'active' }],
            completed: [{ id: 'ev-2', tables: ['raw.inventory'], status: 'completed' }]
        });

        await store.loadEvents();

        expect(mockListEvents).toHaveBeenCalledTimes(1);
        expect(store.activeEvents).toHaveLength(1);
        expect(store.activeEvents[0].id).toBe('ev-1');
        expect(store.completedEvents).toHaveLength(1);
        expect(store.completedEvents[0].id).toBe('ev-2');
    });

    it('loadEvents sets error on API failure', async () => {
        mockListEvents.mockRejectedValue(new Error('Network error'));

        await store.loadEvents();

        expect(store.error).toBeTruthy();
        expect(store.activeEvents).toEqual([]);
    });

    it('loadSettings calls API and updates settings', async () => {
        const testSettings = {
            target_environment_id: 'staging',
            display_timezone: 'Europe/Moscow',
            banner_template: 'custom template',
            dashboard_scope: 'all',
            excluded_dashboard_ids: [1, 2],
            forced_dashboard_ids: [3],
            updated_at: null
        };
        mockGetSettings.mockResolvedValue(testSettings);

        await store.loadSettings();

        expect(store.settings).toEqual(testSettings);
    });

    it('loadSettings does not throw on API failure', async () => {
        mockGetSettings.mockRejectedValue(new Error('API error'));

        await expect(store.loadSettings()).resolves.not.toThrow();
        expect(store.settings).toBeNull();
    });

    it('loadDashboardBanners updates state', async () => {
        const banners = [
            { dashboard_id: 42, active: true, events: ['ev-1'], start_time: '2026-05-21T22:00:00Z', end_time: null },
            { dashboard_id: 57, active: false, events: [], start_time: null, end_time: null }
        ];
        mockListDashboardBanners.mockResolvedValue(banners);

        await store.loadDashboardBanners();

        expect(mockListDashboardBanners).toHaveBeenCalledTimes(1);
        expect(store.dashboardBanners).toHaveLength(2);
    });

    it('loadDashboardBanners handles non-array response', async () => {
        mockListDashboardBanners.mockResolvedValue(null);

        await store.loadDashboardBanners();

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

    it('endEvent calls API and refreshes events', async () => {
        mockEndMaintenance.mockResolvedValue({ task_id: 'task-1', status: 'pending' });
        mockListEvents.mockResolvedValue({ active: [], completed: [] });

        await store.endEvent('ev-1');

        expect(mockEndMaintenance).toHaveBeenCalledWith('ev-1');
        expect(mockListEvents).toHaveBeenCalled();
    });

    it('endAllEvents calls API and refreshes events', async () => {
        mockEndAllMaintenance.mockResolvedValue({ task_id: 'task-bulk', status: 'pending' });
        mockListEvents.mockResolvedValue({ active: [], completed: [] });

        await store.endAllEvents();

        expect(mockEndAllMaintenance).toHaveBeenCalled();
        expect(mockListEvents).toHaveBeenCalled();
    });

    it('updateSettings calls API and updates settings', async () => {
        const newSettings = { dashboard_scope: 'all' };
        mockUpdateSettings.mockResolvedValue({
            ...newSettings,
            target_environment_id: 'prod',
            display_timezone: 'UTC',
            banner_template: 'test',
            excluded_dashboard_ids: [],
            forced_dashboard_ids: [],
            updated_at: '2026-05-22T10:00:00Z'
        });

        await store.updateSettings(newSettings);

        expect(mockUpdateSettings).toHaveBeenCalledWith(newSettings);
        expect(store.settings).toBeTruthy();
        expect(store.settings.dashboard_scope).toBe('all');
    });
});
// #endregion MaintenanceStoreTests
