import { Component, OnInit, HostListener, ViewChild, AfterViewInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { AuthService } from '../../services/auth.service';
import { AppointmentService, Appointment } from '../../services/appointment.service';
import { UserService, UserInfo, PatientProfile, PatientUpdateRequest } from '../../services/user.service';
import { ChatComponent } from '../../components/chat/chat.component';
import { ChatService, ChatUser, Conversation } from '../../services/chat.service';
import { NotificationService, Notification } from '../../services/notification.service';
import { CallComponent } from '../../components/call/call.component';
import { MedicalRecordService, MedicalRecord, VitalSigns, LabResult } from '../../services/medical-record.service';
import { PrescriptionService, Prescription } from '../../services/prescription.service';
import { TwoFactorAuthService } from '../../services/two-factor-auth.service';
import { LoggerService } from '../../services/logger.service';
import { ModalService } from '../../services/modal.service';
import { PatientDashboardHeaderComponent } from './components/patient-dashboard-header/patient-dashboard-header.component';
import { PatientDashboardTabsComponent } from './components/patient-dashboard-tabs/patient-dashboard-tabs.component';
import { PatientOverviewPanelComponent } from './components/patient-overview-panel/patient-overview-panel.component';
import { PatientAppointmentsPanelComponent } from './components/patient-appointments-panel/patient-appointments-panel.component';
import { PatientProfilePanelComponent } from './components/patient-profile-panel/patient-profile-panel.component';
import { PatientDoctorsPanelComponent } from './components/patient-doctors-panel/patient-doctors-panel.component';
import { PatientEhrPanelComponent } from './components/patient-ehr-panel/patient-ehr-panel.component';
import { PatientPrescriptionsPanelComponent } from './components/patient-prescriptions-panel/patient-prescriptions-panel.component';
import { PatientSecurityPanelComponent } from './components/patient-security-panel/patient-security-panel.component';

@Component({
  selector: 'app-patient',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    ChatComponent,
    CallComponent,
    PatientDashboardHeaderComponent,
    PatientDashboardTabsComponent,
    PatientOverviewPanelComponent,
    PatientAppointmentsPanelComponent,
    PatientProfilePanelComponent,
    PatientDoctorsPanelComponent,
    PatientEhrPanelComponent,
    PatientPrescriptionsPanelComponent,
    PatientSecurityPanelComponent
  ],
  templateUrl: './patient.component.html',
  styleUrl: './patient.component.scss'
})
export class PatientComponent implements OnInit, AfterViewInit {
  @ViewChild(ChatComponent) chatComponent?: ChatComponent;
  
  appointments: Appointment[] = [];
  doctors: any[] = [];
  patientInfo: any = null;
  patientProfile: PatientProfile | null = null;
  loading = false;
  error: string | null = null;
  currentUser: UserInfo | null = null;
  activeTab: string = 'overview';
  patientId: string | null = null;
  showEditProfile = false;
  editUserData: any = {
    firstName: '',
    lastName: '',
    phoneNumber: ''
  };
  editProfileData: PatientUpdateRequest = {
    emergencyContactName: '',
    emergencyContactPhone: '',
    bloodType: '',
    allergies: [],
    // Enterprise fields
    dateOfBirth: '',
    gender: '',
    streetAddress: '',
    city: '',
    state: '',
    zipCode: '',
    country: '',
    insuranceProvider: '',
    insurancePolicyNumber: '',
    medicalHistorySummary: '',
    currentMedications: [],
    primaryCarePhysicianName: '',
    primaryCarePhysicianPhone: '',
    preferredLanguage: '',
    occupation: '',
    maritalStatus: ''
  };
  newAllergy: string = '';
  newMedication: string = '';

  newAppointment = {
    doctorId: '',
    scheduledDate: '',
    scheduledTime: ''
    // durationInMinutes is not needed - always defaults to 30 for patients
  };
  showRequestForm = false;
  availableSlots: string[] = [];
  loadingSlots = false;
  selectedDate: string = '';

  chatUnreadCount: number = 0;
  showChatWidget = false;
  showChatMenu = false;
  chatSearchQuery: string = '';
  chatSearchResults: ChatUser[] = [];
  filteredConversations: Conversation[] = [];
  conversations: Conversation[] = [];
  showBlockedUsers = false;
  blockedUsers: ChatUser[] = [];
  isLoadingBlockedUsers = false;
  private searchTimeout: any = null;
  notifications: Notification[] = [];
  notificationCount: number = 0;
  showNotifications: boolean = false;

  // New features data
  medicalRecords: MedicalRecord[] = [];
  vitalSigns: VitalSigns[] = [];
  labResults: LabResult[] = [];
  prescriptions: Prescription[] = [];
  latestVitalSigns: VitalSigns | null = null;
  twoFAEnabled = false;
  twoFAStatus: any = null;
  show2FAModal = false;
  qrCodeUrl: string = '';
  twoFASecretKey: string = '';
  twoFABackupCodes: string[] = [];
  twoFACodeInput: string = '';

