import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, forwardRef, ContentChildren, QueryList, AfterContentInit, OnDestroy, signal } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { Subject, takeUntil } from 'rxjs';
import { RadioButtonComponent, RadioButtonSize, RadioButtonVariant, RadioButtonState, RadioButtonData } from './radio-button.component';

export type RadioGroupOrientation = 'horizontal' | 'vertical';

@Component({
  selector: 'ui-radio-group',
  standalone: true,
  changeDetection: ChangeDetectionStrategy.OnPush,
  imports: [CommonModule, RadioButtonComponent],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => RadioGroupComponent),
      multi: true
    }
  ],
  template: `
    <div class="radio-group-wrapper" [class]="getWrapperClasses()">
      @if (label) {
        <div class="radio-group__label" [class.radio-group__label--required]="required">
          {{ label }}
          @if (required) {
            <span class="radio-group__required-indicator">*</span>
          }
        </div>
      }
      
      <div class="radio-group" [class]="getGroupClasses()" role="radiogroup" [attr.aria-labelledby]="label ? groupId + '-label' : null">
        @if (options && options.length > 0) {
          @for (option of options; track option.value) {
            <ui-radio-button
              [value]="option.value"
              [label]="option.label"
              [description]="option.description || ''"
              [name]="name || groupId"
              [size]="size"
              [variant]="variant"
              [disabled]="disabled || (option.disabled ?? false)"
              [radioId]="groupId + '-' + option.value"
              (selectionChange)="onSelectionChange($event)"
              (radioFocus)="onRadioFocus($event)"
              (radioBlur)="onRadioBlur($event)"
            />
          }
        } @else {
          <ng-content></ng-content>
        }
      </div>
      
      @if (helperText && !errorMessage) {
        <div class="radio-group__helper-text">{{ helperText }}</div>
      }
      
      @if (errorMessage) {
        <div class="radio-group__error-text">{{ errorMessage }}</div>
      }
    </div>
  `,
  styleUrls: ['./radio-group.component.scss']
})
export class RadioGroupComponent implements ControlValueAccessor, AfterContentInit, OnDestroy {
  @ContentChildren(RadioButtonComponent) radioButtons!: QueryList<RadioButtonComponent>;

  @Input() options: RadioButtonData[] = [];
  @Input() label: string = '';
  @Input() name: string = '';
  @Input() size: RadioButtonSize = 'md';
  @Input() variant: RadioButtonVariant = 'primary';
  @Input() state: RadioButtonState = 'default';
  @Input() orientation: RadioGroupOrientation = 'vertical';
  @Input() disabled = false;
  @Input() required = false;
  @Input() helperText: string = '';
  @Input() errorMessage: string = '';
  @Input() dense = false;
  @Input() groupId: string = `radio-group-${Math.random().toString(36).substr(2, 9)}`;

  @Output() selectionChange = new EventEmitter<string>();
  @Output() groupFocus = new EventEmitter<FocusEvent>();
  @Output() groupBlur = new EventEmitter<FocusEvent>();

  private selectedValue = signal<string>('');
  private destroy$ = new Subject<void>();

  // ControlValueAccessor implementation
  private onChange = (value: string) => {};
  private onTouched = () => {};

  ngAfterContentInit(): void {
    this.syncRadioButtons();
    
    // Listen for changes in radio buttons
    this.radioButtons.changes.pipe(takeUntil(this.destroy$)).subscribe(() => {
      this.syncRadioButtons();
    });
  }

  ngOnDestroy(): void {
    this.destroy$.next();
    this.destroy$.complete();
  }

  writeValue(value: string): void {
    this.selectedValue.set(value || '');
    this.syncRadioButtons();
  }

  registerOnChange(fn: (value: string) => void): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
    this.syncRadioButtons();
  }

  private syncRadioButtons(): void {
    if (this.radioButtons) {
      this.radioButtons.forEach(radio => {
        radio.name = this.name || this.groupId;
        radio.size = this.size;
        radio.variant = this.variant;
        radio.state = this.state;
        radio.writeValue(this.selectedValue());
        radio.setDisabledState(this.disabled);
        radio.registerOnChange(this.onChange);
        radio.registerOnTouched(this.onTouched);
      });
    }
  }

  getWrapperClasses(): string {
    const classes = [
      `radio-group-wrapper--${this.size}`,
      `radio-group-wrapper--${this.variant}`,
      `radio-group-wrapper--${this.state}`,
      `radio-group-wrapper--${this.orientation}`
    ];

    if (this.disabled) classes.push('radio-group-wrapper--disabled');
    if (this.dense) classes.push('radio-group-wrapper--dense');
    if (this.errorMessage) classes.push('radio-group-wrapper--error');

    return classes.join(' ');
  }

  getGroupClasses(): string {
    const classes = [
      `radio-group--${this.orientation}`
    ];

    if (this.dense) classes.push('radio-group--dense');

    return classes.join(' ');
  }

  onSelectionChange(value: string): void {
    this.selectedValue.set(value);
    this.onChange(value);
    this.selectionChange.emit(value);
    this.syncRadioButtons();
  }

  onRadioFocus(event: FocusEvent): void {
    this.groupFocus.emit(event);
  }

  onRadioBlur(event: FocusEvent): void {
    this.onTouched();
    this.groupBlur.emit(event);
  }
}