// @vitest-environment jsdom
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { SettingsTab } from './SettingsTab';
import type { BotState } from '../hooks/useWebSocket';

const {
    authState,
    refreshProfileMock,
    updateCurrentUserProfileMock
} = vi.hoisted(() => ({
    authState: {
        user: { id: 'user-1' } as any,
        profile: {
            role: 'admin',
            first_name: 'Sam',
            last_name: 'Trader',
            ALPACA_API_KEY: 'p-key',
            ALPACA_SECRET_KEY: 'p-secret',
            REAL_ALPACA_API_KEY: 'r-key',
            REAL_ALPACA_SECRET_KEY: 'r-secret',
            trade_enable: false,
            drop_threshold_for_buy: 0.02,
            gain_threshold_for_sell: 0.01,
            market_poll_interval_in_seconds: 60000
        } as any
    },
    refreshProfileMock: vi.fn(),
    updateCurrentUserProfileMock: vi.fn()
}));

vi.mock('../components/AuthContext', () => ({
    useAuth: () => ({
        ...authState,
        refreshProfile: refreshProfileMock
    })
}));

vi.mock('../lib/profileApi', () => ({
    updateCurrentUserProfile: updateCurrentUserProfileMock
}));

const botState: BotState = {
    symbols: {}, alerts: [], positions: [], orders: [], history: [],
    settings: {
        executionMode: 'Paper', riskPerTrade: 0.01, totalCapital: 15000,
        maxOpenTrades: 6, isAlgoEnabled: true, enabledRules: ['TrendBiasRule']
    },
    uptime: 1000
};

describe('SettingsTab Master Suite', () => {
    beforeEach(() => {
        vi.clearAllMocks();
        // Reset authState to default
        authState.user = { id: 'user-1' };
        authState.profile = {
            role: 'admin',
            first_name: 'Sam',
            last_name: 'Trader',
            ALPACA_API_KEY: 'p-key',
            ALPACA_SECRET_KEY: 'p-secret',
            trade_enable: false,
            drop_threshold_for_buy: 0.02,
            gain_threshold_for_sell: 0.01,
            market_poll_interval_in_seconds: 60000
        };

        updateCurrentUserProfileMock.mockResolvedValue({});
        vi.stubGlobal('alert', vi.fn());
    });

    it('edits and saves configuration', async () => {
        const user = userEvent.setup();
        const { container } = render(<SettingsTab botState={botState} />);

        await user.click(screen.getByText('Edit Configuration'));

        const firstNameInput = container.querySelector('input[name="first_name"]') as HTMLInputElement;
        await user.clear(firstNameInput);
        await user.type(firstNameInput, 'Sarah');

        await user.click(screen.getByText('Save Changes'));

        await waitFor(() => {
            expect(updateCurrentUserProfileMock).toHaveBeenCalled();
            expect(alert).toHaveBeenCalledWith('Settings saved successfully!');
        });
    });

    it('handles numeric validation error', async () => {
        const user = userEvent.setup();
        const { container } = render(<SettingsTab botState={botState} />);
        await user.click(screen.getByText('Edit Configuration'));

        const buyThresholdInput = container.querySelector('input[name="drop_threshold_for_buy"]') as HTMLInputElement;
        await user.clear(buyThresholdInput);
        await user.type(buyThresholdInput, 'not-a-number');

        await user.click(screen.getByText('Save Changes'));
        expect(alert).toHaveBeenCalledWith(expect.stringContaining('valid numbers'));
    });

    it('covers Cancel button branch', async () => {
        const user = userEvent.setup();
        render(<SettingsTab botState={botState} />);
        await user.click(screen.getByText('Edit Configuration'));
        await user.click(screen.getByText('Cancel'));
        expect(screen.getByText('Edit Configuration')).toBeInTheDocument();
    });

    it('covers save exception catch block', async () => {
        const user = userEvent.setup();
        updateCurrentUserProfileMock.mockRejectedValueOnce(new Error('DB Error'));
        render(<SettingsTab botState={botState} />);
        await user.click(screen.getByText('Edit Configuration'));
        await user.click(screen.getByText('Save Changes'));
        await waitFor(() => expect(alert).toHaveBeenCalledWith(expect.stringContaining('DB Error')));
    });

    it('covers fallback in mapProfileToFormData', () => {
        authState.profile = null;
        render(<SettingsTab botState={botState} />);
        expect(screen.getByDisplayValue('user')).toBeInTheDocument();
    });
});