  constructor(
    private appointmentService: AppointmentService,
    public userService: UserService,
    private auth: AuthService,
    private router: Router,
    private chatService: ChatService,
    private notificationService: NotificationService,
    private medicalRecordService: MedicalRecordService,
    private prescriptionService: PrescriptionService,
    private twoFactorAuthService: TwoFactorAuthService,
    private modalService: ModalService,
    private logger: LoggerService
  ) {}

  async ngOnInit() {
    await this.loadUserAndAppointments();
    
    // Connect to chat service and initialize notifications
    await this.chatService.connect();
    await this.notificationService.refreshUserId();
    
    // Load conversations immediately so notification service can detect unread messages
    await this.chatService.getConversations();
    
    this.chatService.conversations$.subscribe((conversations: Conversation[]) => {
      this.conversations = conversations;
      this.chatUnreadCount = conversations.reduce((sum, c) => sum + c.unreadCount, 0);
      if (this.chatSearchQuery) {
        const queryLower = this.chatSearchQuery.toLowerCase();
        this.filteredConversations = conversations.filter(conv =>
          conv.otherUserName?.toLowerCase().includes(queryLower)
        );
      }
    });
    
    // Subscribe to notifications - Enterprise notification management
    // Business Logic:
    // 1. Show only message and missed-call notifications (relevant to user)
    // 2. Hide message notifications from active conversation (user is already viewing that chat)
    // 3. Always show missed-call notifications (high priority, requires attention)
    // 4. Show all other message notifications (from users not currently chatting)
    this.notificationService.notifications$.subscribe(notifications => {
      // Get all notifications first
      const allNotifications = notifications;
      
      // Filter to only show message and missed-call notifications
      const relevantNotifications = allNotifications.filter(n => 
        n.type === 'message' || n.type === 'missed-call'
      );
      
      // Apply enterprise filtering: exclude notifications from active conversation
      // This prevents duplicate notifications when user is actively viewing a chat
      this.notifications = relevantNotifications.filter(n => {
        // Missed calls are always shown (high priority)
        if (n.type === 'missed-call') {
          return true;
        }
        
        // Message notifications: hide if from active conversation
        if (n.type === 'message') {
          // Use enterprise method to check if notification is from active conversation
          return !this.notificationService.isNotificationFromActiveConversation(n);
        }
        
        return false;
      });
      
      // Calculate unread count (only for displayed notifications)
      this.notificationCount = this.notifications.filter(n => !n.read).length;
      
      this.logger.debug('PatientComponent: Notification management updated', {
        totalNotifications: allNotifications.length,
        relevantNotifications: relevantNotifications.length,
        displayedNotifications: this.notifications.length,
        unreadCount: this.notificationCount,
        activeConversation: this.notificationService.getActiveConversationUserId()
      });
    });
    
    // Force check for unread messages after a short delay to ensure notifications are created
    setTimeout(async () => {
      await this.notificationService.checkForUnreadMessages();
    }, 3000);
  }

  ngAfterViewInit(): void {
    // ViewChild is available after view init
  }

  toggleNotifications(): void {
    this.showNotifications = !this.showNotifications;
    
    // When opening notifications dropdown, mark all visible notifications as read
    // This removes the indicator but keeps the notifications
    if (this.showNotifications) {
      // Mark all unread notifications as read when dropdown is opened
      const unreadNotifications = this.notifications.filter(n => !n.read);
      unreadNotifications.forEach(notification => {
        this.notificationService.markAsRead(notification.id);
      });
    }
  }

  @HostListener('document:click', ['$event'])
  onDocumentClick(event: MouseEvent): void {
    const target = event.target as HTMLElement;
    
    if (target.closest('.unblock-button-dropdown')) {
      return;
    }

    if (!target.closest('.notification-container')) {
      this.showNotifications = false;
    }
    if (!target.closest('.chat-menu-container')) {
      if (this.showChatMenu) {
        this.clearChatSearch();
      }
      this.showChatMenu = false;
    }
    if (!target.closest('.blocked-users-container')) {
      this.showBlockedUsers = false;
    }
  }

  markNotificationAsRead(notificationId: string): void {
    this.notificationService.markAsRead(notificationId);
  }

  markAllNotificationsAsRead(): void {
    this.notificationService.markAllAsRead();
  }

  deleteNotification(notificationId: string, event?: Event): void {
    if (event) {
      event.stopPropagation(); // Prevent triggering navigation when clicking delete
    }
    this.notificationService.deleteNotification(notificationId);
  }

  deleteAllNotifications(): void {
    this.notificationService.deleteAllNotifications();
  }

