import { createInjector } from '@furystack/inject'
import { createComponent, flushUpdates, initializeShadeRoot } from '@furystack/shades'
import { usingAsync } from '@furystack/utils'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import {
  ButtonGroup,
  SegmentedControl,
  ToggleButton,
  ToggleButtonGroup,
  type SegmentedControlOption,
} from './button-group.js'
import { Button } from './button.js'

describe('ButtonGroup', () => {
  beforeEach(() => {
    document.body.innerHTML = '<div id="root"></div>'
  })

  afterEach(() => {
    document.body.innerHTML = ''
  })

  const renderButtonGroup = async (props: Parameters<typeof ButtonGroup>[0] = {}, children?: JSX.Element[]) => {
    const injector = createInjector()
    const root = document.getElementById('root')!
    initializeShadeRoot({
      injector,
      rootElement: root,
      jsxElement: <ButtonGroup {...props}>{children}</ButtonGroup>,
    })
    await flushUpdates()
    return {
      injector,
      group: root.querySelector('shade-button-group') as HTMLElement,
      [Symbol.asyncDispose]: () => injector[Symbol.asyncDispose](),
    }
  }

  describe('rendering', () => {
    it('should render a button group element', async () => {
      await usingAsync(await renderButtonGroup(), async ({ group }) => {
        expect(group).toBeTruthy()
        expect(group.tagName.toLowerCase()).toBe('shade-button-group')
      })
    })

    it('should have role="group"', async () => {
      await usingAsync(await renderButtonGroup(), async ({ group }) => {
        expect(group.getAttribute('role')).toBe('group')
      })
    })

    it('should render children', async () => {
      await usingAsync(
        await renderButtonGroup({}, [<Button>First</Button>, <Button>Second</Button>]),
        async ({ group }) => {
          const buttons = group.querySelectorAll('button[is="shade-button"]')
          expect(buttons.length).toBe(2)
        },
      )
    })
  })

  describe('orientation', () => {
    it('should default to horizontal orientation', async () => {
      await usingAsync(await renderButtonGroup(), async ({ group }) => {
        expect(group.getAttribute('data-orientation')).toBe('horizontal')
      })
    })

    it('should support vertical orientation', async () => {
      await usingAsync(await renderButtonGroup({ orientation: 'vertical' }), async ({ group }) => {
        expect(group.getAttribute('data-orientation')).toBe('vertical')
      })
    })
  })

  describe('variant', () => {
    it('should not set data-variant when variant is not specified', async () => {
      await usingAsync(await renderButtonGroup(), async ({ group }) => {
        expect(group.getAttribute('data-variant')).toBeNull()
      })
    })

    it('should set data-variant for contained', async () => {
      await usingAsync(await renderButtonGroup({ variant: 'contained' }), async ({ group }) => {
        expect(group.getAttribute('data-variant')).toBe('contained')
      })
    })

    it('should set data-variant for outlined', async () => {
      await usingAsync(await renderButtonGroup({ variant: 'outlined' }), async ({ group }) => {
        expect(group.getAttribute('data-variant')).toBe('outlined')
      })
    })
  })

  describe('color', () => {
    it('should not set data-color when color is not specified', async () => {
      await usingAsync(await renderButtonGroup(), async ({ group }) => {
        expect(group.getAttribute('data-color')).toBeNull()
      })
    })

    it('should set data-color for primary', async () => {
      await usingAsync(await renderButtonGroup({ color: 'primary' }), async ({ group }) => {
        expect(group.getAttribute('data-color')).toBe('primary')
      })
    })
  })

  describe('disabled', () => {
    it('should not set data-disabled when not disabled', async () => {
      await usingAsync(await renderButtonGroup(), async ({ group }) => {
        expect(group.hasAttribute('data-disabled')).toBe(false)
      })
    })

    it('should set data-disabled when disabled', async () => {
      await usingAsync(await renderButtonGroup({ disabled: true }), async ({ group }) => {
        expect(group.hasAttribute('data-disabled')).toBe(true)
      })
    })
  })

  describe('custom styles', () => {
    it('should apply custom styles', async () => {
      await usingAsync(await renderButtonGroup({ style: { gap: '4px' } }), async ({ group }) => {
        expect(group.style.gap).toBe('4px')
      })
    })
  })
})

