import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { fireEvent, render, screen } from '@testing-library/react'
import { Provider } from '../provider/widget-provider'
import {
  clearAllWidgetStores,
  useTransformEnabled,
  useWidgetId,
} from '../stores'
import { Category } from './category'
import { RelativeData } from '../actions/relative-data/relative-data'
import type { CategoryWidgetData } from './types'

beforeEach(() => clearAllWidgetStores())
afterEach(() => clearAllWidgetStores())

// Replicates `CategoryActionWiring` from the storybook composer
// (apps/storybook/stories/modules/widgets/category/category.tsx). The
// composer-level wiring isn't testable in `apps/storybook` (no vitest
// infra), so we re-implement just the relative-data branch here and
// assert the bar-width math end-to-end through Provider → action →
// bridge → UI.
function Wired({ maxOverride }: { maxOverride?: number }) {
  const id = useWidgetId()
  const relativeDataActive = useTransformEnabled(id, 'relative-data')
  const effectiveMaxOverride = relativeDataActive ? 100 : maxOverride
  return <Category maxOverride={effectiveMaxOverride} />
}

// Single-series dataset where the max value is 1000 so percent values
// map to round numbers we can match exactly against bar widths.
const DATA: CategoryWidgetData = [
  [
    { name: 'A', value: 1000 },
    { name: 'B', value: 500 },
    { name: 'C', value: 250 },
  ],
]

function getBarFills(): HTMLElement[] {
  return Array.from(
    document.querySelectorAll<HTMLElement>('[data-bar-fill="true"]'),
  )
}

describe('Category + RelativeData composer wiring', () => {
  it('default (RelativeData off) → bars scale to data max', () => {
    render(
      <Provider id='cat-rd-off' data={DATA}>
        <RelativeData />
        <Wired />
      </Provider>,
    )
    const fills = getBarFills()
    expect(fills).toHaveLength(3)
    // 1000/1000, 500/1000, 250/1000
    expect(fills[0]!.style.width).toBe('100%')
    expect(fills[1]!.style.width).toBe('50%')
    expect(fills[2]!.style.width).toBe('25%')
  })

  it('clicking the % action flips bars to a 100-denominator', () => {
    render(
      <Provider id='cat-rd-toggle' data={DATA}>
        <RelativeData />
        <Wired />
      </Provider>,
    )
    // Toggle ON. RelativeData rewrites data values into percentages
    // (A=1000/1750 ≈ 57.14, B=500/1750 ≈ 28.57, C=250/1750 ≈ 14.29) AND
    // the composer wiring forces maxOverride=100 so the bar widths
    // match those percent values directly.
    fireEvent.click(screen.getByRole('button', { name: /relative|percent/i }))
    const fills = getBarFills()
    expect(fills).toHaveLength(3)
    // Allow a small rounding tolerance — the percent transform produces
    // floats, the bar math multiplies by 100 again.
    const a = parseFloat(fills[0]!.style.width)
    const b = parseFloat(fills[1]!.style.width)
    const c = parseFloat(fills[2]!.style.width)
    expect(a).toBeGreaterThan(55)
    expect(a).toBeLessThan(60)
    expect(b).toBeGreaterThan(27)
    expect(b).toBeLessThan(30)
    expect(c).toBeGreaterThan(13)
    expect(c).toBeLessThan(16)
    // The largest bar must be NOT 100% — that's the whole point of the
    // fix. Without the wiring, A would have been 100% (largest of the
    // percent series).
    expect(a).toBeLessThan(100)
  })

  it('toggling off again restores data-max scaling', () => {
    render(
      <Provider id='cat-rd-restore' data={DATA}>
        <RelativeData />
        <Wired />
      </Provider>,
    )
    const button = screen.getByRole('button', { name: /relative|percent/i })
    fireEvent.click(button) // on
    fireEvent.click(button) // off
    const fills = getBarFills()
    expect(fills[0]!.style.width).toBe('100%')
    expect(fills[1]!.style.width).toBe('50%')
    expect(fills[2]!.style.width).toBe('25%')
  })
})
