import {
  customElement,
  DeesElement,
  type TemplateResult,
  html,
  property,
  css,
  cssManager,
} from '@design.estate/dees-element';
import { DeesIcon } from '@design.estate/dees-catalog';
import { demo } from './eco-applauncher-soundmenu.demo.js';

// Ensure dees-icon is registered
DeesIcon;

declare global {
  interface HTMLElementTagNameMap {
    'eco-applauncher-soundmenu': EcoApplauncherSoundmenu;
  }
}

export interface IAudioDevice {
  id: string;
  name: string;
  type: 'speaker' | 'headphones' | 'bluetooth' | 'hdmi';
  active?: boolean;
}

@customElement('eco-applauncher-soundmenu')
export class EcoApplauncherSoundmenu extends DeesElement {
  public static demo = demo;
  public static demoGroup = 'App Launcher';

  public static styles = [
    cssManager.defaultStyles,
    css`
      :host {
        display: block;
        position: relative;
        pointer-events: none;
      }

      :host([open]) {
        pointer-events: auto;
      }

      .menu-container {
        background: ${cssManager.bdTheme('#ffffff', 'hsl(240 6% 10%)')};
        border: 1px solid ${cssManager.bdTheme('hsl(0 0% 90%)', 'hsl(240 5% 20%)')};
        border-radius: 12px;
        box-shadow: ${cssManager.bdTheme(
          '0 8px 32px rgba(0, 0, 0, 0.15)',
          '0 8px 32px rgba(0, 0, 0, 0.4)'
        )};
        min-width: 280px;
        overflow: hidden;
        opacity: 0;
        transform: scale(0.95) translateY(-8px);
        transition: all 0.2s ease-out;
        pointer-events: none;
      }

      :host([open]) .menu-container {
        opacity: 1;
        transform: scale(1) translateY(0);
        pointer-events: auto;
      }

      .menu-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 16px;
        border-bottom: 1px solid ${cssManager.bdTheme('hsl(0 0% 92%)', 'hsl(240 5% 15%)')};
      }

      .menu-title {
        font-size: 15px;
        font-weight: 600;
        color: ${cssManager.bdTheme('hsl(0 0% 10%)', 'hsl(0 0% 98%)')};
        display: flex;
        align-items: center;
        gap: 10px;
      }

      .volume-section {
        padding: 20px 16px;
      }

      .volume-slider-container {
        display: flex;
        align-items: center;
        gap: 12px;
      }

      .volume-icon {
        color: ${cssManager.bdTheme('hsl(0 0% 40%)', 'hsl(0 0% 70%)')};
        cursor: pointer;
        transition: color 0.15s ease;
      }

      .volume-icon:hover {
        color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
      }

      .volume-icon.muted {
        color: hsl(0 72% 51%);
      }

      .volume-slider {
        flex: 1;
        height: 6px;
        background: ${cssManager.bdTheme('hsl(0 0% 88%)', 'hsl(240 5% 20%)')};
        border-radius: 3px;
        position: relative;
        cursor: pointer;
      }

      .volume-fill {
        height: 100%;
        background: hsl(217 91% 60%);
        border-radius: 3px;
        transition: width 0.1s ease;
      }

      .volume-fill.muted {
        background: ${cssManager.bdTheme('hsl(0 0% 70%)', 'hsl(0 0% 40%)')};
      }

      .volume-thumb {
        position: absolute;
        top: 50%;
        transform: translate(-50%, -50%);
        width: 16px;
        height: 16px;
        background: white;
        border-radius: 50%;
        box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
        cursor: grab;
      }

      .volume-thumb:active {
        cursor: grabbing;
      }

      .volume-percentage {
        min-width: 36px;
        text-align: right;
        font-size: 14px;
        font-weight: 500;
        color: ${cssManager.bdTheme('hsl(0 0% 30%)', 'hsl(0 0% 80%)')};
      }

      .menu-divider {
        height: 1px;
        background: ${cssManager.bdTheme('hsl(0 0% 92%)', 'hsl(240 5% 15%)')};
      }

      .section-title {
        padding: 12px 16px 8px;
        font-size: 12px;
        font-weight: 600;
        color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 50%)')};
        text-transform: uppercase;
        letter-spacing: 0.5px;
      }

      .device-list {
        max-height: 160px;
        overflow-y: auto;
      }

      .device-item {
        display: flex;
        align-items: center;
        gap: 12px;
        padding: 10px 16px;
        cursor: pointer;
        transition: background 0.15s ease;
      }

      .device-item:hover {
        background: ${cssManager.bdTheme('hsl(0 0% 96%)', 'hsl(240 5% 15%)')};
      }

      .device-item.active {
        background: ${cssManager.bdTheme('hsl(217 91% 95%)', 'hsl(217 91% 60% / 0.15)')};
      }

      .device-item.active:hover {
        background: ${cssManager.bdTheme('hsl(217 91% 92%)', 'hsl(217 91% 60% / 0.25)')};
      }

      .device-icon {
        color: ${cssManager.bdTheme('hsl(0 0% 50%)', 'hsl(0 0% 60%)')};
      }

      .device-item.active .device-icon {
        color: hsl(217 91% 60%);
      }

      .device-name {
        flex: 1;
        font-size: 14px;
        color: ${cssManager.bdTheme('hsl(0 0% 20%)', 'hsl(0 0% 90%)')};
      }

      .device-check {
        color: hsl(217 91% 60%);
      }

      .menu-footer {
        padding: 12px 16px;
        border-top: 1px solid ${cssManager.bdTheme('hsl(0 0% 92%)', 'hsl(240 5% 15%)')};
      }

      .settings-link {
        display: flex;
        align-items: center;
        gap: 8px;
        font-size: 14px;
        color: hsl(217 91% 60%);
        cursor: pointer;
        transition: color 0.15s ease;
      }

      .settings-link:hover {
        color: hsl(217 91% 50%);
      }
    `,
  ];

