import { describe, it, expect, vi } from 'vitest';
import { Alpaca, AlpacaClient } from './alpaca';

function mockClient(overrides: Partial<AlpacaClient> = {}): AlpacaClient {
    return {
        getAccount: vi.fn().mockResolvedValue({ cash: '10000.00' }),
        getAssets: vi.fn().mockResolvedValue([]),
        getAsset: vi.fn().mockResolvedValue({ symbol: 'TQQQ', fractionable: true, status: 'active', asset_class: 'us_equity' }),
        getClock: vi.fn().mockResolvedValue({ is_open: false, next_open: '2025-01-01T14:30:00Z', next_close: '2025-01-01T21:00:00Z' }),
        getLatestQuote: vi.fn().mockResolvedValue({ ap: 50.00, bp: 49.90 }),
        getLatestTrades: vi.fn().mockResolvedValue(new Map()),
        ...overrides,
    };
}

describe('Alpaca', () => {
    it('throws when live is true', () => {
        expect(() => new Alpaca(true)).toThrow('not doing live yet');
    });

    it('delegates getAccount to the underlying client', async () => {
        const client = mockClient();
        const alpaca = new Alpaca(false, client);
        const account = await alpaca.getAccount();
        expect(account.cash).toBe('10000.00');
        expect(client.getAccount).toHaveBeenCalled();
    });

    it('delegates getAsset with the symbol string', async () => {
        const client = mockClient();
        const alpaca = new Alpaca(false, client);
        await alpaca.getAsset('TQQQ');
        expect(client.getAsset).toHaveBeenCalledWith('TQQQ');
    });

    it('delegates getClock to the underlying client', async () => {
        const client = mockClient();
        const alpaca = new Alpaca(false, client);
        const clock = await alpaca.getClock();
        expect(clock.is_open).toBe(false);
        expect(client.getClock).toHaveBeenCalled();
    });

    it('delegates getLatestQuote to the underlying client', async () => {
        const client = mockClient();
        const alpaca = new Alpaca(false, client);
        const quote = await alpaca.getLatestQuote('TQQQ');
        expect(quote.ap).toBe(50.00);
        expect(client.getLatestQuote).toHaveBeenCalledWith('TQQQ');
    });

    it('delegates getAssets with active us_equity filter', async () => {
        const client = mockClient();
        const alpaca = new Alpaca(false, client);
        await alpaca.getAssets();
        expect(client.getAssets).toHaveBeenCalledWith({ status: 'active', asset_class: 'us_equity' });
    });

    it('delegates getLatestTrades to the underlying client', async () => {
        const client = mockClient();
        const alpaca = new Alpaca(false, client);
        await alpaca.getLatestTrades(['TQQQ', 'SPY']);
        expect(client.getLatestTrades).toHaveBeenCalledWith(['TQQQ', 'SPY']);
    });
});
