import {
  ChangeDetectionStrategy,
  Component,
  ElementRef,
  EventEmitter,
  HostListener,
  Input,
  OnDestroy,
  Output,
  signal,
  ViewChild,
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatChipsModule } from '@angular/material/chips';
import { AgentCardData, AgentStatus } from '../../models/agent.model';

// ============================================================================
// Agent Session Drawer — Per CUB-26
// Desktop: 480px side drawer slides from right with modal overlay.
// Mobile: Bottom sheet slides up from bottom.
// Shows: Agent name, status badge, session key, live log tail,
//         recent messages, and action buttons.
// ============================================================================

export interface SessionLogLine {
  timestamp: Date;
  level: 'info' | 'warn' | 'error' | 'debug';
  message: string;
}

export interface SessionMessage {
  id: string;
  sender: 'agent' | 'user';
  content: string;
  timestamp: Date;
}

@Component({
  selector: 'app-agent-session-drawer',
  standalone: true,
  imports: [CommonModule, MatButtonModule, MatIconModule, MatChipsModule],
  templateUrl: './agent-session-drawer.component.html',
  styleUrl: './agent-session-drawer.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AgentSessionDrawerComponent implements OnDestroy {
  // ---------------------------------------------------------------------------
  // Inputs
  // ---------------------------------------------------------------------------

  /** The agent whose session details are displayed. */
  @Input() set agent(value: AgentCardData | null) {
    this._agent = value;
    if (value) {
      this.isOpen.set(true);
      this.loadSessionData(value);
    }
  }
  get agent(): AgentCardData | null {
    return this._agent;
  }
  private _agent: AgentCardData | null = null;

  /** Whether this is mobile viewport (bottom sheet mode). */
  @Input() isMobile = false;

  // ---------------------------------------------------------------------------
  // Outputs
  // ---------------------------------------------------------------------------

  /** Emitted when the user clicks "Open Full Session". Payload is the session key. */
  @Output() readonly openSession = new EventEmitter<string>();

  /** Emitted when the user clicks "Pin to Dashboard". Payload is the session key. */
  @Output() readonly pinToDashboard = new EventEmitter<string>();

  /** Emitted when the drawer closes. */
  @Output() readonly drawerClose = new EventEmitter<void>();

  // ---------------------------------------------------------------------------
  // Signals
  // ---------------------------------------------------------------------------

  readonly isOpen = signal(false);
  readonly logLines = signal<SessionLogLine[]>([]);
  readonly recentMessages = signal<SessionMessage[]>([]);

  // ---------------------------------------------------------------------------
  // View Children
  // ---------------------------------------------------------------------------

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

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

  getStatusClass(status: string): string {
    return `status-dot--${status}`;
  }

  getStatusLabel(status: AgentStatus): string {
    const labels: Record<AgentStatus, string> = {
      active: 'Active',
      idle: 'Idle',
      thinking: 'Thinking…',
      error: 'Error',
      offline: 'Offline',
    };
    return labels[status] ?? status;
  }

  getStatusChipColor(status: AgentStatus): string {
    const map: Record<AgentStatus, string> = {
      active: 'status-chip--active',
      idle: 'status-chip--idle',
      thinking: 'status-chip--thinking',
      error: 'status-chip--error',
      offline: 'status-chip--offline',
    };
    return map[status] ?? '';
  }

  getLogLevelClass(level: SessionLogLine['level']): string {
    return `log-line--${level}`;
  }

  /** Format a date to a short time string. */
  formatTime(date: Date): string {
    return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
  }

  /** Format a date to a relative time string. */
  formatRelativeTime(date: Date): string {
    const now = Date.now();
    const then = date.getTime();
    const diffSec = Math.max(0, Math.floor((now - then) / 1000));
    if (diffSec < 60) return 'just now';
    if (diffSec < 3600) return `${Math.floor(diffSec / 60)}m ago`;
    if (diffSec < 86400) return `${Math.floor(diffSec / 3600)}h ago`;
    return `${Math.floor(diffSec / 86400)}d ago`;
  }

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

  /** Open the drawer for a specific agent. */
  open(agentData: AgentCardData): void {
    this._agent = agentData;
    this.isOpen.set(true);
    this.loadSessionData(agentData);
  }

  /** Close the drawer. */
  close(): void {
    this.isOpen.set(false);
    this.drawerClose.emit();
  }

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

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

  /** Handle keyboard navigation within the drawer. */
  onDrawerKeydown(event: KeyboardEvent): void {
    if (event.key === 'Escape') {
      this.close();
      return;
    }
    // Tab through actions — browser default Tab behavior is fine,
    // we just trap focus within the drawer
  }

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

  onBackdropClick(): void {
    this.close();
  }

  // ---------------------------------------------------------------------------
  // Actions
  // ---------------------------------------------------------------------------

  onOpenSession(): void {
    if (this._agent) {
      this.openSession.emit(this._agent.sessionKey);
    }
    this.close();
  }

  onPinToDashboard(): void {
    if (this._agent) {
      this.pinToDashboard.emit(this._agent.sessionKey);
    }
    // Don't close — user may want to keep viewing
  }

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

  ngOnDestroy(): void {
    // Clean up any subscriptions when needed
  }

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

  /** Load mock session data for the agent (TODO: wire to real data service). */
  private loadSessionData(agentData: AgentCardData): void {
    // TODO: Replace with real session data service when available.
    // For now, generate placeholder log lines and messages.
    const now = new Date();
    const logLines: SessionLogLine[] = [];
    for (let i = 19; i >= 0; i--) {
      const ts = new Date(now.getTime() - i * 5000);
      const levels: SessionLogLine['level'][] = ['info', 'info', 'info', 'debug', 'warn'];
      const messages = [
        `Processing task queue for ${agentData.displayName}`,
        `SignalR heartbeat OK`,
        `Session state: active`,
        `Checking for pending commands…`,
        `Updating task progress: ${Math.floor(Math.random() * 100)}%`,
      ];
      logLines.push({
        timestamp: ts,
        level: levels[i % levels.length],
        message: messages[i % messages.length],
      });
    }
    this.logLines.set(logLines);

    const recentMessages: SessionMessage[] = [
      {
        id: '1',
        sender: 'user',
        content: `Hey ${agentData.displayName}, how's the current task going?`,
        timestamp: new Date(now.getTime() - 120000),
      },
      {
        id: '2',
        sender: 'agent',
        content: agentData.currentTask ?? 'Working on it — progress is steady.',
        timestamp: new Date(now.getTime() - 115000),
      },
      {
        id: '3',
        sender: 'user',
        content: 'Great, let me know if you hit any blockers.',
        timestamp: new Date(now.getTime() - 110000),
      },
    ];
    this.recentMessages.set(recentMessages);
  }
}