/*!
 * Matomo - free/libre analytics platform
 *
 * @link    https://matomo.org
 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 */

import { mount } from '@vue/test-utils';

// CoreHome is a package-style cross-plugin import with no jest module mapping, so it must be
// virtually mocked. Tooltips is the (no-op here) directive used by the real MetricValue this
// component mounts. The sparkline itself is rendered by the shell, not this body.
jest.mock('CoreHome', () => ({
  Tooltips: {},
  // ucfirst is mocked as an identity passthrough; its capitalization is covered by ucfirst.spec.
  ucfirst: (s?: string) => s ?? '',
}), { virtual: true });

// eslint-disable-next-line @typescript-eslint/no-var-requires
const NoComparison = require('./NoComparison.vue').default;

function makeSparkline(overrides = {}) {
  return {
    url: '?module=API&action=get&columns=nb_visits',
    metrics: { '': [{ value: '10,558', description: 'Visits', column: 'nb_visits' }] },
    order: 1,
    title: null,
    group: '0',
    seriesIndices: null,
    graphParams: null,
    ...overrides,
  };
}

function createWrapper(sparkline: unknown, allMetricsDocumentation: Record<string, string> = {}) {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  return mount(NoComparison as any, { props: { sparkline, allMetricsDocumentation } });
}

describe('CoreVisualizations/NoComparison', () => {
  it('passes the primary metric to MetricValue as title + value', () => {
    const wrapper = createWrapper(makeSparkline());

    const metricValue = wrapper.findComponent({ name: 'MetricValue' });
    expect(metricValue.props('title')).toBe('Visits');
    expect(metricValue.props('value')).toBe('10,558');
  });

  it('gives MetricValue the fixed-height modifier so no-comparison cards line up', () => {
    // The fixed height + one-line title clamp live on MetricValue via this modifier (defined in
    // MetricValue.less), not reached into from here, so the class must ride on the MetricValue root.
    const wrapper = createWrapper(makeSparkline());

    expect(wrapper.findComponent({ name: 'MetricValue' }).classes())
      .toContain('metricValue--fixedHeight');
  });

  it('resolves the primary metric documentation by column and passes it to MetricValue', () => {
    const wrapper = createWrapper(
      makeSparkline(),
      { nb_visits: 'The number of visits.' },
    );

    expect(wrapper.findComponent({ name: 'MetricValue' }).props('documentation'))
      .toBe('The number of visits.');
  });

  it('passes undefined documentation when the metric column is unknown or empty', () => {
    const wrapper = createWrapper(
      makeSparkline({ metrics: { '': [{ value: '10,558', description: 'Visits', column: '' }] } }),
      { nb_visits: 'The number of visits.' },
    );

    expect(wrapper.findComponent({ name: 'MetricValue' }).props('documentation')).toBeUndefined();
  });

  it('passes a second metric to MetricValue as the secondary value + label', () => {
    const wrapper = createWrapper(makeSparkline({
      metrics: {
        '': [
          { value: '10,558', description: 'Visits' },
          { value: '9,527', description: 'unique' },
        ],
      },
    }));

    const metricValue = wrapper.findComponent({ name: 'MetricValue' });
    expect(metricValue.props('secondaryValue')).toBe('9,527');
    expect(metricValue.props('secondaryLabel')).toBe('unique');
    expect(wrapper.find('.metricValue__secondaryLine').text()).toBe('9,527 unique');
  });

  it('omits the secondary line when there is only one metric', () => {
    const wrapper = createWrapper(makeSparkline());

    const metricValue = wrapper.findComponent({ name: 'MetricValue' });
    expect(metricValue.props('secondaryValue')).toBeUndefined();
    expect(wrapper.find('.metricValue__secondary').exists()).toBe(false);
  });

  it('renders an EvolutionBadge with the entry evolution props when present', () => {
    const wrapper = createWrapper(makeSparkline({
      evolution: {
        percent: '+0.5%',
        trend: 53,
        isLowerValueBetter: false,
        tooltip: 'since last period',
      },
    }));

    const badge = wrapper.findComponent({ name: 'EvolutionBadge' });
    expect(badge.exists()).toBe(true);
    expect(badge.props('percent')).toBe('+0.5%');
    expect(badge.props('trend')).toBe(53);
    expect(badge.props('isLowerValueBetter')).toBe(false);
    expect(badge.props('tooltip')).toBe('since last period');
  });

  it('renders no EvolutionBadge when the entry has no evolution', () => {
    const wrapper = createWrapper(makeSparkline());

    expect(wrapper.findComponent({ name: 'EvolutionBadge' }).exists()).toBe(false);
  });

  it('coerces a null evolution tooltip to an empty string for the badge', () => {
    const wrapper = createWrapper(makeSparkline({
      evolution: {
        percent: '-2%',
        trend: -10,
        isLowerValueBetter: false,
        tooltip: null,
      },
    }));

    expect(wrapper.findComponent({ name: 'EvolutionBadge' }).props('tooltip')).toBe('');
  });
});