  async handleNotificationClick(notification: Notification): Promise<void> {
    // Mark as read when clicked
    if (!notification.read) {
      this.notificationService.markAsRead(notification.id);
    }
    
    // Close notification dropdown and open chat widget
    this.showNotifications = false;
    this.showChatWidget = true;
    this.showChatMenu = false;
    
    // If notification has actionUrl with userId, try to open that conversation
    if (notification.actionUrl) {
      const urlParams = new URLSearchParams(notification.actionUrl.split('?')[1]);
      const userId = urlParams.get('userId');
      if (userId) {
        // Small delay to ensure tab switch happens first, then open conversation
        setTimeout(async () => {
          // Try to get chat component reference (it might not be available if tab isn't active)
          let attempts = 0;
          const maxAttempts = 10;
          const checkChatComponent = setInterval(async () => {
            attempts++;
            if (this.chatComponent) {
              clearInterval(checkChatComponent);
              await this.chatComponent.openConversation(userId);
            } else if (attempts >= maxAttempts) {
              clearInterval(checkChatComponent);
              this.logger.warn('ChatComponent not available after switching to chat tab');
            }
          }, 100);
          
          // Stop checking after 2 seconds
          setTimeout(() => clearInterval(checkChatComponent), 2000);
        }, 300);
      }
    }
  }

  getNotificationTime(timestamp: Date): string {
    const now = new Date();
    const diffMs = now.getTime() - timestamp.getTime();
    const diffMins = Math.floor(diffMs / 60000);
    
    if (diffMins < 1) return 'Just now';
    if (diffMins < 60) return `${diffMins}m ago`;
    if (diffMins < 1440) return `${Math.floor(diffMins / 60)}h ago`;
    
    return timestamp.toLocaleDateString();
  }

  toggleChatWidget(): void {
    this.showChatWidget = !this.showChatWidget;
    if (!this.showChatWidget) {
      this.showChatMenu = false;
    }
  }

  toggleChatMenu(): void {
    this.showChatMenu = !this.showChatMenu;
    if (this.showChatMenu) {
      this.showBlockedUsers = false;
      if (this.chatComponent) {
        this.chatComponent.refreshConversations();
      }
    } else {
      this.clearChatSearch();
    }
  }

  toggleBlockedUsers(event?: Event): void {
    event?.stopPropagation();
    this.showBlockedUsers = !this.showBlockedUsers;
    if (this.showBlockedUsers) {
      this.loadBlockedUsers();
      this.showChatMenu = false;
    }
  }

  async loadBlockedUsers(): Promise<void> {
    this.isLoadingBlockedUsers = true;
    try {
      this.blockedUsers = await this.chatService.getBlockedUsersWithDetails();
    } catch (error) {
      this.logger.error('Error loading blocked users:', error);
      this.blockedUsers = [];
    } finally {
      this.isLoadingBlockedUsers = false;
    }
  }

  async unblockUser(user: ChatUser): Promise<void> {
    try {
      const userId = String(user.userId).trim();
      if (!userId) {
        throw new Error('Invalid user ID');
      }
      await this.chatService.unblockUser(userId);
      this.blockedUsers = this.blockedUsers.filter(u => u.userId !== user.userId);
      if (this.chatComponent) {
        await this.chatComponent.refreshConversations();
      }
      await this.modalService.alert(
        `${user.firstName} ${user.lastName} has been unblocked successfully.`,
        'success',
        'User Unblocked'
      );
    } catch (error: any) {
      this.logger.error('Error unblocking user:', error);
      await this.modalService.alert(
        error?.response?.data?.error || 'Failed to unblock user',
        'error',
        'Unblock Error'
      );
    }
  }

  async openChatConversation(otherUserId: string): Promise<void> {
    if (!this.chatComponent) {
      this.logger.warn('ChatComponent not available');
      return;
    }
    const conversation = this.chatComponent.conversations.find(c => c.otherUserId === otherUserId);
    if (conversation) {
      await this.chatComponent.selectConversation(conversation);
      this.showChatMenu = false;
      this.showChatWidget = true;
    }
  }

  async openChatWithUser(userId: string): Promise<void> {
    if (!this.chatComponent) {
      this.logger.warn('ChatComponent not available');
      return;
    }
    this.showChatWidget = true;
    this.showChatMenu = false;

    const existingConversation = this.chatComponent.conversations.find(c => c.otherUserId === userId);
    if (existingConversation) {
      await this.chatComponent.selectConversation(existingConversation);
    } else {
      await this.chatComponent.openConversation(userId);
    }
    this.clearChatSearch();
  }

  onChatSearch(query: string): void {
    const trimmedQuery = query.trim();
    this.chatSearchQuery = trimmedQuery;

    if (this.searchTimeout) {
      clearTimeout(this.searchTimeout);
    }

    if (!trimmedQuery) {
      this.chatSearchResults = [];
      this.filteredConversations = [];
      return;
    }

    const queryLower = trimmedQuery.toLowerCase();
    if (this.conversations.length > 0) {
      this.filteredConversations = this.conversations.filter(conv =>
        conv.otherUserName?.toLowerCase().includes(queryLower)
      );
    } else {
      this.filteredConversations = [];
    }

    if (trimmedQuery.length < 2) {
      this.chatSearchResults = [];
      return;
    }

    this.searchTimeout = setTimeout(async () => {
      try {
        const existingUserIds = this.conversations.map(c => c.otherUserId);
        if (this.currentUser?.role === 'DOCTOR') {
          const users = await this.chatService.searchPatients(trimmedQuery);
          this.chatSearchResults = users.filter(user => !existingUserIds.includes(user.userId));
        } else {
          const users = await this.chatService.searchDoctors(trimmedQuery);
          this.chatSearchResults = users.filter(user => !existingUserIds.includes(user.userId));
        }
      } catch (error) {
        this.logger.error('Error searching users:', error);
        this.chatSearchResults = [];
      }
    }, 300);
  }

