// #region MaintenanceFormTests [C:2] [TYPE Module] [SEMANTICS test, component, maintenance, start, form, environment_id]
// @BRIEF Component tests for StartMaintenanceForm — verifies environment_id is included in submission.
// @RELATION BINDS_TO -> [StartMaintenanceForm]
// @TEST_CONTRACT: Submit includes environment_id from environmentContextStore
// @TEST_EDGE: No environment selected -> error toast, no API call
// @TEST_EDGE: Environment selected -> API call includes environment_id

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/svelte';

// ── Hoisted mutable state (before vi.mock calls, hoisted to top) ──

const { mockStartMaintenance, mockAddToast, mockEnvStore } = vi.hoisted(() => {
    // Mutable env store state — tests can change this before render
    let _selectedEnvId = 'env-prod';

    const mockEnvStoreObj = {
        value: {
            get selectedEnvId() { return _selectedEnvId; },
        },
        subscribe: vi.fn(),
    };

    return {
        mockStartMaintenance: vi.fn(),
        mockAddToast: vi.fn(),
        mockEnvStore: {
            obj: mockEnvStoreObj,
            setSelectedEnvId(id: string) { _selectedEnvId = id; },
        },
    };
});

// ── Module mocks ──────────────────────────────────────────────

vi.mock('$lib/api/maintenance.js', () => ({
    startMaintenance: mockStartMaintenance,
}));

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

vi.mock('$lib/stores/environmentContext.svelte.js', () => ({
    environmentContextStore: mockEnvStore.obj,
}));

vi.mock('$lib/i18n/index.svelte.js', () => {
    const subscribers = new Set();
    const tData = {
        maintenance: {
            start_maintenance: 'Start Maintenance',
            start_maintenance_description: 'Schedule a maintenance window',
            start_now: 'Start Maintenance',
            starting: 'Starting...',
            start_success: 'Maintenance started. Task: {task_id}',
            start_error: 'Failed to start maintenance',
            table_name: 'Table Name',
            table_required: 'Table name is required',
            table_name_placeholder: 'e.g. raw.sales',
            table_help: 'Enter the table name',
            start_time_label: 'Start Time',
            start_time_help: 'When maintenance begins',
            end_time_label: 'End Time (optional)',
            end_time_help: 'When maintenance ends',
            message_label: 'Message (optional)',
            message_placeholder: 'Scheduled data mart refresh',
            template_label: 'Quick Template',
            template_none: 'Custom',
            template_daily_refresh: 'Daily Refresh',
            template_daily_refresh_desc: '4h ETL window',
            template_schema_migration: 'Schema Migration',
            template_schema_migration_desc: '2h schema change',
            template_emergency: 'Emergency',
            template_emergency_desc: '1h critical fix',
            template_extended: 'Extended',
            template_extended_desc: '8h large refresh',
            no_environment: 'No environment selected. Please select an environment first.',
        },
        common: {},
    };
    return {
        t: {
            subscribe(run: (_value: unknown) => void) {
                subscribers.add(run);
                run(tData);
                return () => subscribers.delete(run);
            },
        },
        _: (key: string) => key,
        getT: () => ({}),
    };
});

// ── Imports (after mocks) ─────────────────────────────────────

import StartMaintenanceForm from '$lib/components/StartMaintenanceForm.svelte';

describe('StartMaintenanceForm', () => {
    beforeEach(() => {
        vi.clearAllMocks();
        // Reset to default: environment selected
        mockEnvStore.setSelectedEnvId('env-prod');
    });

    // #region test_submits_with_environment_id [C:2] [TYPE Function]
    // @BRIEF Submit with environment selected includes environment_id in API call.
    // @TEST_EDGE: Environment selected -> API call includes environment_id
    it('submits with environment_id from context store', async () => {
        mockStartMaintenance.mockResolvedValue({
            task_id: 'task-1',
            maintenance_id: 'm-1',
            status: 'pending',
        });

        render(StartMaintenanceForm);

        // Fill in table name
        const tableInput = screen.getByPlaceholderText('e.g. raw.sales');
        await fireEvent.input(tableInput, { target: { value: 'raw.my_table' } });

        // Click the submit button (use role to avoid heading match)
        const submitButton = screen.getByRole('button', { name: /Start Maintenance/i });
        await fireEvent.click(submitButton);

        // Verify startMaintenance was called with environment_id
        expect(mockStartMaintenance).toHaveBeenCalledTimes(1);
        const callParams = mockStartMaintenance.mock.calls[0][0];
        expect(callParams).toHaveProperty('environment_id', 'env-prod');
        expect(callParams).toHaveProperty('tables');
        expect(callParams.tables).toContain('raw.my_table');
    });
    // #endregion test_submits_with_environment_id

    // #region test_validation_fails_without_environment [C:2] [TYPE Function]
    // @BRIEF No environment selected shows error toast and does not call API.
    // @TEST_EDGE: No environment selected -> error toast, no API call
    it('shows error toast when no environment is selected', async () => {
        // Set empty environment
        mockEnvStore.setSelectedEnvId('');

        render(StartMaintenanceForm);

        // Fill in table name
        const tableInput = screen.getByPlaceholderText('e.g. raw.sales');
        await fireEvent.input(tableInput, { target: { value: 'raw.my_table' } });

        // Click the submit button
        const submitButton = screen.getByRole('button', { name: /Start Maintenance/i });
        await fireEvent.click(submitButton);

        // API should NOT have been called
        expect(mockStartMaintenance).not.toHaveBeenCalled();

        // Error toast should have been shown with the missing environment message
        expect(mockAddToast).toHaveBeenCalledWith(
            expect.stringContaining('No environment selected'),
            'error',
        );
    });
    // #endregion test_validation_fails_without_environment

    // #region test_validation_fails_without_table [C:2] [TYPE Function]
    // @BRIEF Empty table name shows inline validation, no API call.
    it('shows validation error when table name is empty', async () => {
        render(StartMaintenanceForm);

        // Click Submit without filling table name
        const submitButton = screen.getByRole('button', { name: /Start Maintenance/i });
        await fireEvent.click(submitButton);

        // API should NOT have been called
        expect(mockStartMaintenance).not.toHaveBeenCalled();

        // Inline validation error should be visible
        expect(screen.getByText('Table name is required')).toBeTruthy();
    });
    // #endregion test_validation_fails_without_table
});
// #endregion MaintenanceFormTests
