// #region Test.Translate.InsertMethodSelector [C:2] [TYPE Module] [SEMANTICS test, translate, insert-method, ui]
// @BRIEF Vitest tests for InsertMethodSelector component states and transitions.
// @RELATION BINDS_TO -> [Translate.InsertMethodSelector]
// @TEST_INVARIANT: default state -> sqllab_selected
// @TEST_INVARIANT: direct_db with connections -> dropdown visible
// @TEST_INVARIANT: direct_db no connections -> Settings link visible
// @TEST_EDGE: empty connections list -> "Go to Settings" link shown
// @TEST_EDGE: dialect mismatch -> connections filtered out
// @TEST_INVARIANT: test_connection success/failure -> result displayed

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/svelte';
import InsertMethodSelector from '$lib/components/translate/InsertMethodSelector.svelte';
import { api } from '$lib/api';

vi.mock('$lib/api', () => ({
  api: {
    fetchConnections: vi.fn(),
    testConnection: vi.fn(),
  },
}));

vi.mock('$lib/i18n/index.svelte.js', () => ({
  getT: () => ({
    translate: { config: {} },
    settings: {},
  }),
}));

const mockConnections = [
  { id: 'c1', name: 'Products DB', dialect: 'postgresql', host: 'db.prod', port: 5432 },
  { id: 'c2', name: 'Reports DB', dialect: 'postgresql', host: 'db.rpt', port: 5432 },
  { id: 'c3', name: 'ClickHouse', dialect: 'clickhouse', host: 'ch.anal', port: 9000 },
];

describe('InsertMethodSelector', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  // #region default_state [C:2] [TYPE Function]
  // @BRIEF Default state shows sqllab selected
  // @TEST_CONTRACT: insertMethod="sqllab" -> SQL Lab radio checked
  it('defaults to sqllab insert method', () => {
    const { container } = render(InsertMethodSelector, {
      props: { insertMethod: 'sqllab', connectionId: null, jobDialect: 'postgresql' },
    });

    const radios = container.querySelectorAll('input[type="radio"]');
    expect(radios[0].checked).toBe(true);
    expect(radios[1].checked).toBe(false);
  });
  // #endregion default_state

  // #region switch_to_direct_db [C:2] [TYPE Function]
  // @BRIEF Switching to direct_db with connections shows dropdown
  // @TEST_INVARIANT: click direct_db radio -> connections loaded -> dropdown visible
  it('shows connection dropdown when switching to direct_db with connections', async () => {
    vi.mocked(api.fetchConnections).mockResolvedValue(mockConnections);

    const { container } = render(InsertMethodSelector, {
      props: { insertMethod: 'sqllab', connectionId: null, jobDialect: 'postgresql' },
    });

    const radios = container.querySelectorAll('input[type="radio"]');
    fireEvent.click(radios[1]);

    await waitFor(() => {
      expect(api.fetchConnections).toHaveBeenCalled();
      const select = container.querySelector('select');
      expect(select).toBeTruthy();
    });
  });
  // #endregion switch_to_direct_db

  // #region empty_connections [C:2] [TYPE Function]
  // @BRIEF Empty connections shows Settings link
  // @TEST_EDGE: no connections -> "Go to Settings" link rendered
  it('shows settings link when no connections exist', async () => {
    vi.mocked(api.fetchConnections).mockResolvedValue([]);

    const { container } = render(InsertMethodSelector, {
      props: { insertMethod: 'sqllab', connectionId: null, jobDialect: 'postgresql' },
    });

    const radios = container.querySelectorAll('input[type="radio"]');
    fireEvent.click(radios[1]);

    await waitFor(() => {
      expect(container.textContent).toContain('Go to Settings');
    });
  });
  // #endregion empty_connections

  // #region dialect_filtering [C:2] [TYPE Function]
  // @BRIEF Connections filtered by dialect matching jobDialect
  // @TEST_EDGE: clickhouse dialect -> only clickhouse connections shown
  it('filters connections by dialect', async () => {
    vi.mocked(api.fetchConnections).mockResolvedValue(mockConnections);

    const { container } = render(InsertMethodSelector, {
      props: { insertMethod: 'sqllab', connectionId: null, jobDialect: 'clickhouse' },
    });

    const radios = container.querySelectorAll('input[type="radio"]');
    fireEvent.click(radios[1]);

    await waitFor(() => {
      const select = container.querySelector('select');
      const options = select?.querySelectorAll('option');
      const optionTexts = Array.from(options || []).map(o => o.textContent);
      // Should only have clickhouse connections. PostgreSQL ones filtered out
      expect(optionTexts.some(t => t?.includes('ClickHouse'))).toBe(true);
      // Default option "Select connection" counts too
      expect(optionTexts.some(t => t?.includes('Products DB'))).toBe(false);
    });
  });
  // #endregion dialect_filtering

  // #region test_connection_result [C:2] [TYPE Function]
  // @BRIEF Connection test success shows result
  // @TEST_EDGE: test_connection success -> green success message
  it('calls testConnection API when Test button clicked', async () => {
    vi.mocked(api.fetchConnections).mockResolvedValue(mockConnections);
    vi.mocked(api.testConnection).mockResolvedValue({ success: true, latency_ms: 12 });

    render(InsertMethodSelector, {
      props: { insertMethod: 'direct_db', connectionId: 'c1', jobDialect: 'postgresql' },
    });

    // The button text is the i18n fallback "Test Connection"
    await waitFor(() => {
      expect(screen.getByText('Test Connection')).toBeTruthy();
    });

    await fireEvent.click(screen.getByText('Test Connection'));

    await waitFor(() => {
      expect(api.testConnection).toHaveBeenCalledWith('c1');
    });
  });
  // #endregion test_connection_result
});
// #endregion Test.Translate.InsertMethodSelector
