/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import fetchMock from 'fetch-mock';
import { render, screen, waitFor } from 'spec/helpers/testing-library';
import userEvent from '@testing-library/user-event';
import DatasourceEditor from '..';
import { props, DATASOURCE_ENDPOINT } from './DatasourceEditor.test';

// Optimized render function that doesn't use waitFor initially
// This helps prevent one source of the timeout
const fastRender = props =>
  render(<DatasourceEditor {...props} />, {
    useRedux: true,
    initialState: { common: { currencies: ['USD', 'GBP', 'EUR'] } },
  });

// eslint-disable-next-line no-restricted-globals -- TODO: Migrate from describe blocks
describe('DatasourceEditor Currency Tests', () => {
  beforeEach(() => {
    fetchMock.get(DATASOURCE_ENDPOINT, [], { overwriteRoutes: true });
  });

  afterEach(() => {
    fetchMock.restore();
  });

  // The problematic test, now optimized
  test('renders currency controls', async () => {
    // Setup a metric with currency data
    const propsWithCurrency = {
      ...props,
      datasource: {
        ...props.datasource,
        metrics: [
          {
            ...props.datasource.metrics[0],
            currency: { symbol: 'USD', symbolPosition: 'prefix' },
          },
          ...props.datasource.metrics.slice(1),
        ],
      },
      // Fresh mock for each test to avoid interference
      onChange: jest.fn(),
    };

    // Faster rendering without initial waitFor
    fastRender(propsWithCurrency);

    // Navigate to metrics tab
    const metricButton = screen.getByTestId('collection-tab-Metrics');
    await userEvent.click(metricButton);

    // Find and expand the first metric row
    const expandToggles = await screen.findAllByLabelText(
      /expand row/i,
      {},
      { timeout: 5000 },
    );
    await userEvent.click(expandToggles[0]);

    // Check for currency section header
    const currencyHeader = await screen.findByText(
      'Metric currency',
      {},
      { timeout: 5000 },
    );
    expect(currencyHeader).toBeVisible();

    // Check prefix/suffix dropdown - first find the wrapper
    const positionSelector = screen.getByRole('combobox', {
      name: 'Currency prefix or suffix',
    });

    // Verify current value is 'Prefix'
    expect(positionSelector).toBeInTheDocument();

    // Open the dropdown
    userEvent.click(positionSelector);

    // Wait for dropdown to open and find the suffix option
    const suffixOption = await waitFor(
      () => {
        // Look for 'suffix' option in the dropdown
        const options = document.querySelectorAll('.ant-select-item-option');
        const suffixOpt = Array.from(options).find(opt =>
          opt.textContent.toLowerCase().includes('suffix'),
        );

        if (!suffixOpt) throw new Error('Suffix option not found');
        return suffixOpt;
      },
      { timeout: 5000 },
    );

    // Clear the mock to ensure clean state
    propsWithCurrency.onChange.mockClear();

    // Click the suffix option
    userEvent.click(suffixOption);

    // Check if onChange was called with the expected parameters
    await waitFor(
      () => {
        expect(propsWithCurrency.onChange).toHaveBeenCalledTimes(1);
        const callArg = propsWithCurrency.onChange.mock.calls[0][0];

        // More robust check for the metrics array
        const metrics = callArg.metrics || [];
        const updatedMetric = metrics.find(
          m => m.currency && m.currency.symbolPosition === 'suffix',
        );

        expect(updatedMetric).toBeDefined();
        expect(updatedMetric.currency.symbol).toBe('USD');
      },
      { timeout: 5000 },
    );

    // Now test changing the currency symbol
    const currencySymbol = await screen.findByRole(
      'combobox',
      {
        name: 'Currency symbol',
      },
      { timeout: 5000 },
    );

    // Open the currency dropdown
    userEvent.click(currencySymbol);

    // Wait for dropdown to open and find the GBP option
    const gbpOption = await waitFor(
      () => {
        // Look for 'GBP' option in the dropdown
        const options = document.querySelectorAll('.ant-select-item-option');
        const gbpOpt = Array.from(options).find(opt =>
          opt.textContent.includes('GBP'),
        );

        if (!gbpOpt) throw new Error('GBP option not found');
        return gbpOpt;
      },
      { timeout: 5000 },
    );

    // Clear mock again
    propsWithCurrency.onChange.mockClear();

    // Click the GBP option
    userEvent.click(gbpOption);

    // Verify the onChange with GBP was called
    await waitFor(
      () => {
        expect(propsWithCurrency.onChange).toHaveBeenCalledTimes(1);
        const callArg = propsWithCurrency.onChange.mock.calls[0][0];

        // More robust check
        const metrics = callArg.metrics || [];
        const updatedMetric = metrics.find(
          m => m.currency && m.currency.symbol === 'GBP',
        );

        expect(updatedMetric).toBeDefined();
        expect(updatedMetric.currency.symbolPosition).toBe('suffix');
      },
      { timeout: 5000 },
    );
  }, 60000);
});
