// @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 { Login } from './Login';

const { loginMock, registerMock, resetPasswordForEmailMock, tradingAuthState } = vi.hoisted(() => ({
    loginMock: vi.fn(),
    registerMock: vi.fn(),
    resetPasswordForEmailMock: vi.fn(),
    tradingAuthState: {
        error: null as string | null
    }
}));

vi.mock('../lib/tradingAuth', () => ({
    useTradingAuth: () => ({
        login: loginMock,
        register: registerMock,
        error: tradingAuthState.error,
    })
}));

vi.mock('../lib/supabaseClient', () => ({
    supabase: {
        auth: {
            resetPasswordForEmail: resetPasswordForEmailMock
        }
    }
}));

describe('Login DOM flow', () => {
    beforeEach(() => {
        loginMock.mockReset();
        registerMock.mockReset();
        resetPasswordForEmailMock.mockReset();
        tradingAuthState.error = null;
        loginMock.mockResolvedValue(true);
        registerMock.mockResolvedValue(true);
        resetPasswordForEmailMock.mockResolvedValue({ error: null });
    });

    it('submits sign-in credentials and surfaces auth errors', async () => {
        tradingAuthState.error = 'Invalid login credentials';
        loginMock.mockResolvedValueOnce(false);
        const user = userEvent.setup();

        render(<Login />);

        await user.type(screen.getByPlaceholderText('trader@example.com'), 'user@demo.com');
        await user.type(screen.getByPlaceholderText('••••••••'), 'bad-password');
        await user.click(screen.getByRole('button', { name: 'Sign In' }));

        await waitFor(() => {
            expect(loginMock).toHaveBeenCalledWith('user@demo.com', 'bad-password');
            expect(screen.getByText('Invalid login credentials')).toBeInTheDocument();
        });

        await user.click(screen.getByRole('button', { name: 'Forgot Password?' }));
        expect(screen.getByText('Reset your password')).toBeInTheDocument();
        expect(screen.queryByText('Invalid login credentials')).not.toBeInTheDocument();
    }, 15000);

    it('submits sign-up and shows confirmation message', async () => {
        const user = userEvent.setup();
        render(<Login />);

        await user.click(screen.getByRole('button', { name: 'Need an account? Sign Up' }));
        expect(screen.getByText('Create an account')).toBeInTheDocument();

        await user.type(screen.getByPlaceholderText('trader@example.com'), 'new@demo.com');
        await user.type(screen.getByPlaceholderText(/•|â€¢/), 'StrongPassword1!');
        await user.click(screen.getByRole('button', { name: 'Sign Up' }));

        await waitFor(() => {
            expect(registerMock).toHaveBeenCalledWith('new@demo.com', 'StrongPassword1!', 'new');
            expect(screen.getByText('Check your email for the confirmation link!')).toBeInTheDocument();
        });
    });

    it('sends reset password email and lets user return to sign-in', async () => {
        const user = userEvent.setup();
        render(<Login />);

        await user.click(screen.getByRole('button', { name: 'Forgot Password?' }));
        expect(screen.getByRole('button', { name: 'Send Reset Link' })).toBeInTheDocument();
        expect(screen.queryByPlaceholderText(/•|â€¢/)).not.toBeInTheDocument();

        await user.type(screen.getByPlaceholderText('trader@example.com'), 'recover@demo.com');
        await user.click(screen.getByRole('button', { name: 'Send Reset Link' }));

        await waitFor(() => {
            expect(resetPasswordForEmailMock).toHaveBeenCalledWith(
                'recover@demo.com',
                expect.objectContaining({
                    redirectTo: expect.stringContaining('/reset-callback')
                })
            );
            expect(screen.getByText('Password reset link sent! Check your email.')).toBeInTheDocument();
        });

        await user.click(screen.getByRole('button', { name: 'Back to Sign In' }));
        expect(screen.getByText('Sign in to access bot controls')).toBeInTheDocument();
    });
});