  clearChatSearch(): void {
    this.chatSearchQuery = '';
    this.chatSearchResults = [];
    this.filteredConversations = [];
  }

  getConversationTime(timestamp: string | Date): string {
    if (!timestamp) return '';
    const date = new Date(timestamp);
    const now = new Date();
    const diffMs = now.getTime() - date.getTime();
    const diffMins = Math.floor(diffMs / 60000);
    const diffHours = Math.floor(diffMs / 3600000);
    const diffDays = Math.floor(diffMs / 86400000);

    if (diffMins < 1) return 'Now';
    if (diffMins < 60) return `${diffMins}m`;
    if (diffHours < 24) return `${diffHours}h`;
    if (diffDays < 7) return `${diffDays}d`;

    return date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
  }

  onChatImageError(event: Event): void {
    const img = event.target as HTMLImageElement;
    img.style.display = 'none';
    const avatarCircle = img.nextElementSibling as HTMLElement;
    if (avatarCircle && avatarCircle.classList.contains('avatar-circle')) {
      avatarCircle.style.display = 'flex';
    }
  }

  getStatusText(status: string | undefined): string {
    if (!status) return 'Offline';
    switch (status) {
      case 'ONLINE':
        return 'Online';
      case 'BUSY':
        return 'Busy';
      case 'OFFLINE':
        return 'Offline';
      default:
        return status;
    }
  }

  async onFileSelected(event: Event): Promise<void> {
    const input = event.target as HTMLInputElement;
    if (input.files && input.files.length > 0) {
      const file = input.files[0];
      try {
        const avatarUrl = await this.userService.uploadAvatar(file);
        // Refresh current user to get updated avatar
        this.currentUser = await this.userService.getCurrentUser();
        // Reload patient profile if available
        if (this.currentUser) {
          this.patientProfile = await this.userService.getPatientProfile();
        }
      } catch (error: any) {
        this.logger.error('Error uploading avatar:', error);
        await this.modalService.alert(
          error?.response?.data?.error || 'Failed to upload avatar. Please try again.',
          'error',
          'Upload Error'
        );
      }
    }
  }

  async loadUserAndAppointments() {
    this.loading = true;
    this.error = null;
    try {
      this.currentUser = await this.userService.getCurrentUser();
      if (!this.currentUser) {
        throw new Error('Unable to load user information');
      }

      // Load patient profile first to get the patient ID
      this.patientProfile = await this.userService.getPatientProfile();
      if (this.patientProfile?.id) {
        this.patientId = this.patientProfile.id;
      }

      await Promise.all([
        this.loadAppointments(),
        this.loadDoctors(),
        this.loadPatientInfo(),
        this.loadEHRData(),
        this.loadPrescriptions(),
        this.load2FAStatus()
      ]);
    } catch (e: any) {
      if (e?.response?.status === 401) {
        await this.auth.logout();
        this.router.navigateByUrl('/login');
        return;
      }
      this.error = e?.response?.data?.message || 'Failed to load dashboard data';
    } finally {
      this.loading = false;
    }
  }

  async loadAppointments() {
    try {
      if (!this.patientId) {
        // If patientId is not set, try to get it from profile
        if (!this.patientProfile) {
          this.patientProfile = await this.userService.getPatientProfile();
        }
        if (this.patientProfile?.id) {
          this.patientId = this.patientProfile.id;
        } else {
          this.logger.warn('Patient ID not available, cannot load appointments');
          this.appointments = [];
          return;
        }
      }

      if (this.patientId) {
        this.appointments = await this.appointmentService.getAppointmentsByPatientId(this.patientId);
      } else {
        this.appointments = [];
      }
    } catch (e: any) {
      this.logger.error('Error loading appointments:', e);
      this.appointments = [];
    }
  }

  async loadDoctors() {
    try {
      // First, extract doctors from appointments (only shows doctors with non-deleted appointments)
      this.extractDoctorsFromAppointments();
      
      // If we have appointments, we already have the doctors
      // Otherwise, fallback to loading all doctors (for dropdowns, etc.)
      if (this.doctors.length === 0) {
        this.doctors = await this.userService.getAllDoctors();
      }
    } catch (e: any) {
      this.logger.error('Error loading doctors:', e);
      // Fallback: try to extract from appointments
      this.extractDoctorsFromAppointments();
      // If still empty, load all doctors
      if (this.doctors.length === 0) {
        this.doctors = await this.userService.getAllDoctors();
      }
    }
  }
  
