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

declare global {
  interface HTMLElementTagNameMap {
    'dees-input-tags': DeesInputTags;
  }
}

@customElement('dees-input-tags')
export class DeesInputTags extends DeesInputBase<DeesInputTags> {
  // STATIC
  public static demo = demoFunc;
  public static demoGroup = 'Input';

  // INSTANCE
  @property({ type: Array })
  accessor value: string[] = [];

  @property({ type: String })
  accessor placeholder: string = 'Add tags...';

  @property({ type: Number })
  accessor maxTags: number = 0; // 0 means unlimited

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

  @state()
  accessor inputValue: string = '';

  @state()
  accessor showSuggestions: boolean = false;

  @state()
  accessor highlightedSuggestionIndex: number = -1;

  @property({ type: String })
  accessor validationText: string = '';

  public static styles = [
    themeDefaultStyles,
    ...DeesInputBase.baseStyles,
    cssManager.defaultStyles,
    css`
      /* TODO: Migrate hardcoded values to --dees-* CSS variables */
      :host {
        display: block;
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
      }

      .input-wrapper {
        width: 100%;
      }

      .tags-container {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        gap: 6px;
        padding: 6px 10px;
        min-height: 40px;
        background: transparent;
        border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
        border-radius: 6px;
        transition: all 0.15s ease;
        cursor: text;
      }

      .tags-container:hover:not(.disabled) {
        border-color: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
      }

      .tags-container:focus-within {
        border-color: ${cssManager.bdTheme('hsl(222.2 47.4% 51.2%)', 'hsl(217.2 91.2% 59.8%)')};
        box-shadow: 0 0 0 3px ${cssManager.bdTheme('hsl(222.2 47.4% 51.2% / 0.1)', 'hsl(217.2 91.2% 59.8% / 0.1)')};
      }

      .tags-container.disabled {
        background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 14.9%)')};
        border-color: ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
        cursor: not-allowed;
        opacity: 0.5;
      }

      .tag {
        display: inline-flex;
        align-items: center;
        gap: 4px;
        padding: 2px 8px;
        background: ${cssManager.bdTheme('hsl(215 20.2% 65.1% / 0.2)', 'hsl(215 20.2% 35.1% / 0.2)')};
        color: ${cssManager.bdTheme('hsl(215.3 25% 26.7%)', 'hsl(217.9 10.6% 74.9%)')};
        border: 1px solid ${cssManager.bdTheme('hsl(215 20.2% 65.1% / 0.3)', 'hsl(215 20.2% 35.1% / 0.3)')};
        border-radius: 4px;
        font-size: 13px;
        font-weight: 500;
        line-height: 18px;
        user-select: none;
        animation: tagAppear 0.15s cubic-bezier(0.4, 0, 0.2, 1);
      }

      @keyframes tagAppear {
        from {
          transform: scale(0.95);
          opacity: 0;
        }
        to {
          transform: scale(1);
          opacity: 1;
        }
      }

      .tag-remove {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 14px;
        height: 14px;
        margin-left: 2px;
        border-radius: 3px;
        cursor: pointer;
        transition: all 0.15s ease;
        color: ${cssManager.bdTheme('hsl(215.3 25% 46.7%)', 'hsl(217.9 10.6% 54.9%)')};
      }

      .tag-remove:hover {
        background: ${cssManager.bdTheme('hsl(0 0% 0% / 0.08)', 'hsl(0 0% 100% / 0.08)')};
        color: ${cssManager.bdTheme('hsl(215.3 25% 26.7%)', 'hsl(217.9 10.6% 74.9%)')};
      }

      .tag-remove dees-icon {
        width: 10px;
        height: 10px;
      }

      .tag-input {
        flex: 1;
        min-width: 120px;
        border: none;
        background: transparent;
        outline: none;
        font-size: 14px;
        font-family: inherit;
        color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
        padding: 2px 4px;
        line-height: 20px;
      }

      .tag-input::placeholder {
        color: ${cssManager.bdTheme('hsl(0 0% 63.9%)', 'hsl(0 0% 45.1%)')};
      }

      .tag-input:disabled {
        cursor: not-allowed;
      }

      /* Suggestions dropdown */
      .suggestions-container {
        position: relative;
      }

      .suggestions-dropdown {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        margin-top: 4px;
        background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(0 0% 3.9%)')};
        border: 1px solid ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
        border-radius: 6px;
        box-shadow: 0 4px 6px -1px hsl(0 0% 0% / 0.1), 0 2px 4px -2px hsl(0 0% 0% / 0.1);
        max-height: 200px;
        overflow-y: auto;
        z-index: 1000;
      }

      .suggestion {
        padding: 6px 10px;
        cursor: pointer;
        transition: all 0.15s ease;
        font-size: 14px;
        color: ${cssManager.bdTheme('hsl(0 0% 15%)', 'hsl(0 0% 90%)')};
      }

      .suggestion:hover {
        background: ${cssManager.bdTheme('hsl(0 0% 95.1%)', 'hsl(0 0% 14.9%)')};
      }

      .suggestion.highlighted {
        background: ${cssManager.bdTheme('hsl(210 40% 96.1%)', 'hsl(215 20.2% 16.8%)')};
        color: ${cssManager.bdTheme('hsl(0 0% 9%)', 'hsl(0 0% 95%)')};
      }

      /* Validation styles */
      .validation-message {
        color: ${cssManager.bdTheme('hsl(0 72.2% 50.6%)', 'hsl(0 62.8% 30.6%)')};
        font-size: 13px;
        margin-top: 6px;
        line-height: 1.5;
      }

      /* Description styles */
      .description {
        color: ${cssManager.bdTheme('hsl(215.4 16.3% 56.9%)', 'hsl(215 20.2% 55.1%)')};
        font-size: 13px;
        margin-top: 6px;
        line-height: 1.5;
      }

      /* Scrollbar styling */
      .suggestions-dropdown::-webkit-scrollbar {
        width: 8px;
      }

      .suggestions-dropdown::-webkit-scrollbar-track {
        background: transparent;
      }

      .suggestions-dropdown::-webkit-scrollbar-thumb {
        background: ${cssManager.bdTheme('hsl(0 0% 89.8%)', 'hsl(0 0% 14.9%)')};
        border-radius: 4px;
      }

      .suggestions-dropdown::-webkit-scrollbar-thumb:hover {
        background: ${cssManager.bdTheme('hsl(0 0% 79.8%)', 'hsl(0 0% 20.9%)')};
      }
    `,
  ];

