import { describe, it, expect, vi } from 'vitest';
import { render } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import NostrProvider from './NostrProvider';
import { AppProvider } from '@/components/AppProvider';
import { AppConfig } from '@/contexts/AppContext';
import { NWelshman } from '@nostrify/welshman';

// Mock NWelshman since it requires network access
vi.mock('@nostrify/welshman', () => ({
  NWelshman: vi.fn().mockImplementation(() => ({
    query: vi.fn().mockResolvedValue([]),
    event: vi.fn().mockResolvedValue(undefined),
    req: vi.fn().mockImplementation(async function* () {
      yield ['EOSE', ''];
    }),
    close: vi.fn().mockResolvedValue(undefined),
  })),
}));

const defaultConfig: AppConfig = {
  theme: "light",
  relayUrl: "wss://relay.primal.net",
};

const presetRelays = [
  { url: 'wss://relay.nostr.band', name: 'Nostr.Band' },
  { url: 'wss://relay.damus.io', name: 'Damus' },
];

describe('NostrProvider with NWelshman', () => {
  it('renders children without errors', () => {
    const queryClient = new QueryClient({
      defaultOptions: {
        queries: { retry: false },
        mutations: { retry: false },
      },
    });

    const TestComponent = () => <div data-testid="test-child">Test content</div>;

    const { getByTestId } = render(
      <QueryClientProvider client={queryClient}>
        <AppProvider storageKey="test:app-config" defaultConfig={defaultConfig} presetRelays={presetRelays}>
          <NostrProvider>
            <TestComponent />
          </NostrProvider>
        </AppProvider>
      </QueryClientProvider>
    );

    expect(getByTestId('test-child')).toBeInTheDocument();
  });

  it('creates NWelshman with router configuration', async () => {
    const queryClient = new QueryClient({
      defaultOptions: {
        queries: { retry: false },
        mutations: { retry: false },
      },
    });

    const TestComponent = () => <div>Test</div>;

    render(
      <QueryClientProvider client={queryClient}>
        <AppProvider storageKey="test:app-config-2" defaultConfig={defaultConfig} presetRelays={presetRelays}>
          <NostrProvider>
            <TestComponent />
          </NostrProvider>
        </AppProvider>
      </QueryClientProvider>
    );

    // Verify NWelshman was instantiated
    expect(vi.mocked(NWelshman)).toHaveBeenCalled();
    
    // Verify router was passed with correct configuration
    const routerArg = vi.mocked(NWelshman).mock.calls[0][0];
    expect(routerArg).toBeDefined();
    expect(typeof routerArg.options.getUserPubkey).toBe('function');
    expect(typeof routerArg.options.getStaticRelays).toBe('function');
    expect(typeof routerArg.options.getIndexerRelays).toBe('function');
    expect(typeof routerArg.options.getSearchRelays).toBe('function');
    expect(typeof routerArg.options.getRelayQuality).toBe('function');
    
    // Test router methods return expected values
    const staticRelays = routerArg.options.getStaticRelays();
    expect(staticRelays).toContain('wss://relay.primal.net');
    expect(staticRelays).toContain('wss://relay.nostr.band');
    
    const indexerRelays = routerArg.options.getIndexerRelays();
    expect(indexerRelays).toContain('wss://relay.nostr.band');
    
    const searchRelays = routerArg.options.getSearchRelays();
    expect(searchRelays).toContain('wss://relay.nostr.band');
    
    expect(routerArg.options.getRedundancy()).toBe(2);
    expect(routerArg.options.getLimit()).toBe(5);
  });

  it('handles relay quality scoring', async () => {
    const queryClient = new QueryClient({
      defaultOptions: {
        queries: { retry: false },
        mutations: { retry: false },
      },
    });

    const TestComponent = () => <div>Test</div>;

    render(
      <QueryClientProvider client={queryClient}>
        <AppProvider storageKey="test:app-config-3" defaultConfig={defaultConfig} presetRelays={presetRelays}>
          <NostrProvider>
            <TestComponent />
          </NostrProvider>
        </AppProvider>
      </QueryClientProvider>
    );

    const routerArg = vi.mocked(NWelshman).mock.calls[vi.mocked(NWelshman).mock.calls.length - 1][0];
    const getRelayQuality = routerArg.options.getRelayQuality;
    
    // Test quality scoring
    expect(getRelayQuality('wss://relay.primal.net')).toBe(1.0); // User's configured relay
    expect(getRelayQuality('wss://relay.damus.io')).toBe(0.9); // High quality relay
    expect(getRelayQuality('wss://nostr.band')).toBe(0.9); // High quality relay
    expect(getRelayQuality('wss://unknown.relay')).toBe(0.5); // Unknown relay
  });
});