  extractDoctorsFromAppointments() {
    // Extract unique doctors from appointments (only those with non-deleted appointments)
    const doctorMap = new Map<string, any>();
    this.appointments.forEach(apt => {
      const doctorKey = `${apt.doctorFirstName}-${apt.doctorLastName}`;
      if (!doctorMap.has(doctorKey)) {
        doctorMap.set(doctorKey, {
          id: (apt as any).doctorId || '',
          firstName: apt.doctorFirstName,
          lastName: apt.doctorLastName,
          email: '',
          displayName: `Dr. ${apt.doctorFirstName} ${apt.doctorLastName}`
        });
      }
    });
    this.doctors = Array.from(doctorMap.values());
  }

  async loadPatientInfo() {
    try {
      // Use the already-loaded patientProfile instead of calling admin endpoint
      // Combine patientProfile with currentUser to create patientInfo structure
      if (this.patientProfile && this.currentUser) {
        this.patientInfo = {
          ...this.patientProfile,
          user: {
            id: this.currentUser.id,
            email: this.currentUser.email,
            firstName: this.currentUser.firstName,
            lastName: this.currentUser.lastName,
            phoneNumber: this.currentUser.phoneNumber,
            isActive: this.currentUser.isActive
          }
        };
      } else {
        // If patientProfile wasn't loaded yet, try to load it
        if (!this.patientProfile) {
          this.patientProfile = await this.userService.getPatientProfile();
        }
        if (this.patientProfile && this.currentUser) {
          this.patientInfo = {
            ...this.patientProfile,
            user: {
              id: this.currentUser.id,
              email: this.currentUser.email,
              firstName: this.currentUser.firstName,
              lastName: this.currentUser.lastName,
              phoneNumber: this.currentUser.phoneNumber,
              isActive: this.currentUser.isActive
            }
          };
        }
      }
    } catch (e: any) {
      this.logger.error('Error loading patient info:', e);
      this.patientInfo = null;
    }
  }

  async refresh() {
    await this.loadUserAndAppointments();
  }

  async requestAppointment() {
    if (!this.newAppointment.doctorId || !this.newAppointment.scheduledDate || !this.newAppointment.scheduledTime) {
      this.error = 'Please fill in all required fields and select an available time slot';
      return;
    }

    if (!this.currentUser || !this.patientId) {
      this.error = 'Patient information not available. Please refresh the page.';
      return;
    }

    try {
      // Get doctor's default duration, fallback to 30 if not set
      const selectedDoctor = this.doctors.find(d => d.id === this.newAppointment.doctorId);
      const durationMinutes = selectedDoctor?.defaultDurationMinutes || 30;
      
      await this.appointmentService.createAppointment({
        patientId: this.patientId,
        doctorId: this.newAppointment.doctorId,
        scheduledDate: this.newAppointment.scheduledDate,
        scheduledTime: this.newAppointment.scheduledTime,
        durationMinutes: durationMinutes // Use doctor's default duration
      });
      
      this.showRequestForm = false;
      this.newAppointment = {
        doctorId: '',
        scheduledDate: '',
        scheduledTime: ''
        // durationInMinutes is always 30 for patients
      };
      this.availableSlots = [];
      this.selectedDate = '';
      await this.refresh();
      this.error = null;
    } catch (e: any) {
      this.logger.error('Error creating appointment:', e);
      this.logger.error('Error response:', e?.response?.data);
      
      // Handle validation errors
      if (e?.response?.status === 400) {
        const errorData = e?.response?.data;
        if (typeof errorData === 'string') {
          this.error = errorData;
        } else if (errorData?.message) {
          this.error = errorData.message;
        } else if (errorData && typeof errorData === 'object') {
          // Handle field-specific validation errors
          const errorMessages = Object.values(errorData).filter((msg: any) => typeof msg === 'string');
          this.error = errorMessages.length > 0 
            ? errorMessages.join(', ') 
            : 'Validation failed. Please check all fields.';
        } else {
          this.error = 'Failed to request appointment. Please check all required fields.';
        }
      } else {
        this.error = e?.response?.data?.message || 'Failed to request appointment. Please try again.';
      }
    }
  }

  async loadAvailableSlots() {
    if (!this.newAppointment.doctorId || !this.newAppointment.scheduledDate) {
      this.availableSlots = [];
      return;
    }

    // Only load if date changed
    if (this.selectedDate === this.newAppointment.scheduledDate) {
      return;
    }

    this.selectedDate = this.newAppointment.scheduledDate;
    this.loadingSlots = true;
    this.availableSlots = [];

    try {
      // Get doctor's default duration from doctors list
      const selectedDoctor = this.doctors.find(d => d.id === this.newAppointment.doctorId);
      
      // Only pass durationMinutes if it's explicitly set in the frontend (should not happen)
      // Otherwise, let backend use doctor's defaultDurationMinutes from database
      // This ensures the backend always uses the most up-to-date doctor setting
      const durationMinutes = undefined; // Always let backend determine from doctor's default
      
      this.availableSlots = await this.appointmentService.getAvailableTimeSlots(
        this.newAppointment.doctorId,
        this.newAppointment.scheduledDate,
        durationMinutes // Pass undefined so backend uses doctor's defaultDurationMinutes from DB
      );
    } catch (e: any) {
      this.logger.error('Error loading available slots:', e);
      this.error = 'Failed to load available time slots';
      this.availableSlots = [];
    } finally {
      this.loadingSlots = false;
    }
  }