describe('ToggleButton', () => {
  beforeEach(() => {
    document.body.innerHTML = '<div id="root"></div>'
  })

  afterEach(() => {
    document.body.innerHTML = ''
  })

  const renderToggleButton = async (props: Parameters<typeof ToggleButton>[0]) => {
    const injector = createInjector()
    const root = document.getElementById('root')!
    initializeShadeRoot({
      injector,
      rootElement: root,
      jsxElement: <ToggleButton {...props}>Label</ToggleButton>,
    })
    await flushUpdates()
    return {
      injector,
      button: root.querySelector('button[is="shade-toggle-button"]') as HTMLButtonElement,
      [Symbol.asyncDispose]: () => injector[Symbol.asyncDispose](),
    }
  }

  describe('pressed', () => {
    it('should not set data-selected when pressed is not specified', async () => {
      await usingAsync(await renderToggleButton({ value: 'a' }), async ({ button }) => {
        expect(button.hasAttribute('data-selected')).toBe(false)
      })
    })

    it('should set data-selected when pressed is true', async () => {
      await usingAsync(await renderToggleButton({ value: 'a', pressed: true }), async ({ button }) => {
        expect(button.hasAttribute('data-selected')).toBe(true)
      })
    })

    it('should not set data-selected when pressed is false', async () => {
      await usingAsync(await renderToggleButton({ value: 'a', pressed: false }), async ({ button }) => {
        expect(button.hasAttribute('data-selected')).toBe(false)
      })
    })
  })

  describe('size', () => {
    it('should not set data-size by default', async () => {
      await usingAsync(await renderToggleButton({ value: 'a' }), async ({ button }) => {
        expect(button.hasAttribute('data-size')).toBe(false)
      })
    })

    it('should not set data-size for medium (default)', async () => {
      await usingAsync(await renderToggleButton({ value: 'a', size: 'medium' }), async ({ button }) => {
        expect(button.hasAttribute('data-size')).toBe(false)
      })
    })

    it('should set data-size="small" for small size', async () => {
      await usingAsync(await renderToggleButton({ value: 'a', size: 'small' }), async ({ button }) => {
        expect(button.getAttribute('data-size')).toBe('small')
      })
    })

    it('should set data-size="large" for large size', async () => {
      await usingAsync(await renderToggleButton({ value: 'a', size: 'large' }), async ({ button }) => {
        expect(button.getAttribute('data-size')).toBe('large')
      })
    })
  })
})

