import {
  Component,
  HostListener,
  computed,
  inject,
  signal
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { Store } from '@ngrx/store';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucidePhone, lucidePhoneOff } from '@ng-icons/lucide';
import { UserAvatarComponent } from '../../../../shared';
import { selectCurrentUser } from '../../../../store/users/users.selectors';
import { User } from '../../../../shared-kernel';
import { DirectCallService } from '../../application/services/direct-call.service';
import { DirectCallSession, participantToUser } from '../../domain/models/direct-call.model';

@Component({
  selector: 'app-incoming-call-modal',
  standalone: true,
  imports: [
    CommonModule,
    NgIcon,
    UserAvatarComponent
  ],
  viewProviders: [
    provideIcons({
      lucidePhone,
      lucidePhoneOff
    })
  ],
  templateUrl: './incoming-call-modal.component.html'
})
export class IncomingCallModalComponent {
  readonly calls = inject(DirectCallService);
  readonly currentUser = inject(Store).selectSignal(selectCurrentUser);
  readonly session = this.calls.incomingCall;
  readonly answering = signal(false);
  readonly caller = computed(() => {
    const session = this.session();

    if (!session) {
      return null;
    }

    const callerId = this.callerIdFor(session);
    const participant = callerId ? session.participants[callerId]?.profile : null;

    return (callerId ? this.calls.userForParticipant(callerId) : null)
      ?? (participant ? participantToUser(participant) : null);
  });
  readonly callerName = computed(() => this.caller()?.displayName || 'Someone');
  readonly callKindLabel = computed(() => {
    const participantCount = this.session()?.participantIds.length ?? 0;

    return participantCount > 2 ? `${participantCount} person call` : 'Direct call';
  });

  @HostListener('document:keydown.escape')
  onEscape(): void {
    this.decline();
  }

  async answer(): Promise<void> {
    const session = this.session();

    if (!session || this.answering()) {
      return;
    }

    this.answering.set(true);

    try {
      await this.calls.answerIncomingCall(session.callId);
    } finally {
      this.answering.set(false);
    }
  }

  decline(): void {
    const session = this.session();

    if (!session) {
      return;
    }

    this.calls.declineIncomingCall(session.callId);
  }

  private callerIdFor(session: DirectCallSession): string | null {
    const currentUserId = this.currentUserKey();

    if (session.initiatorId && session.initiatorId !== currentUserId) {
      return session.initiatorId;
    }

    return session.participantIds.find((participantId) => participantId !== currentUserId) ?? null;
  }

  private currentUserKey(): string | null {
    const user = this.currentUser();

    return user ? this.userKey(user) : null;
  }

  private userKey(user: User): string {
    return user.oderId || user.id;
  }
}