  @property({ type: Boolean, reflect: true })
  accessor open = false;

  @property({ type: Number })
  accessor volume = 50;

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

  @property({ type: Array })
  accessor outputDevices: IAudioDevice[] = [];

  @property({ type: String })
  accessor activeDeviceId: string | null = null;

  private boundHandleClickOutside = this.handleClickOutside.bind(this);
  private isDragging = false;
  private inactivityTimeout: ReturnType<typeof setTimeout> | null = null;
  private readonly INACTIVITY_TIMEOUT = 60000; // 1 minute
  private lastActivityTime = 0;

  public render(): TemplateResult {
    const volumeIcon = this.getVolumeIcon();

    return html`
      <div class="menu-container"
        @click=${(e: MouseEvent) => e.stopPropagation()}
        @mousedown=${this.resetInactivityTimer}
      >
        <div class="menu-header">
          <span class="menu-title">
            <dees-icon .icon=${volumeIcon} .iconSize=${18}></dees-icon>
            Sound
          </span>
        </div>

        <div class="volume-section">
          <div class="volume-slider-container">
            <dees-icon
              class="volume-icon ${this.muted ? 'muted' : ''}"
              .icon=${this.muted ? 'lucide:volumeX' : 'lucide:volume2'}
              .iconSize=${20}
              @click=${this.handleMuteToggle}
            ></dees-icon>
            <div
              class="volume-slider"
              @click=${this.handleSliderClick}
              @mousedown=${this.handleSliderMouseDown}
            >
              <div
                class="volume-fill ${this.muted ? 'muted' : ''}"
                style="width: ${this.muted ? 0 : this.volume}%"
              ></div>
              <div
                class="volume-thumb"
                style="left: ${this.muted ? 0 : this.volume}%"
              ></div>
            </div>
            <span class="volume-percentage">${this.muted ? 0 : this.volume}%</span>
          </div>
        </div>

        ${this.outputDevices.length > 0 ? html`
          <div class="menu-divider"></div>
          <div class="section-title">Output</div>
          <div class="device-list">
            ${this.outputDevices.map((device) => this.renderDeviceItem(device))}
          </div>
        ` : ''}

        <div class="menu-footer">
          <div class="settings-link" @click=${this.handleSettingsClick}>
            <dees-icon .icon=${'lucide:settings'} .iconSize=${14}></dees-icon>
            Sound Settings...
          </div>
        </div>
      </div>
    `;
  }

  private renderDeviceItem(device: IAudioDevice): TemplateResult {
    const isActive = device.id === this.activeDeviceId;
    const icon = this.getDeviceIcon(device.type);

    return html`
      <div
        class="device-item ${isActive ? 'active' : ''}"
        @click=${() => this.handleDeviceSelect(device)}
      >
        <dees-icon class="device-icon" .icon=${icon} .iconSize=${18}></dees-icon>
        <span class="device-name">${device.name}</span>
        ${isActive ? html`
          <dees-icon class="device-check" .icon=${'lucide:check'} .iconSize=${16}></dees-icon>
        ` : ''}
      </div>
    `;
  }