  onDoctorChange() {
    this.availableSlots = [];
    this.selectedDate = '';
    this.newAppointment.scheduledTime = '';
    if (this.newAppointment.scheduledDate) {
      this.loadAvailableSlots();
    }
  }

  onDateChange() {
    this.newAppointment.scheduledTime = '';
    if (this.newAppointment.doctorId && this.newAppointment.scheduledDate) {
      this.loadAvailableSlots();
    }
  }

  selectTimeSlot(time: string) {
    this.newAppointment.scheduledTime = time;
  }

  async cancelAppointment(appointment: Appointment) {
    if (!appointment.id) {
      this.error = 'Appointment ID not available. Backend needs to include ID in response.';
      return;
    }
    const confirmed = await this.modalService.confirm(
      'Are you sure you want to cancel this appointment?',
      'Cancel Appointment',
      'Cancel Appointment',
      'Keep Appointment'
    );
    if (!confirmed) return;
    
    try {
      await this.appointmentService.cancelAppointment(appointment.id);
      await this.refresh();
    } catch (e: any) {
      this.error = e?.response?.data?.message || 'Failed to cancel appointment';
    }
  }

  async deleteAppointment(appointment: Appointment) {
    if (!appointment.id) {
      this.error = 'Appointment ID not available. Backend needs to include ID in response.';
      return;
    }
    const confirmed = await this.modalService.confirm(
      'Are you sure you want to delete this appointment? This action cannot be undone.',
      'Delete Appointment',
      'Delete',
      'Cancel'
    );
    if (!confirmed) {
      return;
    }
    
    try {
      await this.appointmentService.deleteAppointment(appointment.id);
      await this.refresh();
      this.error = null;
    } catch (e: any) {
      this.error = e?.response?.data?.message || e?.message || 'Failed to delete appointment';
    }
  }

  // Note: Patients cannot confirm appointments - only doctors can confirm
  // Appointments are auto-confirmed when created if the slot is available
  // This method is kept for backward compatibility but should not be called from UI
  async confirmAppointment(appointment: Appointment) {
    this.error = 'Only doctors can confirm appointments. Your appointment will be automatically confirmed if the slot is available.';
  }

  setTab(tab: string) {
    this.activeTab = tab;
  }

  async logout() {
    // Update online status and disconnect WebSocket before removing token
    try {
      await this.chatService.disconnect();
    } catch (error) {
      // Ignore errors during logout
    }
    await this.auth.logout();
    this.router.navigateByUrl('/login');
  }

  formatDate(dateString: string): string {
    if (!dateString) return 'N/A';
    const date = new Date(dateString);
    return date.toLocaleDateString();
  }

  formatTime(timeString: string): string {
    if (!timeString) return 'N/A';
    return timeString.substring(0, 5);
  }

  getStatusClass(status: string): string {
    const statusLower = status?.toLowerCase() || '';
    if (statusLower === 'completed') return 'status-completed';
    if (statusLower === 'confirmed') return 'status-confirmed';
    if (statusLower === 'cancelled') return 'status-cancelled';
    return 'status-scheduled';
  }

  getUpcomingAppointments(): Appointment[] {
    const now = new Date();
    return this.appointments
      .filter(apt => {
        const aptDate = new Date(`${apt.scheduledDate}T${apt.scheduledTime}`);
        return aptDate >= now && apt.status !== 'CANCELLED' && apt.status !== 'COMPLETED';
      })
      .sort((a, b) => {
        const dateA = new Date(`${a.scheduledDate}T${a.scheduledTime}`);
        const dateB = new Date(`${b.scheduledDate}T${b.scheduledTime}`);
        return dateA.getTime() - dateB.getTime();
      });
  }

  getPastAppointments(): Appointment[] {
    const now = new Date();
    return this.appointments
      .filter(apt => {
        const aptDate = new Date(`${apt.scheduledDate}T${apt.scheduledTime}`);
        return aptDate < now || apt.status === 'CANCELLED' || apt.status === 'COMPLETED';
      })
      .sort((a, b) => {
        const dateA = new Date(`${a.scheduledDate}T${a.scheduledTime}`);
        const dateB = new Date(`${b.scheduledDate}T${b.scheduledTime}`);
        return dateB.getTime() - dateA.getTime();
      });
  }

  getTotalAppointments(): number {
    return this.appointments.length;
  }

  getUpcomingCount(): number {
    return this.getUpcomingAppointments().length;
  }

  getCompletedCount(): number {
    return this.appointments.filter(apt => apt.status === 'COMPLETED').length;
  }

  getCancelledCount(): number {
    return this.appointments.filter(apt => apt.status === 'CANCELLED').length;
  }

