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

import * as colors from '../../00colors.js'

import { demoFunc } from './dees-input-multitoggle.demo.js';
import { themeDefaultStyles } from '../../00theme.js';

declare global {
  interface HTMLElementTagNameMap {
    'dees-input-multitoggle': DeesInputMultitoggle;
  }
}

@customElement('dees-input-multitoggle')
export class DeesInputMultitoggle extends DeesInputBase<DeesInputMultitoggle> {
  public static demo = demoFunc;
  public static demoGroup = 'Input';


  @property()
  accessor type: 'boolean' | 'multi' | 'single' = 'multi';

  @property()
  accessor booleanTrueName: string = 'true';

  @property()
  accessor booleanFalseName: string = 'false';

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

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

  @property({ type: Boolean })
  accessor boolValue: boolean = false;

  // Add value property for form compatibility
  public get value(): string | boolean {
    if (this.type === 'boolean') {
      return this.selectedOption === this.booleanTrueName;
    }
    return this.selectedOption;
  }

  public set value(val: string | boolean) {
    if (this.type === 'boolean' && typeof val === 'boolean') {
      this.selectedOption = val ? this.booleanTrueName : this.booleanFalseName;
    } else {
      this.selectedOption = val as string;
    }
    this.requestUpdate();
    // Defer indicator update to next frame if component not yet updated
    if (this.hasUpdated) {
      requestAnimationFrame(() => {
        this.setIndicator();
      });
    }
  }

  public static styles = [
    themeDefaultStyles,
    ...DeesInputBase.baseStyles,
    cssManager.defaultStyles,
    css`
      /* TODO: Migrate hardcoded values to --dees-* CSS variables */
      :host {
        color: ${cssManager.bdTheme('#09090b', '#fafafa')};
        user-select: none;
      }

      .selections {
        position: relative;
        display: inline-flex;
        align-items: center;
        background: ${cssManager.bdTheme('#ffffff', '#18181b')};
        border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
        padding: 4px;
        border-radius: 8px;
        box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
      }

      .option {
        position: relative;
        padding: 8px 20px;
        border-radius: 6px;
        cursor: pointer;
        white-space: nowrap;
        transition: color 0.2s ease;
        font-size: 14px;
        font-weight: 500;
        color: ${cssManager.bdTheme('#71717a', '#71717a')};
        line-height: 1;
        z-index: 2;
      }

      .option:hover {
        color: ${cssManager.bdTheme('#18181b', '#e4e4e7')};
      }

      .option.selected {
        color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
      }

      .indicator {
        opacity: 0;
        position: absolute;
        height: calc(100% - 8px);
        top: 4px;
        border-radius: 6px;
        background: ${cssManager.bdTheme('rgba(59, 130, 246, 0.15)', 'rgba(59, 130, 246, 0.15)')};
        transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
        z-index: 1;
      }
      
      .indicator.no-transition {
        transition: none;
      }
      
      :host([disabled]) .selections {
        opacity: 0.5;
        cursor: not-allowed;
      }

      :host([disabled]) .option {
        cursor: not-allowed;
        pointer-events: none;
      }

      :host([disabled]) .indicator {
        background: ${cssManager.bdTheme('rgba(113, 113, 122, 0.15)', 'rgba(113, 113, 122, 0.15)')};
      }
    `,
  ];

  public render(): TemplateResult {
    return html`
      <div class="input-wrapper">
        <dees-label .label=${this.label} .description=${this.description}></dees-label>
        <div class="mainbox">
          <div class="selections">
          <div class="indicator"></div>
          ${this.options.map(
            (option) =>
              html`<div class="option ${option === this.selectedOption ? 'selected': ''}" @click=${() => this.handleSelection(option)}>
                ${option}
              </div> `
          )}
          </div>
        </div>
      </div>
    `;
  }

  public async connectedCallback() {
    await super.connectedCallback();
    // Initialize boolean options early
    if (this.type === 'boolean' && this.options.length === 0) {
      this.options = [this.booleanTrueName || 'true', this.booleanFalseName || 'false'];
      // Set default selection for boolean if not set
      if (!this.selectedOption) {
        this.selectedOption = this.booleanFalseName || 'false';
      }
    }
    // Set default selection to first option if not set
    if (!this.selectedOption && this.options.length > 0) {
      this.selectedOption = this.options[0];
    }
  }

  public async firstUpdated(_changedProperties: Map<string | number | symbol, unknown>) {
    super.firstUpdated(_changedProperties);
    // Update boolean options if they changed
    if (this.type === 'boolean') {
      this.options = [this.booleanTrueName || 'true', this.booleanFalseName || 'false'];
    }
    // Wait for the next frame to ensure DOM is fully rendered
    await this.updateComplete;
    
    // Wait for fonts to load
    if (document.fonts) {
      await document.fonts.ready;
    }
    
    // Wait one more frame after fonts are loaded
    await new Promise(resolve => requestAnimationFrame(resolve));
    
    // Now set the indicator
    this.setIndicator();
  }

  public async handleSelection(optionArg: string) {
    if (this.disabled) return;
    this.selectedOption = optionArg;
    this.requestUpdate();
    this.changeSubject.next(this);
    await this.updateComplete;
    this.setIndicator();
  }
  
  private indicatorInitialized = false;

  public async setIndicator() {
    const indicator: HTMLDivElement = this.shadowRoot.querySelector('.indicator');
    const selectedIndex = this.options.indexOf(this.selectedOption);
    
    // If no valid selection, hide indicator
    if (selectedIndex === -1 || !indicator) {
      if (indicator) {
        indicator.style.opacity = '0';
      }
      return;
    }
    
    const option: HTMLDivElement = this.shadowRoot.querySelector(
      `.option:nth-child(${selectedIndex + 2})`
    );
    
    if (indicator && option) {
      // Only disable transition for the very first positioning
      if (!this.indicatorInitialized) {
        indicator.classList.add('no-transition');
        this.indicatorInitialized = true;
        
        // Remove the no-transition class after a brief delay
        setTimeout(() => {
          indicator.classList.remove('no-transition');
        }, 50);
      }
      
      indicator.style.width = `${option.clientWidth}px`;
      indicator.style.left = `${option.offsetLeft}px`;
      indicator.style.opacity = '1';
    }
  }

  public getValue(): string | boolean {
    if (this.type === 'boolean') {
      return this.selectedOption === this.booleanTrueName;
    }
    return this.selectedOption;
  }

  public setValue(value: string | boolean): void {
    if (this.type === 'boolean' && typeof value === 'boolean') {
      this.selectedOption = value ? (this.booleanTrueName || 'true') : (this.booleanFalseName || 'false');
    } else {
      this.selectedOption = value as string;
    }
    this.requestUpdate();
    if (this.hasUpdated) {
      requestAnimationFrame(() => {
        this.setIndicator();
      });
    }
  }
}
