import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { CallService, CallInfo } from '../../services/call.service';
import { UserService } from '../../services/user.service';
import { LoggerService } from '../../services/logger.service';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-call',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './call.component.html',
  styleUrl: './call.component.scss'
})
export class CallComponent implements OnInit, OnDestroy {
  @ViewChild('localVideo') localVideoRef!: ElementRef<HTMLVideoElement>;
  @ViewChild('remoteVideo') remoteVideoRef!: ElementRef<HTMLVideoElement>;

  currentCall: CallInfo | null = null;
  isRinging: boolean = false;
  isCallActive: boolean = false;
  isMuted: boolean = false;
  isVideoEnabled: boolean = true;
  isIncoming: boolean = false;
  private subscriptions: Subscription[] = [];
  private currentUser: any = null; // Cache current user to avoid repeated API calls

  constructor(
    public callService: CallService,
    public userService: UserService,
    private logger: LoggerService
  ) {}

  async ngOnInit(): Promise<void> {
    // Cache current user on init to avoid repeated calls
    this.currentUser = await this.userService.getCurrentUser();

    const callSub = this.callService.call$.subscribe(callInfo => {
      this.handleCallUpdate(callInfo);
    });

    const signalSub = this.callService.signal$.subscribe(signal => {
      if (signal.signalData?.remoteStreamReady && this.remoteVideoRef) {
        const remoteStream = this.callService.getRemoteStream();
        if (remoteStream && this.remoteVideoRef.nativeElement) {
          this.remoteVideoRef.nativeElement.srcObject = remoteStream;
        }
      }
    });

    this.subscriptions.push(callSub, signalSub);

    // Update video streams periodically
    const interval = setInterval(() => {
      this.updateVideoStreams();
    }, 1000);

    this.subscriptions.push(new Subscription(() => clearInterval(interval)));
  }

  ngOnDestroy(): void {
    this.subscriptions.forEach(sub => sub.unsubscribe());
  }

  private async handleCallUpdate(callInfo: CallInfo | null): Promise<void> {
    this.logger.debug('Call component received call update:', callInfo);
    
    // Handle null callInfo (when call is cleared)
    if (!callInfo) {
      this.logger.debug('Call info is null, clearing call state');
      this.currentCall = null;
      this.isRinging = false;
      this.isCallActive = false;
      if (this.localVideoRef?.nativeElement) {
        this.localVideoRef.nativeElement.srcObject = null;
      }
      if (this.remoteVideoRef?.nativeElement) {
        this.remoteVideoRef.nativeElement.srcObject = null;
      }
      return;
    }
    
    this.currentCall = callInfo;

    // Ensure we have current user (use cache if available, fetch if not)
    if (!this.currentUser) {
      this.currentUser = await this.userService.getCurrentUser();
    }

    // Determine if this is an incoming call (we are the receiver) or outgoing call (we are the sender)
    if (this.currentUser) {
      const isSender = callInfo.senderId === this.currentUser.id;
      const isReceiver = callInfo.receiverId === this.currentUser.id;
      
      // It's incoming if we are the receiver (not the sender) and the call is ringing
      // It's outgoing if we are the sender (not the receiver) and the call is ringing
      this.isIncoming = isReceiver && !isSender && callInfo.callStatus === 'ringing';
      
      this.logger.debug('Current user ID:', this.currentUser.id, 
                  'Sender ID:', callInfo.senderId, 
                  'Receiver ID:', callInfo.receiverId, 
                  'Is sender:', isSender,
                  'Is receiver:', isReceiver,
                  'Is incoming:', this.isIncoming);
    }

    if (callInfo.callStatus === 'ringing') {
      this.logger.debug('Call is ringing - showing UI');
      this.isRinging = true;
      this.isCallActive = false;
      // Update UI immediately
      this.updateVideoStreams();
    } else if (callInfo.callStatus === 'accepted') {
      this.logger.debug('Call accepted - starting active call');
      this.isRinging = false;
      this.isCallActive = true;
      setTimeout(() => this.updateVideoStreams(), 500);
    } else {
      this.isRinging = false;
      this.isCallActive = false;
      if (callInfo.callStatus === 'ended' || callInfo.callStatus === 'rejected' || callInfo.callStatus === 'cancelled') {
        this.logger.debug('Call terminated:', callInfo.callStatus);
        this.currentCall = null;
      }
    }
  }

  private updateVideoStreams(): void {
    if (this.localVideoRef?.nativeElement) {
      const localStream = this.callService.getLocalStream();
      if (localStream) {
        this.localVideoRef.nativeElement.srcObject = localStream;
      }
    }

    if (this.remoteVideoRef?.nativeElement && this.isCallActive) {
      const remoteStream = this.callService.getRemoteStream();
      if (remoteStream) {
        this.remoteVideoRef.nativeElement.srcObject = remoteStream;
      }
    }
  }

  async answerCall(): Promise<void> {
    await this.callService.answerCall();
    this.isRinging = false;
    this.isCallActive = true;
  }

  async rejectCall(): Promise<void> {
    await this.callService.rejectCall();
    this.isRinging = false;
    this.currentCall = null;
  }

  async endCall(): Promise<void> {
    // If call is still ringing and we're the caller, cancel the call
    if (this.isRinging && !this.isIncoming && this.currentCall) {
      await this.callService.cancelCall();
    } else {
      await this.callService.endCall();
    }
    this.isCallActive = false;
    this.currentCall = null;
    this.isRinging = false;
    if (this.localVideoRef?.nativeElement) {
      this.localVideoRef.nativeElement.srcObject = null;
    }
    if (this.remoteVideoRef?.nativeElement) {
      this.remoteVideoRef.nativeElement.srcObject = null;
    }
  }

  async toggleMute(): Promise<void> {
    this.isMuted = !await this.callService.toggleMute();
  }

  async toggleVideo(): Promise<void> {
    this.isVideoEnabled = !await this.callService.toggleVideo();
  }

  getOtherUserName(): string {
    if (!this.currentCall) return '';
    // Use cached currentUser if available, otherwise return based on call info
    // If we're the sender (incoming=false), show receiver name
    // If we're the receiver (incoming=true), show sender name
    if (this.isIncoming && this.currentCall.senderName) {
      return this.currentCall.senderName;
    } else if (!this.isIncoming && this.currentCall.receiverName) {
      return this.currentCall.receiverName;
    }
    return this.currentCall.senderName || this.currentCall.receiverName || 'Unknown';
  }

  getOtherUserAvatarUrl(): string | undefined {
    if (!this.currentCall) return undefined;
    // Return sender's avatar if we're the receiver (incoming call)
    // Return receiver's avatar if we're the sender (outgoing call)
    if (this.isIncoming) {
      return this.currentCall.senderAvatarUrl;
    }
    // For outgoing calls, return the receiver's avatar
    return this.currentCall.receiverAvatarUrl;
  }

  isVideoCall(): boolean {
    return this.currentCall?.callType === 'video';
  }

  shouldShowCall(): boolean {
    return this.currentCall !== null && (this.isRinging || this.isCallActive);
  }
}