describe('ToggleButtonGroup', () => {
  beforeEach(() => {
    document.body.innerHTML = '<div id="root"></div>'
  })

  afterEach(() => {
    document.body.innerHTML = ''
  })

  const renderToggleGroup = async (props: Parameters<typeof ToggleButtonGroup>[0] = {}, children?: JSX.Element[]) => {
    const injector = createInjector()
    const root = document.getElementById('root')!
    initializeShadeRoot({
      injector,
      rootElement: root,
      jsxElement: <ToggleButtonGroup {...props}>{children}</ToggleButtonGroup>,
    })
    await flushUpdates()
    return {
      injector,
      group: root.querySelector('shade-toggle-button-group') as HTMLElement,
      [Symbol.asyncDispose]: () => injector[Symbol.asyncDispose](),
    }
  }

  describe('rendering', () => {
    it('should render a toggle button group', async () => {
      await usingAsync(await renderToggleGroup(), async ({ group }) => {
        expect(group).toBeTruthy()
        expect(group.getAttribute('role')).toBe('group')
      })
    })

    it('should render toggle button children', async () => {
      await usingAsync(
        await renderToggleGroup({}, [
          <ToggleButton value="a">A</ToggleButton>,
          <ToggleButton value="b">B</ToggleButton>,
          <ToggleButton value="c">C</ToggleButton>,
        ]),
        async ({ group }) => {
          const buttons = group.querySelectorAll('button[data-value]')
          expect(buttons.length).toBe(3)
        },
      )
    })
  })

  describe('exclusive mode', () => {
    it('should call onValueChange with clicked value in exclusive mode', async () => {
      const handleChange = vi.fn()
      await usingAsync(
        await renderToggleGroup({ exclusive: true, value: '', onValueChange: handleChange }, [
          <ToggleButton value="left">Left</ToggleButton>,
          <ToggleButton value="center">Center</ToggleButton>,
          <ToggleButton value="right">Right</ToggleButton>,
        ]),
        async ({ group }) => {
          const centerBtn = group.querySelector('button[data-value="center"]') as HTMLButtonElement
          centerBtn.click()
          expect(handleChange).toHaveBeenCalledWith('center')
        },
      )
    })

    it('should deselect in exclusive mode when clicking the already selected value', async () => {
      const handleChange = vi.fn()
      await usingAsync(
        await renderToggleGroup({ exclusive: true, value: 'center', onValueChange: handleChange }, [
          <ToggleButton value="left">Left</ToggleButton>,
          <ToggleButton value="center">Center</ToggleButton>,
          <ToggleButton value="right">Right</ToggleButton>,
        ]),
        async ({ group }) => {
          const centerBtn = group.querySelector('button[data-value="center"]') as HTMLButtonElement
          centerBtn.click()
          expect(handleChange).toHaveBeenCalledWith('')
        },
      )
    })
  })

  describe('multi-select mode', () => {
    it('should add value to selection in multi-select mode', async () => {
      const handleChange = vi.fn()
      await usingAsync(
        await renderToggleGroup({ value: ['bold'], onValueChange: handleChange }, [
          <ToggleButton value="bold">B</ToggleButton>,
          <ToggleButton value="italic">I</ToggleButton>,
          <ToggleButton value="underline">U</ToggleButton>,
        ]),
        async ({ group }) => {
          const italicBtn = group.querySelector('button[data-value="italic"]') as HTMLButtonElement
          italicBtn.click()
          expect(handleChange).toHaveBeenCalledWith(['bold', 'italic'])
        },
      )
    })

    it('should remove value from selection in multi-select mode', async () => {
      const handleChange = vi.fn()
      await usingAsync(
        await renderToggleGroup({ value: ['bold', 'italic'], onValueChange: handleChange }, [
          <ToggleButton value="bold">B</ToggleButton>,
          <ToggleButton value="italic">I</ToggleButton>,
          <ToggleButton value="underline">U</ToggleButton>,
        ]),
        async ({ group }) => {
          const boldBtn = group.querySelector('button[data-value="bold"]') as HTMLButtonElement
          boldBtn.click()
          expect(handleChange).toHaveBeenCalledWith(['italic'])
        },
      )
    })
  })

  describe('selected state', () => {
    it('should mark the selected button with data-selected in exclusive mode', async () => {
      await usingAsync(
        await renderToggleGroup({ exclusive: true, value: 'center' }, [
          <ToggleButton value="left">Left</ToggleButton>,
          <ToggleButton value="center">Center</ToggleButton>,
          <ToggleButton value="right">Right</ToggleButton>,
        ]),
        async ({ group }) => {
          await flushUpdates()
          await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
          const centerBtn = group.querySelector('button[data-value="center"]') as HTMLButtonElement
          const leftBtn = group.querySelector('button[data-value="left"]') as HTMLButtonElement
          expect(centerBtn.hasAttribute('data-selected')).toBe(true)
          expect(leftBtn.hasAttribute('data-selected')).toBe(false)
        },
      )
    })

    it('should mark multiple selected buttons in multi-select mode', async () => {
      await usingAsync(
        await renderToggleGroup({ value: ['bold', 'underline'] }, [
          <ToggleButton value="bold">B</ToggleButton>,
          <ToggleButton value="italic">I</ToggleButton>,
          <ToggleButton value="underline">U</ToggleButton>,
        ]),
        async ({ group }) => {
          await flushUpdates()
          await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
          const boldBtn = group.querySelector('button[data-value="bold"]') as HTMLButtonElement
          const italicBtn = group.querySelector('button[data-value="italic"]') as HTMLButtonElement
          const underlineBtn = group.querySelector('button[data-value="underline"]') as HTMLButtonElement
          expect(boldBtn.hasAttribute('data-selected')).toBe(true)
          expect(italicBtn.hasAttribute('data-selected')).toBe(false)
          expect(underlineBtn.hasAttribute('data-selected')).toBe(true)
        },
      )
    })
  })

  describe('orientation', () => {
    it('should default to horizontal', async () => {
      await usingAsync(await renderToggleGroup(), async ({ group }) => {
        expect(group.getAttribute('data-orientation')).toBe('horizontal')
      })
    })

    it('should support vertical', async () => {
      await usingAsync(await renderToggleGroup({ orientation: 'vertical' }), async ({ group }) => {
        expect(group.getAttribute('data-orientation')).toBe('vertical')
      })
    })
  })

  describe('color', () => {
    it('should set default color CSS variable when no color specified', async () => {
      await usingAsync(await renderToggleGroup(), async ({ group }) => {
        expect(group.style.getPropertyValue('--toggle-color-main')).toBe('var(--shades-theme-text-secondary)')
      })
    })

    it('should set color CSS variable for a palette color', async () => {
      await usingAsync(await renderToggleGroup({ color: 'primary' }), async ({ group }) => {
        expect(group.style.getPropertyValue('--toggle-color-main')).toBe('var(--shades-theme-palette-primary-main)')
      })
    })
  })

  describe('size', () => {
    it('should not set data-size on children by default', async () => {
      await usingAsync(
        await renderToggleGroup({}, [
          <ToggleButton value="a">A</ToggleButton>,
          <ToggleButton value="b">B</ToggleButton>,
        ]),
        async ({ group }) => {
          await flushUpdates()
          await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
          const buttons = group.querySelectorAll('button[data-value]')
          buttons.forEach((btn) => {
            expect(btn.hasAttribute('data-size')).toBe(false)
          })
        },
      )
    })

    it('should propagate size="small" to child buttons', async () => {
      await usingAsync(
        await renderToggleGroup({ size: 'small' }, [
          <ToggleButton value="a">A</ToggleButton>,
          <ToggleButton value="b">B</ToggleButton>,
        ]),
        async ({ group }) => {
          await flushUpdates()
          await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
          const buttons = group.querySelectorAll('button[data-value]')
          buttons.forEach((btn) => {
            expect(btn.getAttribute('data-size')).toBe('small')
          })
        },
      )
    })

    it('should propagate size="large" to child buttons', async () => {
      await usingAsync(
        await renderToggleGroup({ size: 'large' }, [
          <ToggleButton value="a">A</ToggleButton>,
          <ToggleButton value="b">B</ToggleButton>,
        ]),
        async ({ group }) => {
          await flushUpdates()
          await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
          const buttons = group.querySelectorAll('button[data-value]')
          buttons.forEach((btn) => {
            expect(btn.getAttribute('data-size')).toBe('large')
          })
        },
      )
    })

    it('should remove data-size when size is medium', async () => {
      await usingAsync(
        await renderToggleGroup({ size: 'medium' }, [
          <ToggleButton value="a" size="small">
            A
          </ToggleButton>,
        ]),
        async ({ group }) => {
          await flushUpdates()
          await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
          const btn = group.querySelector('button[data-value]')
          expect(btn?.hasAttribute('data-size')).toBe(false)
        },
      )
    })
  })
})