  getTodayDate(): string {
    const today = new Date();
    const year = today.getFullYear();
    const month = String(today.getMonth() + 1).padStart(2, '0');
    const day = String(today.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  }

  getVerifiedDoctors(): any[] {
    return this.doctors.filter((d: any) => d.isVerified === true);
  }

  selectedDoctorProfile: any = null;
  showDoctorProfileModal = false;

  async viewDoctorProfile(doctorId: string) {
    try {
      this.selectedDoctorProfile = await this.userService.getDoctorProfileById(doctorId);
      this.showDoctorProfileModal = true;
    } catch (e: any) {
      this.error = e?.message || 'Failed to load doctor profile';
      this.logger.error('Failed to load doctor profile:', e);
    }
  }

  async removeDoctorFromHistory(doctor: any, event?: Event) {
    event?.stopPropagation(); // Prevent card click
    
    const confirmed = await this.modalService.confirm(
      `Are you sure you want to remove Dr. ${doctor.firstName} ${doctor.lastName} from your history? This will hide all appointments with this doctor from your view. This action cannot be undone.`,
      'Remove Doctor from History',
      'warning'
    );
    
    if (!confirmed) return;

    try {
      this.loading = true;
      await this.appointmentService.removeDoctorFromHistory(doctor.id);
      await this.modalService.alert(
        'Doctor removed from history successfully',
        'success',
        'Success'
      );
      
      // Refresh appointments and doctors
      await Promise.all([
        this.loadAppointments(),
        this.loadDoctors()
      ]);
    } catch (error: any) {
      this.logger.error('Error removing doctor from history:', error);
      await this.modalService.alert(
        error?.message || 'Failed to remove doctor from history',
        'error',
        'Error'
      );
    } finally {
      this.loading = false;
    }
  }

  closeDoctorProfileModal() {
    this.showDoctorProfileModal = false;
    this.selectedDoctorProfile = null;
  }

  async loadPatientProfile() {
    try {
      this.patientProfile = await this.userService.getPatientProfile();
      if (this.patientProfile?.id && !this.patientId) {
        this.patientId = this.patientProfile.id;
      }
    } catch (e: any) {
      this.logger.error('Failed to load patient profile:', e);
      this.patientProfile = null;
    }
  }

  async updateUserProfile() {
    // This method is not used anymore - updatePatientProfile handles both
    return;
  }

  async updatePatientProfile() {
    try {
      // Update user profile if fields are provided
      const hasUserChanges = this.editUserData.firstName || this.editUserData.lastName || this.editUserData.phoneNumber;
      if (hasUserChanges) {
        await this.userService.updateUserProfile(this.editUserData);
      }
      
      // Update patient profile
      await this.userService.updatePatientProfile(this.editProfileData);
      await this.loadPatientProfile();
      await this.loadUserAndAppointments();
      this.showEditProfile = false;
      this.editUserData = {
        firstName: '',
        lastName: '',
        phoneNumber: ''
      };
      this.editProfileData = {
        emergencyContactName: '',
        emergencyContactPhone: '',
        bloodType: '',
        allergies: [],
        // Enterprise fields - reset to empty
        dateOfBirth: '',
        gender: '',
        streetAddress: '',
        city: '',
        state: '',
        zipCode: '',
        country: '',
        insuranceProvider: '',
        insurancePolicyNumber: '',
        medicalHistorySummary: '',
        currentMedications: [],
        primaryCarePhysicianName: '',
        primaryCarePhysicianPhone: '',
        preferredLanguage: '',
        occupation: '',
        maritalStatus: ''
      };
    } catch (e: any) {
      this.error = e?.response?.data?.message || 'Failed to update patient profile';
    }
  }

  addAllergy() {
    if (this.newAllergy.trim() && this.editProfileData.allergies) {
      this.editProfileData.allergies.push(this.newAllergy.trim());
      this.newAllergy = '';
    }
  }

  removeAllergy(index: number) {
    if (this.editProfileData.allergies) {
      this.editProfileData.allergies.splice(index, 1);
    }
  }

  addMedication() {
    if (this.newMedication && this.newMedication.trim()) {
      if (!this.editProfileData.currentMedications) {
        this.editProfileData.currentMedications = [];
      }
      this.editProfileData.currentMedications.push(this.newMedication.trim());
      this.newMedication = '';
    }
  }

  removeMedication(index: number) {
    if (this.editProfileData.currentMedications) {
      this.editProfileData.currentMedications.splice(index, 1);
    }
  }

  editProfile() {
    // Ensure currentUser is loaded
    if (!this.currentUser) {
      this.logger.error('Current user not loaded');
      return;
    }
    // Ensure patientProfile is loaded
    if (!this.patientProfile) {
      this.logger.error('Patient profile not loaded');
      return;
    }
    // Use patientProfile instead of patientInfo
    this.editUserData = {
      firstName: this.currentUser.firstName || '',
      lastName: this.currentUser.lastName || '',
      phoneNumber: this.currentUser.phoneNumber || ''
    };
    this.editProfileData = {
      emergencyContactName: this.patientProfile.emergencyContactName || '',
      emergencyContactPhone: this.patientProfile.emergencyContactPhone || '',
      bloodType: this.patientProfile.bloodType || '',
      allergies: [...(this.patientProfile.allergies || [])],
      // Enterprise fields
      dateOfBirth: this.patientProfile.dateOfBirth || '',
      gender: this.patientProfile.gender || '',
      streetAddress: this.patientProfile.streetAddress || '',
      city: this.patientProfile.city || '',
      state: this.patientProfile.state || '',
      zipCode: this.patientProfile.zipCode || '',
      country: this.patientProfile.country || '',
      insuranceProvider: this.patientProfile.insuranceProvider || '',
      insurancePolicyNumber: this.patientProfile.insurancePolicyNumber || '',
      medicalHistorySummary: this.patientProfile.medicalHistorySummary || '',
      currentMedications: [...(this.patientProfile.currentMedications || [])],
      primaryCarePhysicianName: this.patientProfile.primaryCarePhysicianName || '',
      primaryCarePhysicianPhone: this.patientProfile.primaryCarePhysicianPhone || '',
      preferredLanguage: this.patientProfile.preferredLanguage || '',
      occupation: this.patientProfile.occupation || '',
      maritalStatus: this.patientProfile.maritalStatus || ''
    };
    this.showEditProfile = true;
  }

  // New feature loading methods
  async loadEHRData() {
    if (!this.patientId) return;
    try {
      [this.medicalRecords, this.vitalSigns, this.labResults, this.latestVitalSigns] = await Promise.all([
        this.medicalRecordService.getMedicalRecordsByPatientId(this.patientId),
        this.medicalRecordService.getVitalSignsByPatientId(this.patientId),
        this.medicalRecordService.getLabResultsByPatientId(this.patientId),
        this.medicalRecordService.getLatestVitalSignsByPatientId(this.patientId)
      ]);
    } catch (e: any) {
      this.logger.error('Error loading EHR data:', e);
      this.medicalRecords = [];
      this.vitalSigns = [];
      this.labResults = [];
    }
  }

  async loadPrescriptions() {
    if (!this.patientId) return;
    try {
      this.prescriptions = await this.prescriptionService.getPrescriptionsByPatientId(this.patientId);
    } catch (e: any) {
      this.logger.error('Error loading prescriptions:', e);
      this.prescriptions = [];
    }
  }

  async load2FAStatus() {
    try {
      this.twoFAStatus = await this.twoFactorAuthService.get2FAStatus();
      this.twoFAEnabled = this.twoFAStatus?.enabled || false;
    } catch (e: any) {
      this.logger.error('Error loading 2FA status:', e);
      this.twoFAEnabled = false;
    }
  }

  async setup2FA() {
    try {
      const setup = await this.twoFactorAuthService.setup2FA();
      this.qrCodeUrl = setup.qrCodeUrl;
      this.twoFASecretKey = setup.secretKey;
      this.twoFABackupCodes = setup.backupCodes || [];
      this.twoFACodeInput = '';
      this.show2FAModal = true;
    } catch (e: any) {
      await this.modalService.alert(
        e?.response?.data?.error || 'Failed to setup 2FA',
        'error',
        '2FA Setup Error'
      );
    }
  }

  async verifyAndEnable2FA() {
    if (!this.twoFACodeInput || this.twoFACodeInput.length !== 6) {
      await this.modalService.alert(
        'Please enter a valid 6-digit code',
        'warning',
        'Invalid Code'
      );
      return;
    }
    try {
      await this.twoFactorAuthService.enable2FA(this.twoFACodeInput);
      await this.load2FAStatus();
      this.show2FAModal = false;
      await this.modalService.alert(
        '2FA enabled successfully! Please save your backup codes: ' + this.twoFABackupCodes.join(', '),
        'success',
        '2FA Enabled'
      );
    } catch (e: any) {
      await this.modalService.alert(
        e?.response?.data?.error || 'Failed to enable 2FA',
        'error',
        '2FA Error'
      );
    }
  }

  close2FAModal() {
    this.show2FAModal = false;
    this.qrCodeUrl = '';
    this.twoFASecretKey = '';
    this.twoFABackupCodes = [];
    this.twoFACodeInput = '';
  }

  async disable2FA() {
    const code = await this.modalService.prompt(
      'Enter your 2FA code or backup code to disable two-factor authentication:',
      'Disable 2FA',
      '2FA Code',
      'Enter 2FA code or backup code',
      'text',
      'Disable',
      'Cancel'
    );
    if (!code) return;
    try {
      await this.twoFactorAuthService.disable2FA(code);
      await this.load2FAStatus();
      await this.modalService.alert(
        '2FA disabled successfully',
        'success',
        '2FA Disabled'
      );
    } catch (e: any) {
      await this.modalService.alert(
        e?.response?.data?.error || 'Failed to disable 2FA',
        'error',
        '2FA Error'
      );
    }
  }
}