import {
  customElement,
  type TemplateResult,
  property,
  html,
  css,
  cssManager,
} from '@design.estate/dees-element';
import { DeesInputBase } from '../dees-input-base/dees-input-base.js';
import { demoFunc } from './dees-input-radiogroup.demo.js';
import { themeDefaultStyles } from '../../00theme.js';

declare global {
  interface HTMLElementTagNameMap {
    'dees-input-radiogroup': DeesInputRadiogroup;
  }
}

type RadioOption = string | { option: string; key: string; payload?: any };

@customElement('dees-input-radiogroup')
export class DeesInputRadiogroup extends DeesInputBase<string | object> {
  public static demo = demoFunc;
  public static demoGroup = 'Input';

  // INSTANCE

  @property({ type: Array })
  accessor options: RadioOption[] = [];

  @property()
  accessor selectedOption: string = '';

  @property({ type: String })
  accessor direction: 'vertical' | 'horizontal' = 'vertical';

  @property({ type: String, reflect: true })
  accessor validationState: 'valid' | 'invalid' | 'warn' | 'pending' = null;

  // Form compatibility
  public get value() {
    const option = this.getOptionByKey(this.selectedOption);
    if (typeof option === 'object' && option.payload !== undefined) {
      return option.payload;
    }
    return this.selectedOption;
  }

  public set value(val: string | any) {
    if (typeof val === 'string') {
      this.selectedOption = val;
    } else {
      // Try to find option by payload
      const option = this.options.find(opt => 
        typeof opt === 'object' && opt.payload === val
      );
      if (option && typeof option === 'object') {
        this.selectedOption = option.key;
      }
    }
  }

  public static styles = [
    themeDefaultStyles,
    ...DeesInputBase.baseStyles,
    cssManager.defaultStyles,
    css`
      /* TODO: Migrate hardcoded values to --dees-* CSS variables */
      * {
        box-sizing: border-box;
      }

      :host {
        display: block;
        position: relative;
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
      }

      .maincontainer {
        display: flex;
        flex-direction: column;
        gap: 10px;
      }

      .maincontainer.horizontal {
        flex-direction: row;
        flex-wrap: wrap;
        gap: 20px;
      }

      .radio-option {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 6px 0;
        cursor: pointer;
        transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
        user-select: none;
        position: relative;
        border-radius: 4px;
      }

      .maincontainer.horizontal .radio-option {
        padding: 6px 20px 6px 0;
      }

      .radio-option:hover .radio-circle {
        border-color: ${cssManager.bdTheme('hsl(215 20.2% 65.1%)', 'hsl(215 20.2% 35.1%)')};
        background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(215 20.2% 11.8%)')};
      }

      .radio-option:hover .radio-label {
        color: ${cssManager.bdTheme('hsl(215.3 25% 8.8%)', 'hsl(210 40% 98%)')};
      }

      .radio-circle {
        width: 20px;
        height: 20px;
        border-radius: 50%;
        border: 2px solid ${cssManager.bdTheme('hsl(215 20.2% 65.1%)', 'hsl(215 20.2% 35.1%)')};
        background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(215 30% 6.8%)')};
        transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
        position: relative;
        flex-shrink: 0;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .radio-option.selected .radio-circle {
        border-color: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
        background: ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
      }

      .radio-option.selected .radio-circle::after {
        content: '';
        position: absolute;
        width: 8px;
        height: 8px;
        border-radius: 50%;
        background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(215 30% 6.8%)')};
        transform: scale(0);
        transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
      }

      .radio-option.selected .radio-circle::after {
        transform: scale(1);
      }

      .radio-circle:focus-visible {
        outline: none;
        box-shadow: 0 0 0 2px ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(215 30% 3.9%)')},
                    0 0 0 4px ${cssManager.bdTheme('hsl(217.2 91.2% 59.8%)', 'hsl(213.1 93.9% 67.8%)')};
      }

      .radio-label {
        font-size: 14px;
        font-weight: 500;
        color: ${cssManager.bdTheme('hsl(215.3 25% 26.7%)', 'hsl(217.9 10.6% 74.9%)')};
        transition: color 0.2s cubic-bezier(0.4, 0, 0.2, 1);
        letter-spacing: -0.006em;
        line-height: 20px;
      }

      .radio-option.selected .radio-label {
        color: ${cssManager.bdTheme('hsl(215.3 25% 8.8%)', 'hsl(210 40% 98%)')};
      }

      :host([disabled]) .radio-option {
        cursor: not-allowed;
        opacity: 0.5;
      }

      :host([disabled]) .radio-option:hover .radio-circle {
        border-color: ${cssManager.bdTheme('hsl(215 20.2% 65.1%)', 'hsl(215 20.2% 35.1%)')};
        background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(215 30% 6.8%)')};
      }

      :host([disabled]) .radio-option:hover .radio-label {
        color: ${cssManager.bdTheme('hsl(215.3 25% 26.7%)', 'hsl(217.9 10.6% 74.9%)')};
      }

      .label-text {
        font-size: 14px;
        font-weight: 500;
        color: ${cssManager.bdTheme('hsl(215.3 25% 8.8%)', 'hsl(210 40% 98%)')};
        margin-bottom: 10px;
        letter-spacing: -0.006em;
        line-height: 20px;
      }

      .description-text {
        font-size: 13px;
        color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
        margin-top: 10px;
        line-height: 1.5;
        letter-spacing: -0.003em;
      }

      /* Validation styles */
      :host([validationState="invalid"]) .radio-circle {
        border-color: ${cssManager.bdTheme('hsl(0 72.2% 50.6%)', 'hsl(0 62.8% 30.6%)')};
      }

      :host([validationState="invalid"]) .radio-option.selected .radio-circle {
        border-color: ${cssManager.bdTheme('hsl(0 72.2% 50.6%)', 'hsl(0 62.8% 30.6%)')};
        background: ${cssManager.bdTheme('hsl(0 72.2% 50.6%)', 'hsl(0 62.8% 30.6%)')};
      }

      :host([validationState="valid"]) .radio-option.selected .radio-circle {
        border-color: ${cssManager.bdTheme('hsl(142.1 70.6% 45.3%)', 'hsl(142.1 76.2% 36.3%)')};
        background: ${cssManager.bdTheme('hsl(142.1 70.6% 45.3%)', 'hsl(142.1 76.2% 36.3%)')};
      }

      :host([validationState="warn"]) .radio-option.selected .radio-circle {
        border-color: ${cssManager.bdTheme('hsl(45.4 93.4% 47.5%)', 'hsl(45.4 93.4% 47.5%)')};
        background: ${cssManager.bdTheme('hsl(45.4 93.4% 47.5%)', 'hsl(45.4 93.4% 47.5%)')};
      }

      /* Override base grid layout for radiogroup to prevent large gaps */
      :host([label-position="left"]) .input-wrapper {
        grid-template-columns: auto auto;
      }

      :host([label-position="right"]) .input-wrapper {
        grid-template-columns: auto auto;
      }
    `,
  ];

