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

const { getSessionMock, writeTextMock } = vi.hoisted(() => ({
    getSessionMock: vi.fn(),
    writeTextMock: vi.fn()
}));

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

const profilesFixture = [
    { id: 'p1', name: 'High Risk Scalper ⚡', allocated_capital: 1000, risk_per_trade_percent: 1.5, symbols: 'BTC/USDT' },
    { id: 'p2', name: 'Conservative Bag', allocated_capital: 2000, risk_per_trade_percent: 0.8, symbols: 'ETH/USDT' }
];

describe('ChatControl DOM flow', () => {
    beforeEach(() => {
        getSessionMock.mockReset();
        writeTextMock.mockReset();
        vi.stubGlobal('fetch', vi.fn());

        Object.defineProperty(globalThis.navigator, 'clipboard', {
            value: { writeText: writeTextMock },
            configurable: true
        });
    });

    it('opens chat, shows quick actions, and handles unauthenticated send errors', async () => {
        getSessionMock.mockResolvedValue({ data: { session: null } });
        const onApplyProfile = vi.fn(async () => ({ success: true }));
        const user = userEvent.setup();

        render(<ChatControl profiles={profilesFixture} onApplyProfile={onApplyProfile} />);

        await user.click(screen.getAllByRole('button')[0]);

        expect(screen.getByText('AI Strategy Assistant')).toBeInTheDocument();
        expect(screen.getByText('Tune High Risk Scalper ⚡')).toBeInTheDocument();
        expect(screen.getByText('Tune Conservative Bag')).toBeInTheDocument();

        await user.type(screen.getByPlaceholderText('Describe a strategy profile...'), 'Create a conservative profile{enter}');

        await waitFor(() => {
            expect(screen.getByText(/Error: Not authenticated/i)).toBeInTheDocument();
        }, { timeout: 3000 });
    }, 15000);

    it('sends prompt, edits profile draft, copies JSON, and applies profile', async () => {
        getSessionMock.mockResolvedValue({ data: { session: { access_token: 'token-1' } } });
        const fetchMock = vi.mocked(fetch);
        fetchMock.mockResolvedValue({
            ok: true,
            json: async () => ({
                summary: 'Generated profile summary',
                reasoning: 'Reasoning details',
                action: 'create_profile',
                profile: {
                    name: 'AI Generated',
                    allocated_capital: 1500,
                    risk_per_trade_percent: 1.2,
                    symbols: 'BTC/USDT',
                    is_active: true,
                    strategy_config: {
                        rules: [{ ruleId: 'TrendBiasRule', enabled: true }]
                    }
                }
            })
        } as any);

        const onApplyProfile = vi.fn(async () => ({ success: true }));
        const user = userEvent.setup();

        render(<ChatControl profiles={profilesFixture} onApplyProfile={onApplyProfile} />);

        await user.click(screen.getAllByRole('button')[0]);

        const textarea = screen.getByPlaceholderText('Describe a strategy profile...');
        await user.type(textarea, 'Create a profile for BTC/USDT{enter}');

        await waitFor(() => {
            expect(screen.getByText(/Generated profile summary/i)).toBeInTheDocument();
            expect(screen.getByText(/Reasoning details/i)).toBeInTheDocument();
        });

        await user.click(screen.getByTitle('Copy JSON'));

        await user.click(screen.getByRole('button', { name: /Edit Params/i }));
        const capitalInput = screen.getByPlaceholderText('Capital');
        await user.clear(capitalInput);
        await user.type(capitalInput, '2500');

        await user.click(screen.getByRole('button', { name: /Apply to Dashboard/i }));

        await waitFor(() => {
            expect(onApplyProfile).toHaveBeenCalledWith(
                'create_profile',
                expect.objectContaining({
                    name: 'AI Generated',
                    allocated_capital: 2500
                })
            );
            expect(screen.getByText('Applied')).toBeInTheDocument();
        });
    }, 20000);

    it('marks generated profile action as cancelled', async () => {
        getSessionMock.mockResolvedValue({ data: { session: { access_token: 'token-2' } } });
        vi.mocked(fetch).mockResolvedValue({
            ok: true,
            json: async () => ({
                summary: 'Generated profile summary',
                action: 'create_profile',
                profile: {
                    name: 'Cancelable Profile',
                    allocated_capital: 1200,
                    risk_per_trade_percent: 1,
                    symbols: 'ETH/USDT',
                    is_active: true,
                    strategy_config: { rules: [] }
                }
            })
        } as any);

        const user = userEvent.setup();

        render(<ChatControl profiles={profilesFixture} onApplyProfile={vi.fn(async () => ({ success: true }))} />);
        await user.click(screen.getAllByRole('button')[0]);
        await user.type(screen.getByPlaceholderText('Describe a strategy profile...'), 'Create profile{enter}');

        await waitFor(() => {
            expect(screen.getByRole('button', { name: /Cancel/i })).toBeInTheDocument();
        });

        await user.click(screen.getByRole('button', { name: /Cancel/i }));

        await waitFor(() => {
            expect(screen.getByText('Cancelled')).toBeInTheDocument();
            expect(screen.getByText(/Profile creation cancelled/i)).toBeInTheDocument();
        });
    });
});
