import {
  ChangeDetectionStrategy,
  Component,
  ElementRef,
  EventEmitter,
  HostListener,
  OnDestroy,
  Output,
  signal,
  ViewChild,
} from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { Subject, takeUntil } from 'rxjs';
import { AgentCardData } from '../../models/agent.model';
import { AgentStatusService } from '../../services/agent-status.service';

@Component({
  selector: 'app-quick-jump-drawer',
  standalone: true,
  imports: [ReactiveFormsModule],
  templateUrl: './quick-jump-drawer.component.html',
  styleUrl: './quick-jump-drawer.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class QuickJumpDrawerComponent implements OnDestroy {
  /** Emits when the drawer should close (ESC, outside click, or item select). */
  @Output() readonly drawerClose = new EventEmitter<void>();

  /** Whether the drawer is visible. */
  readonly isOpen = signal(false);

  /** Search/filter input control. */
  readonly searchControl = new FormControl('', { nonNullable: true });

  /** Filtered agent list based on search. */
  readonly filteredAgents = signal<AgentCardData[]>([]);

  /** Track which agent row is highlighted via keyboard navigation. */
  readonly highlightedIndex = signal(-1);

  @ViewChild('searchInput') searchInput!: ElementRef<HTMLInputElement>;
  @ViewChild('drawerPanel') drawerPanel!: ElementRef<HTMLElement>;

  private readonly destroy$ = new Subject<void>();

  constructor(private readonly agentStatusService: AgentStatusService) {
    // Reactively filter agents as the search input changes
    this.searchControl.valueChanges
      .pipe(takeUntil(this.destroy$))
      .subscribe((query) => this.filterAgents(query));

    // Initial load
    this.filterAgents('');
  }

  // ---------------------------------------------------------------------------
  // Public API
  // ---------------------------------------------------------------------------

  /** Open the drawer and focus the search input. */
  open(): void {
    this.isOpen.set(true);
    this.searchControl.setValue('', { emitEvent: false });
    this.highlightedIndex.set(-1);
    // Focus search input after animation frame (drawer needs to render first)
    requestAnimationFrame(() => {
      this.searchInput?.nativeElement?.focus();
    });
  }

  /** Close the drawer. */
  close(): void {
    this.isOpen.set(false);
    this.searchControl.setValue('', { emitEvent: false });
    this.highlightedIndex.set(-1);
    this.drawerClose.emit();
  }

  /** Toggle the drawer open/close. */
  toggle(): void {
    if (this.isOpen()) {
      this.close();
    } else {
      this.open();
    }
  }

  // ---------------------------------------------------------------------------
  // Keyboard Handling
  // ---------------------------------------------------------------------------

  @HostListener('document:keydown.escape')
  onEscapeKey(): void {
    if (this.isOpen()) {
      this.close();
    }
  }

  /** Handle keyboard navigation within the drawer panel. */
  onDrawerKeydown(event: KeyboardEvent): void {
    const agents = this.filteredAgents();
    if (!agents.length) return;

    switch (event.key) {
      case 'ArrowDown': {
        event.preventDefault();
        this.highlightedIndex.update((i) =>
          i < agents.length - 1 ? i + 1 : 0
        );
        this.scrollIntoView();
        break;
      }
      case 'ArrowUp': {
        event.preventDefault();
        this.highlightedIndex.update((i) =>
          i > 0 ? i - 1 : agents.length - 1
        );
        this.scrollIntoView();
        break;
      }
      case 'Enter': {
        const idx = this.highlightedIndex();
        if (idx >= 0 && idx < agents.length) {
          this.selectAgent(agents[idx]);
        }
        break;
      }
    }
  }

  // ---------------------------------------------------------------------------
  // Outside Click
  // ---------------------------------------------------------------------------

  /** Close when clicking on the backdrop (outside the panel). */
  onBackdropClick(event: MouseEvent): void {
    if (
      this.drawerPanel?.nativeElement &&
      !this.drawerPanel.nativeElement.contains(event.target as Node)
    ) {
      this.close();
    }
  }

  // ---------------------------------------------------------------------------
  // Agent Selection
  // ---------------------------------------------------------------------------

  /** Select an agent — navigates or focuses the agent card. */
  selectAgent(agent: AgentCardData): void {
    // TODO: Wire up navigation to the selected agent's detail view
    // For now, emit close after selection
    console.log('[QuickJump] Selected agent:', agent.id);
    this.close();
  }

  // ---------------------------------------------------------------------------
  // Status Helpers
  // ---------------------------------------------------------------------------

  /** Get the CSS class for a given agent status. */
  getStatusClass(status: string): string {
    return `status-dot--${status}`;
  }

  /** Get a human-readable label for an agent status. */
  getStatusLabel(status: string): string {
    const labels: Record<string, string> = {
      active: 'Active',
      idle: 'Idle',
      thinking: 'Thinking',
      error: 'Error',
      offline: 'Offline',
    };
    return labels[status] ?? status;
  }

  // ---------------------------------------------------------------------------
  // Lifecycle
  // ---------------------------------------------------------------------------

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

  // ---------------------------------------------------------------------------
  // Private
  // ---------------------------------------------------------------------------

  private filterAgents(query: string): void {
    const allAgents = this.agentStatusService.agents();
    const lowerQuery = query.toLowerCase().trim();

    if (!lowerQuery) {
      this.filteredAgents.set(allAgents);
      return;
    }

    const filtered = allAgents.filter(
      (agent) =>
        agent.displayName.toLowerCase().includes(lowerQuery) ||
        agent.id.toLowerCase().includes(lowerQuery) ||
        agent.role.toLowerCase().includes(lowerQuery)
    );
    this.filteredAgents.set(filtered);
    this.highlightedIndex.set(-1);
  }

  private scrollIntoView(): void {
    const idx = this.highlightedIndex();
    const el = document.getElementById(`quick-jump-agent-${idx}`);
    el?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
  }
}