describe('SegmentedControl', () => {
  beforeEach(() => {
    document.body.innerHTML = '<div id="root"></div>'
  })

  afterEach(() => {
    document.body.innerHTML = ''
  })

  const defaultOptions: SegmentedControlOption[] = [
    { value: 'daily', label: 'Daily' },
    { value: 'weekly', label: 'Weekly' },
    { value: 'monthly', label: 'Monthly' },
  ]

  const renderSegmented = async (props: Partial<Parameters<typeof SegmentedControl>[0]> = {}) => {
    const injector = createInjector()
    const root = document.getElementById('root')!
    initializeShadeRoot({
      injector,
      rootElement: root,
      jsxElement: <SegmentedControl options={defaultOptions} {...props} />,
    })
    await flushUpdates()
    return {
      injector,
      control: root.querySelector('shade-segmented-control') as HTMLElement,
      [Symbol.asyncDispose]: () => injector[Symbol.asyncDispose](),
    }
  }

  describe('rendering', () => {
    it('should render a segmented control', async () => {
      await usingAsync(await renderSegmented(), async ({ control }) => {
        expect(control).toBeTruthy()
        expect(control.getAttribute('role')).toBe('radiogroup')
      })
    })

    it('should render all options as buttons', async () => {
      await usingAsync(await renderSegmented(), async ({ control }) => {
        const buttons = control.querySelectorAll('.segmented-option')
        expect(buttons.length).toBe(3)
      })
    })

    it('should render option labels', async () => {
      await usingAsync(await renderSegmented(), async ({ control }) => {
        const buttons = control.querySelectorAll('.segmented-option')
        expect(buttons[0].textContent).toContain('Daily')
        expect(buttons[1].textContent).toContain('Weekly')
        expect(buttons[2].textContent).toContain('Monthly')
      })
    })
  })

  describe('selection', () => {
    it('should mark the selected option with data-selected', async () => {
      await usingAsync(await renderSegmented({ value: 'weekly' }), async ({ control }) => {
        const buttons = control.querySelectorAll('.segmented-option')
        expect(buttons[0].hasAttribute('data-selected')).toBe(false)
        expect(buttons[1].hasAttribute('data-selected')).toBe(true)
        expect(buttons[2].hasAttribute('data-selected')).toBe(false)
      })
    })

    it('should set aria-checked on the selected option', async () => {
      await usingAsync(await renderSegmented({ value: 'daily' }), async ({ control }) => {
        const buttons = control.querySelectorAll('.segmented-option')
        expect(buttons[0].getAttribute('aria-checked')).toBe('true')
        expect(buttons[1].getAttribute('aria-checked')).toBe('false')
      })
    })

    it('should call onValueChange when an option is clicked', async () => {
      const handleChange = vi.fn()
      await usingAsync(await renderSegmented({ value: 'daily', onValueChange: handleChange }), async ({ control }) => {
        const monthlyBtn = control.querySelectorAll('.segmented-option')[2] as HTMLButtonElement
        monthlyBtn.click()
        expect(handleChange).toHaveBeenCalledWith('monthly')
      })
    })

    it('should not call onValueChange when clicking the already selected option', async () => {
      const handleChange = vi.fn()
      await usingAsync(await renderSegmented({ value: 'daily', onValueChange: handleChange }), async ({ control }) => {
        const dailyBtn = control.querySelectorAll('.segmented-option')[0] as HTMLButtonElement
        dailyBtn.click()
        expect(handleChange).not.toHaveBeenCalled()
      })
    })
  })

  describe('disabled', () => {
    it('should disable all options when disabled', async () => {
      await usingAsync(await renderSegmented({ disabled: true }), async ({ control }) => {
        const buttons = control.querySelectorAll('.segmented-option')
        expect(buttons.length).toBe(3)
        buttons.forEach((btn) => {
          expect((btn as HTMLButtonElement).disabled).toBe(true)
        })
      })
    })

    it('should disable individual options', async () => {
      const options: SegmentedControlOption[] = [
        { value: 'a', label: 'A' },
        { value: 'b', label: 'B', disabled: true },
        { value: 'c', label: 'C' },
      ]
      await usingAsync(await renderSegmented({ options }), async ({ control }) => {
        const buttons = control.querySelectorAll('.segmented-option')
        expect((buttons[0] as HTMLButtonElement).disabled).toBe(false)
        expect((buttons[1] as HTMLButtonElement).disabled).toBe(true)
        expect((buttons[2] as HTMLButtonElement).disabled).toBe(false)
      })
    })

    it('should not call onValueChange when a disabled option is clicked', async () => {
      const handleChange = vi.fn()
      const options: SegmentedControlOption[] = [
        { value: 'a', label: 'A' },
        { value: 'b', label: 'B', disabled: true },
      ]
      await usingAsync(await renderSegmented({ options, onValueChange: handleChange }), async ({ control }) => {
        const disabledBtn = control.querySelectorAll('.segmented-option')[1] as HTMLButtonElement
        disabledBtn.click()
        expect(handleChange).not.toHaveBeenCalled()
      })
    })
  })

  describe('size', () => {
    it('should not set data-size by default', async () => {
      await usingAsync(await renderSegmented(), async ({ control }) => {
        expect(control.hasAttribute('data-size')).toBe(false)
      })
    })

    it('should set data-size="small" for small size', async () => {
      await usingAsync(await renderSegmented({ size: 'small' }), async ({ control }) => {
        expect(control.getAttribute('data-size')).toBe('small')
      })
    })

    it('should set data-size="large" for large size', async () => {
      await usingAsync(await renderSegmented({ size: 'large' }), async ({ control }) => {
        expect(control.getAttribute('data-size')).toBe('large')
      })
    })
  })

  describe('color', () => {
    it('should set default primary color CSS variable', async () => {
      await usingAsync(await renderSegmented(), async ({ control }) => {
        expect(control.style.getPropertyValue('--seg-color-main')).toBe('var(--shades-theme-palette-primary-main)')
      })
    })

    it('should set color CSS variable for a palette color', async () => {
      await usingAsync(await renderSegmented({ color: 'secondary' }), async ({ control }) => {
        expect(control.style.getPropertyValue('--seg-color-main')).toBe('var(--shades-theme-palette-secondary-main)')
      })
    })
  })

  describe('custom styles', () => {
    it('should apply custom styles', async () => {
      await usingAsync(await renderSegmented({ style: { margin: '10px' } }), async ({ control }) => {
        expect(control.style.margin).toBe('10px')
      })
    })
  })
})