  public render(): TemplateResult {
    return html`
      <div class="input-wrapper">
        ${this.label ? html`<div class="label-text">${this.label}</div>` : ''}
        <div class="maincontainer ${this.direction}">
          ${this.options.map((option) => {
            const optionKey = this.getOptionKey(option);
            const optionLabel = this.getOptionLabel(option);
            const isSelected = this.selectedOption === optionKey;
            
            return html`
              <div 
                class="radio-option ${isSelected ? 'selected' : ''}"
                @click="${() => this.selectOption(optionKey)}"
                @keydown="${(e: KeyboardEvent) => this.handleKeydown(e, optionKey)}"
              >
                <div 
                  class="radio-circle" 
                  tabindex="${this.disabled ? '-1' : '0'}"
                  role="radio"
                  aria-checked="${isSelected}"
                  aria-label="${optionLabel}"
                ></div>
                <div class="radio-label">${optionLabel}</div>
              </div>
            `;
          })}
        </div>
        ${this.description ? html`<div class="description-text">${this.description}</div>` : ''}
      </div>
    `;
  }

  private getOptionKey(option: RadioOption): string {
    if (typeof option === 'string') {
      return option;
    }
    return option.key;
  }

  private getOptionLabel(option: RadioOption): string {
    if (typeof option === 'string') {
      return option;
    }
    return option.option;
  }

  private getOptionByKey(key: string): RadioOption | undefined {
    return this.options.find(opt => this.getOptionKey(opt) === key);
  }

  private selectOption(key: string): void {
    if (this.disabled) {
      return;
    }

    const oldValue = this.selectedOption;
    this.selectedOption = key;

    if (oldValue !== key) {
      this.dispatchEvent(new CustomEvent('change', {
        detail: { value: this.value },
        bubbles: true,
        composed: true,
      }));
      
      this.dispatchEvent(new CustomEvent('input', {
        detail: { value: this.value },
        bubbles: true,
        composed: true,
      }));
      
      this.changeSubject.next(this);
    }
  }

  public getValue(): string | any {
    return this.value;
  }

  public setValue(val: string | any): void {
    this.value = val;
  }

  public async validate(): Promise<boolean> {
    if (this.required && !this.selectedOption) {
      this.validationState = 'invalid';
      return false;
    }
    
    this.validationState = 'valid';
    return true;
  }

  public async firstUpdated() {
    // Auto-select first option if none selected and not required
    if (!this.selectedOption && this.options.length > 0 && !this.required) {
      const firstOption = this.options[0];
      this.selectedOption = this.getOptionKey(firstOption);
    }
  }

  private handleKeydown(event: KeyboardEvent, optionKey: string) {
    if (this.disabled) return;
    
    if (event.key === ' ' || event.key === 'Enter') {
      event.preventDefault();
      this.selectOption(optionKey);
    } else if (event.key === 'ArrowDown' || event.key === 'ArrowRight') {
      event.preventDefault();
      this.focusNextOption();
    } else if (event.key === 'ArrowUp' || event.key === 'ArrowLeft') {
      event.preventDefault();
      this.focusPreviousOption();
    }
  }

  private focusNextOption() {
    const radioCircles = Array.from(this.shadowRoot.querySelectorAll('.radio-circle'));
    const currentIndex = radioCircles.findIndex(el => el === this.shadowRoot.activeElement);
    const nextIndex = (currentIndex + 1) % radioCircles.length;
    (radioCircles[nextIndex] as HTMLElement).focus();
  }

  private focusPreviousOption() {
    const radioCircles = Array.from(this.shadowRoot.querySelectorAll('.radio-circle'));
    const currentIndex = radioCircles.findIndex(el => el === this.shadowRoot.activeElement);
    const prevIndex = currentIndex <= 0 ? radioCircles.length - 1 : currentIndex - 1;
    (radioCircles[prevIndex] as HTMLElement).focus();
  }
}