  public render(): TemplateResult {
    const filteredSuggestions = this.suggestions.filter(
      suggestion => 
        !this.value.includes(suggestion) &&
        suggestion.toLowerCase().includes(this.inputValue.toLowerCase())
    );

    return html`
      <div class="input-wrapper">
        ${this.label ? html`<dees-label .label=${this.label} .required=${this.required}></dees-label>` : ''}
        
        <div class="suggestions-container">
          <div
            class="tags-container ${this.disabled ? 'disabled' : ''}"
            @click=${this.handleContainerClick}
          >
            ${this.value.map(tag => html`
              <div class="tag">
                <span>${tag}</span>
                ${!this.disabled ? html`
                  <div class="tag-remove" @click=${(e: Event) => this.removeTag(e, tag)}>
                    <dees-icon .icon=${'lucide:x'}></dees-icon>
                  </div>
                ` : ''}
              </div>
            `)}
            
            ${!this.disabled && (!this.maxTags || this.value.length < this.maxTags) ? html`
              <input
                type="text"
                class="tag-input"
                .placeholder=${this.placeholder}
                .value=${this.inputValue}
                @input=${this.handleInput}
                @keydown=${this.handleKeyDown}
                @focus=${this.handleFocus}
                @blur=${this.handleBlur}
                ?disabled=${this.disabled}
              />
            ` : ''}
          </div>

          ${this.showSuggestions && filteredSuggestions.length > 0 ? html`
            <div class="suggestions-dropdown">
              ${filteredSuggestions.map((suggestion, index) => html`
                <div
                  class="suggestion ${index === this.highlightedSuggestionIndex ? 'highlighted' : ''}"
                  @mousedown=${(e: Event) => {
                    e.preventDefault(); // Prevent blur
                    this.addTag(suggestion);
                  }}
                  @mouseenter=${() => this.highlightedSuggestionIndex = index}
                >
                  ${suggestion}
                </div>
              `)}
            </div>
          ` : ''}
        </div>

        ${this.validationText ? html`
          <div class="validation-message">${this.validationText}</div>
        ` : ''}
        
        ${this.description ? html`
          <div class="description">${this.description}</div>
        ` : ''}
      </div>
    `;
  }