describe('ToggleButtonGroup edge cases', () => {
  beforeEach(() => {
    document.body.innerHTML = '<div id="root"></div>'
  })

  afterEach(() => {
    document.body.innerHTML = ''
  })

  const renderToggleGroup = async (props: Parameters<typeof ToggleButtonGroup>[0] = {}, children?: JSX.Element[]) => {
    const injector = createInjector()
    const root = document.getElementById('root')!
    initializeShadeRoot({
      injector,
      rootElement: root,
      jsxElement: <ToggleButtonGroup {...props}>{children}</ToggleButtonGroup>,
    })
    await flushUpdates()
    return {
      injector,
      group: root.querySelector('shade-toggle-button-group') as HTMLElement,
      [Symbol.asyncDispose]: () => injector[Symbol.asyncDispose](),
    }
  }

  it('should handle string value for multi-select (non-array)', async () => {
    const handleChange = vi.fn()
    await usingAsync(
      await renderToggleGroup({ value: 'bold', onValueChange: handleChange }, [
        <ToggleButton value="bold">B</ToggleButton>,
        <ToggleButton value="italic">I</ToggleButton>,
      ]),
      async ({ group }) => {
        const italicBtn = group.querySelector('button[data-value="italic"]') as HTMLButtonElement
        italicBtn.click()
        expect(handleChange).toHaveBeenCalledWith(['bold', 'italic'])
      },
    )
  })

  it('should handle empty value for multi-select', async () => {
    const handleChange = vi.fn()
    await usingAsync(
      await renderToggleGroup({ value: undefined, onValueChange: handleChange }, [
        <ToggleButton value="bold">B</ToggleButton>,
      ]),
      async ({ group }) => {
        const boldBtn = group.querySelector('button[data-value="bold"]') as HTMLButtonElement
        boldBtn.click()
        expect(handleChange).toHaveBeenCalledWith(['bold'])
      },
    )
  })

  it('should handle exclusive mode with array value', async () => {
    const handleChange = vi.fn()
    await usingAsync(
      await renderToggleGroup({ exclusive: true, value: ['center'], onValueChange: handleChange }, [
        <ToggleButton value="left">Left</ToggleButton>,
        <ToggleButton value="center">Center</ToggleButton>,
      ]),
      async ({ group }) => {
        const leftBtn = group.querySelector('button[data-value="left"]') as HTMLButtonElement
        leftBtn.click()
        expect(handleChange).toHaveBeenCalledWith('left')
      },
    )
  })

  it('should not call onValueChange when clicking a disabled button', async () => {
    const handleChange = vi.fn()
    await usingAsync(
      await renderToggleGroup({ exclusive: true, value: '', onValueChange: handleChange }, [
        <ToggleButton value="a" disabled>
          A
        </ToggleButton>,
      ]),
      async ({ group }) => {
        const btn = group.querySelector('button[data-value="a"]') as HTMLButtonElement
        btn.click()
        expect(handleChange).not.toHaveBeenCalled()
      },
    )
  })

  it('should disable all toggle buttons when group disabled is true', async () => {
    await usingAsync(
      await renderToggleGroup({ disabled: true }, [
        <ToggleButton value="a">A</ToggleButton>,
        <ToggleButton value="b">B</ToggleButton>,
      ]),
      async ({ group }) => {
        await flushUpdates()
        await new Promise<void>((resolve) => requestAnimationFrame(() => resolve()))
        const buttons = group.querySelectorAll('button[data-value]')
        buttons.forEach((btn) => {
          expect(btn.hasAttribute('disabled')).toBe(true)
        })
      },
    )
  })

  it('should apply vertical orientation border radius via CSS', async () => {
    await usingAsync(
      await renderToggleGroup({ orientation: 'vertical' }, [
        <ToggleButton value="a">A</ToggleButton>,
        <ToggleButton value="b">B</ToggleButton>,
      ]),
      async ({ group }) => {
        await flushUpdates()
        // Border-radius is now applied via CSS rules targeting
        // button:first-of-type / button:last-of-type within the group.
        // Verify the host has the correct orientation data attribute
        // that the CSS selectors depend on.
        expect(group.getAttribute('data-orientation')).toBe('vertical')
        const buttons = group.querySelectorAll('button[data-value]')
        expect(buttons.length).toBe(2)
      },
    )
  })

  it('should apply custom style', async () => {
    await usingAsync(await renderToggleGroup({ style: { gap: '8px' } }), async ({ group }) => {
      expect(group.style.gap).toBe('8px')
    })
  })
})
