/**
 * CheckboxGroup - Groups multiple checkboxes with shared state management
 * @countermeasure/web-components/primitives/checkbox
 */

import { type CheckboxGroupConfig } from './types'
import { Checkbox } from './index'
import { resolveContainer, uniqueId } from '../utils'

export class CheckboxGroup {
  public readonly el: HTMLElement

  private readonly checkboxes: Checkbox[] = []
  private config: CheckboxGroupConfig
  private selectedValues: Set<string>
  private isDestroyed = false

  constructor(config: CheckboxGroupConfig) {
    this.config = config
    this.selectedValues = new Set(config.value ?? [])

    const orientation = config.orientation ?? 'vertical'

    this.el = document.createElement('div')
    this.el.className = `cmm-checkbox-group cmm-checkbox-group--${orientation}`
    this.el.setAttribute('role', 'group')
    this.el.id = uniqueId('cmm-checkbox-group')

    if (config.ariaLabel) {
      this.el.setAttribute('aria-label', config.ariaLabel)
    }

    if (config.className) {
      this.el.classList.add(config.className)
    }

    this.buildCheckboxes()

    if (config.container !== undefined) {
      const parent = resolveContainer(config.container)
      parent.appendChild(this.el)
    }
  }

  getValue(): string[] {
    return [...this.selectedValues]
  }

  setValue(values: string[]): void {
    this.selectedValues = new Set(values)
    this.syncCheckboxes()
  }

  setDisabled(disabled: boolean): void {
    for (const checkbox of this.checkboxes) {
      checkbox.setDisabled(disabled)
    }
  }

  destroy(): void {
    this.isDestroyed = true
    for (const checkbox of this.checkboxes) {
      checkbox.destroy()
    }
    this.checkboxes.length = 0
    this.el.remove()
  }

  private buildCheckboxes(): void {
    for (const checkbox of this.checkboxes) {
      checkbox.destroy()
    }
    this.checkboxes.length = 0

    for (const option of this.config.options) {
      const isChecked = this.selectedValues.has(option.value)
      const isDisabled = this.config.disabled === true || option.disabled === true

      const checkbox = new Checkbox({
        label: option.label,
        value: option.value,
        checked: isChecked,
        disabled: isDisabled,
        onChange: (checked: boolean) => {
          if (this.isDestroyed) {
            return
          }
          if (checked) {
            this.selectedValues.add(option.value)
          } else {
            this.selectedValues.delete(option.value)
          }
          this.config.onChange?.([...this.selectedValues])
        },
      })

      this.checkboxes.push(checkbox)
      this.el.appendChild(checkbox.el)
    }
  }

  private syncCheckboxes(): void {
    for (const checkbox of this.checkboxes) {
      const input = checkbox.el.querySelector('input')
      if (input !== null) {
        const value = input.value
        checkbox.setChecked(this.selectedValues.has(value))
      }
    }
  }
}

export { type CheckboxGroupConfig, type CheckboxGroupOption } from './types'