  private getVolumeIcon(): string {
    if (this.muted || this.volume === 0) return 'lucide:volumeX';
    if (this.volume < 33) return 'lucide:volume';
    if (this.volume < 66) return 'lucide:volume1';
    return 'lucide:volume2';
  }

  private getDeviceIcon(type: IAudioDevice['type']): string {
    switch (type) {
      case 'headphones':
        return 'lucide:headphones';
      case 'bluetooth':
        return 'lucide:bluetooth';
      case 'hdmi':
        return 'lucide:monitor';
      case 'speaker':
      default:
        return 'lucide:speaker';
    }
  }

  private handleMuteToggle(): void {
    this.muted = !this.muted;
    this.dispatchEvent(new CustomEvent('mute-toggle', {
      detail: { muted: this.muted },
      bubbles: true,
      composed: true,
    }));
  }

  private handleSliderClick(e: MouseEvent): void {
    const slider = e.currentTarget as HTMLElement;
    const rect = slider.getBoundingClientRect();
    const percentage = Math.round(((e.clientX - rect.left) / rect.width) * 100);
    this.setVolume(Math.max(0, Math.min(100, percentage)));
  }

  private handleSliderMouseDown(e: MouseEvent): void {
    this.isDragging = true;
    const slider = e.currentTarget as HTMLElement;
    let rafId: number | null = null;
    let pendingPercentage: number | null = null;

    const updateVolume = () => {
      if (pendingPercentage !== null) {
        this.setVolume(pendingPercentage);
        pendingPercentage = null;
      }
      rafId = null;
    };

    const handleMouseMove = (moveEvent: MouseEvent) => {
      if (!this.isDragging) return;
      const rect = slider.getBoundingClientRect();
      pendingPercentage = Math.max(0, Math.min(100, Math.round(((moveEvent.clientX - rect.left) / rect.width) * 100)));
      if (!rafId) {
        rafId = requestAnimationFrame(updateVolume);
      }
    };

    const handleMouseUp = () => {
      this.isDragging = false;
      if (rafId) {
        cancelAnimationFrame(rafId);
      }
      if (pendingPercentage !== null) {
        this.setVolume(pendingPercentage);
      }
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
  }

  private setVolume(value: number): void {
    this.volume = value;
    if (this.muted && value > 0) {
      this.muted = false;
    }
    this.dispatchEvent(new CustomEvent('volume-change', {
      detail: { volume: this.volume },
      bubbles: true,
      composed: true,
    }));
  }

  private handleDeviceSelect(device: IAudioDevice): void {
    this.activeDeviceId = device.id;
    this.dispatchEvent(new CustomEvent('device-select', {
      detail: { device },
      bubbles: true,
      composed: true,
    }));
  }

  private handleSettingsClick(): void {
    this.dispatchEvent(new CustomEvent('settings-click', {
      bubbles: true,
      composed: true,
    }));
  }

  private handleClickOutside(e: MouseEvent): void {
    if (this.open && !this.contains(e.target as Node)) {
      this.closeMenu();
    }
  }

  private resetInactivityTimer(): void {
    const now = Date.now();
    // Throttle: only reset if 5+ seconds since last reset
    if (now - this.lastActivityTime < 5000) {
      return;
    }
    this.lastActivityTime = now;
    this.clearInactivityTimer();
    if (this.open) {
      this.inactivityTimeout = setTimeout(() => {
        this.closeMenu();
      }, this.INACTIVITY_TIMEOUT);
    }
  }

  private clearInactivityTimer(): void {
    if (this.inactivityTimeout) {
      clearTimeout(this.inactivityTimeout);
      this.inactivityTimeout = null;
    }
  }

  private closeMenu(): void {
    this.open = false;
    this.dispatchEvent(new CustomEvent('menu-close', {
      bubbles: true,
      composed: true,
    }));
  }

  protected updated(changedProperties: Map<string, unknown>): void {
    if (changedProperties.has('open')) {
      if (this.open) {
        this.resetInactivityTimer();
      } else {
        this.clearInactivityTimer();
      }
    }
  }

  async connectedCallback(): Promise<void> {
    await super.connectedCallback();
    setTimeout(() => {
      document.addEventListener('click', this.boundHandleClickOutside);
    }, 0);
  }

  async disconnectedCallback(): Promise<void> {
    await super.disconnectedCallback();
    document.removeEventListener('click', this.boundHandleClickOutside);
    this.clearInactivityTimer();
  }
}