  private handleContainerClick(e: Event) {
    if (this.disabled) return;
    
    const input = this.shadowRoot?.querySelector('.tag-input') as HTMLInputElement;
    if (input && e.target !== input) {
      input.focus();
    }
  }

  private handleInput(e: Event) {
    const input = e.target as HTMLInputElement;
    this.inputValue = input.value;
    
    // Check for comma or semicolon to add tag
    if (this.inputValue.includes(',') || this.inputValue.includes(';')) {
      const tag = this.inputValue.replace(/[,;]/g, '').trim();
      if (tag) {
        this.addTag(tag);
      }
    }
  }

  private handleKeyDown(e: KeyboardEvent) {
    const input = e.target as HTMLInputElement;
    
    if (e.key === 'Enter') {
      e.preventDefault();
      if (this.highlightedSuggestionIndex >= 0 && this.showSuggestions) {
        const filteredSuggestions = this.suggestions.filter(
          suggestion => 
            !this.value.includes(suggestion) &&
            suggestion.toLowerCase().includes(this.inputValue.toLowerCase())
        );
        if (filteredSuggestions[this.highlightedSuggestionIndex]) {
          this.addTag(filteredSuggestions[this.highlightedSuggestionIndex]);
        }
      } else if (this.inputValue.trim()) {
        this.addTag(this.inputValue.trim());
      }
    } else if (e.key === 'Backspace' && !this.inputValue && this.value.length > 0) {
      // Remove last tag when backspace is pressed on empty input
      this.removeTag(e, this.value[this.value.length - 1]);
    } else if (e.key === 'ArrowDown' && this.showSuggestions) {
      e.preventDefault();
      const filteredCount = this.suggestions.filter(
        s => !this.value.includes(s) && s.toLowerCase().includes(this.inputValue.toLowerCase())
      ).length;
      this.highlightedSuggestionIndex = Math.min(
        this.highlightedSuggestionIndex + 1,
        filteredCount - 1
      );
    } else if (e.key === 'ArrowUp' && this.showSuggestions) {
      e.preventDefault();
      this.highlightedSuggestionIndex = Math.max(this.highlightedSuggestionIndex - 1, 0);
    } else if (e.key === 'Escape') {
      this.showSuggestions = false;
      this.highlightedSuggestionIndex = -1;
    }
  }

  private handleFocus() {
    if (this.suggestions.length > 0) {
      this.showSuggestions = true;
    }
  }

  private handleBlur() {
    // Delay to allow click on suggestions
    setTimeout(() => {
      this.showSuggestions = false;
      this.highlightedSuggestionIndex = -1;
    }, 200);
  }

  private addTag(tag: string) {
    if (!tag || this.value.includes(tag)) return;
    if (this.maxTags && this.value.length >= this.maxTags) return;

    this.value = [...this.value, tag];
    this.inputValue = '';
    this.showSuggestions = false;
    this.highlightedSuggestionIndex = -1;
    
    // Clear the input
    const input = this.shadowRoot?.querySelector('.tag-input') as HTMLInputElement;
    if (input) {
      input.value = '';
    }

    this.emitChange();
  }

  private removeTag(e: Event, tag: string) {
    e.stopPropagation();
    this.value = this.value.filter(t => t !== tag);
    this.emitChange();
  }

  private emitChange() {
    this.dispatchEvent(new CustomEvent('change', {
      detail: { value: this.value },
      bubbles: true,
      composed: true
    }));
    this.changeSubject.next(this);
  }

  public getValue(): string[] {
    return this.value;
  }

  public setValue(value: string[]): void {
    this.value = value || [];
  }

  public async validate(): Promise<boolean> {
    if (this.required && (!this.value || this.value.length === 0)) {
      this.validationText = 'At least one tag is required';
      return false;
    }
    this.validationText = '';
    return true;
  }
}