import { Component, OnInit, OnDestroy, HostListener, ViewChild, AfterViewInit, ViewEncapsulation } 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, DoctorProfile, DoctorUpdateRequest, UserUpdateRequest } from '../../services/user.service';
import { AdminService } from '../../services/admin.service';
import { AvailabilityService, AvailabilityRequest, AvailabilityResponse, BulkAvailabilityRequest } from '../../services/availability.service';
import { ChatComponent } from '../../components/chat/chat.component';
import { ChatService, ChatUser } from '../../services/chat.service';
import { NotificationService, Notification } from '../../services/notification.service';
import { CallComponent } from '../../components/call/call.component';
import { MedicalRecordService, MedicalRecord, MedicalRecordRequest, VitalSigns, VitalSignsRequest, LabResultRequest } from '../../services/medical-record.service';
import { PrescriptionService, Prescription, PrescriptionRequest } from '../../services/prescription.service';
import { TwoFactorAuthService } from '../../services/two-factor-auth.service';
import { PatientSafetyService, ClinicalAlert, CriticalResult } from '../../services/patient-safety.service';
import { LoggerService } from '../../services/logger.service';
import { AppointmentsComponent } from './components/appointments/appointments.component';
import { CreateAppointmentComponent } from './components/create-appointment/create-appointment.component';
import { AvailabilityComponent } from './components/availability/availability.component';
import { PatientsComponent } from './components/patients/patients.component';
import { ProfileComponent } from './components/profile/profile.component';
import { EhrComponent } from './components/ehr/ehr.component';
import { PrescriptionsComponent } from './components/prescriptions/prescriptions.component';
import { SecurityComponent } from './components/security/security.component';
import { ModalService } from '../../services/modal.service';

@Component({
  selector: 'app-doctor',
  standalone: true,
  imports: [
    CommonModule, 
    FormsModule, 
    ChatComponent, 
    CallComponent,
    AppointmentsComponent,
    CreateAppointmentComponent,
    AvailabilityComponent,
    PatientsComponent,
    ProfileComponent,
    EhrComponent,
    PrescriptionsComponent,
    SecurityComponent
  ],
  templateUrl: './doctor.component.html',
  styleUrl: './doctor.component.scss',
  encapsulation: ViewEncapsulation.None
})
export class DoctorComponent implements OnInit, AfterViewInit, OnDestroy {
  @ViewChild(ChatComponent) chatComponent?: ChatComponent;
  appointments: Appointment[] = [];
  loading = false;
  error: string | null = null;
  currentUser: UserInfo | null = null;
  doctorId: string | null = null;
  activeTab: string = 'overview';
  showCreateForm = false;
  
  newAppointment = {
    patientId: '',
    scheduledDate: '',
    scheduledTime: '',
    durationInMinutes: 30
  };
  patients: any[] = [];
  
  // Availability
  availability: AvailabilityResponse[] = [];
  showAvailabilityForm = false;
  showBulkAvailabilityForm = false;
  dayFilter: string = 'all';
  newAvailability: AvailabilityRequest = {
    doctorId: '',
    dayOfWeek: 'MONDAY',
    startTime: '09:00',
    endTime: '17:00'
  };
  bulkAvailability: BulkAvailabilityRequest = {
    doctorId: '',
    availabilities: []
  };

  // Profile editing
  showEditProfile = false;
  doctorProfile: DoctorProfile | null = null;
  editUserData: UserUpdateRequest = {
    firstName: '',
    lastName: '',
    phoneNumber: ''
  };
  editDoctorData: DoctorUpdateRequest = {
    medicalLicenseNumber: '',
    specialization: '',
    yearsOfExperience: undefined,
    biography: '',
    consultationFee: undefined,
    defaultDurationMinutes: undefined
  };

  chatUnreadCount: number = 0;
  notifications: Notification[] = [];
  notificationCount: number = 0;
  showNotifications: boolean = false;
  showProfileMenu: boolean = false;
  showChatWidget: boolean = false;
  showChatMenu: boolean = false;
  chatSearchQuery: string = '';
  chatSearchResults: ChatUser[] = [];
  filteredConversations: any[] = [];
  showChatSearchResults: boolean = false;
  
  // Blocked users functionality
  showBlockedUsers: boolean = false;
  blockedUsers: ChatUser[] = [];
  isLoadingBlockedUsers: boolean = false;

  // New features data
  selectedPatientId: string | null = null;
  medicalRecords: MedicalRecord[] = [];
  allMedicalRecords: MedicalRecord[] = []; // All records created by this doctor
  vitalSigns: VitalSigns[] = [];
  latestVitalSigns: VitalSigns | null = null;
  labResults: any[] = [];
  prescriptions: Prescription[] = [];
  allPrescriptions: Prescription[] = []; // All prescriptions created by this doctor
  filteredPrescriptions: Prescription[] = [];
  twoFAEnabled = false;
  twoFAStatus: any = null;
  show2FAModal = false;
  qrCodeUrl: string = '';
  twoFASecretKey: string = '';
  twoFABackupCodes: string[] = [];
  twoFACodeInput: string = '';
  showAllRecords = false; // Toggle to show all records vs patient-specific
  
  // Patient Safety
  unacknowledgedAlerts: ClinicalAlert[] = [];
  unacknowledgedCriticalResults: CriticalResult[] = [];
  unacknowledgedAlertsCount: number = 0;
  selectedPrescription: Prescription | null = null;
  private alertsRefreshInterval?: any; // Interval for auto-refreshing alerts
  showCreateAlertForm = false;
  newAlert = {
    patientId: '',
    alertType: 'DRUG_INTERACTION' as 'DRUG_INTERACTION' | 'ALLERGY' | 'CONTRAINDICATION' | 'OVERDOSE_RISK' | 'DUPLICATE_THERAPY' | 'DOSE_ADJUSTMENT' | 'LAB_RESULT_ALERT' | 'VITAL_SIGN_ALERT' | 'COMPLIANCE_ALERT' | 'OTHER',
    severity: 'WARNING' as 'INFO' | 'WARNING' | 'CRITICAL',
    title: '',
    description: '',
    medicationName: '',
    relatedPrescriptionId: null as string | null
  };
  showUpdatePrescription = false;
  selectedLabResult: any = null;
  showUpdateLabResult = false;
  
  // Prescription Management Enterprise Features
  prescriptionSearchTerm: string = '';
  prescriptionStatusFilter: string = 'all'; // 'all', 'ACTIVE', 'COMPLETED', 'CANCELLED', 'DISCONTINUED'
  prescriptionDateFilter: string = 'all'; // 'all', 'today', 'week', 'month', 'year', 'custom'
  prescriptionDateFrom: string = '';
  prescriptionDateTo: string = '';
  prescriptionSortBy: string = 'createdAt'; // 'createdAt', 'medicationName', 'patientName', 'status', 'startDate'
  prescriptionSortOrder: 'asc' | 'desc' = 'desc';
  prescriptionViewMode: 'card' | 'table' = 'card';
  selectedPrescriptions: string[] = [];
  showPrescriptionAnalytics = false;
  
  // Forms
  showCreateMedicalRecord = false;
  showCreatePrescription = false;
  showPrescriptionDebug = false;
  async openCreatePrescription() {
    this.showCreatePrescription = !this.showCreatePrescription;
    if (this.showCreatePrescription) {
      // Ensure patients are loaded
      if (!this.patients || this.patients.length === 0) {
        this.logger.debug('[OpenCreatePrescription] Loading patients...');
        await this.loadPatients(true); // Load for dropdowns (includes all patients)
      }
      this.logger.debug('[OpenCreatePrescription] Patients loaded:', this.patients?.length || 0);
      
      // Pre-fill patient and doctor in the form if available
      if (this.selectedPatientId) {
        this.newPrescription.patientId = this.selectedPatientId;
        this.logger.debug('[OpenCreatePrescription] Pre-filled patientId from selectedPatientId:', this.selectedPatientId);
      } else if (this.patients && this.patients.length === 1) {
        // If only one patient, auto-select it
        this.newPrescription.patientId = this.patients[0].id;
        this.selectedPatientId = this.patients[0].id;
        this.logger.debug('[OpenCreatePrescription] Auto-selected single patient:', this.patients[0].id);
      }
      
      if (!this.newPrescription.doctorId && this.doctorId) {
        this.newPrescription.doctorId = this.doctorId;
        this.logger.debug('[OpenCreatePrescription] Pre-filled doctorId:', this.doctorId);
      }
      if (!(this.newPrescription as any).startDate) {
        (this.newPrescription as any).startDate = new Date().toISOString().split('T')[0];
      }
      if ((this.newPrescription as any).quantity == null) {
        (this.newPrescription as any).quantity = 30;
      }
      if ((this.newPrescription as any).refills == null) {
        (this.newPrescription as any).refills = 0;
      }
      
      this.logger.debug('[OpenCreatePrescription] Final newPrescription state:', this.newPrescription);
    }
  }

  get prescriptionDebug() {
    return {
      selectedPatientId: this.selectedPatientId,
      doctorIdContext: this.doctorId,
      newPrescription: this.newPrescription,
      patientsLoaded: Array.isArray(this.patients) ? this.patients.map(p => p.id) : []
    };
  }

  onPatientSelectionChange(patientId: string) {
    this.selectedPatientId = patientId;
    // If selected ID is not one of known patient entity IDs, try resolving from userId
    const exists = Array.isArray(this.patients) && this.patients.some(p => p.id === patientId);
    if (!exists && patientId) {
      this.userService.getPatientIdByUserId(patientId).then(resolved => {
        if (resolved) {
          this.selectedPatientId = resolved;
          this.newPrescription.patientId = resolved;
          this.newLabResult.patientId = resolved as any;
        }
      }).catch(() => {});
    } else {
      this.newPrescription.patientId = patientId;
      this.newLabResult.patientId = patientId as any;
    }
  }
  showCreateVitalSigns = false;
  showCreateLabResult = false;
  
  newMedicalRecord: MedicalRecordRequest = {
    patientId: '',
    doctorId: '',
    recordType: 'NOTE',
    title: '',
    content: '',
    diagnosisCode: ''
  };
  
  newPrescription: PrescriptionRequest = {
    patientId: '',
    doctorId: '',
    medicationName: '',
    dosage: '',
    frequency: '',
    quantity: 30,
    refills: 0,
    startDate: new Date().toISOString().split('T')[0] // Today's date
  };
  
  newVitalSigns: VitalSignsRequest = {
    patientId: '',
    temperature: undefined,
    bloodPressureSystolic: undefined,
    bloodPressureDiastolic: undefined,
    heartRate: undefined,
    respiratoryRate: undefined,
    oxygenSaturation: undefined,
    weight: undefined,
    height: undefined,
    notes: ''
  };
  
  newLabResult: LabResultRequest = {
    patientId: undefined as any,
    doctorId: '',
    testName: '',
    resultValue: '',
    status: 'PENDING',
    orderedDate: new Date().toISOString().split('T')[0] // Today's date
  };

  constructor(
    private appointmentService: AppointmentService,
    public userService: UserService,
    private auth: AuthService,
    private admin: AdminService,
    private router: Router,
    private availabilityService: AvailabilityService,
    private chatService: ChatService,
    private notificationService: NotificationService,
    private medicalRecordService: MedicalRecordService,
    private prescriptionService: PrescriptionService,
    private twoFactorAuthService: TwoFactorAuthService,
    private patientSafetyService: PatientSafetyService,
    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 => {
      this.chatUnreadCount = conversations.reduce((sum, c) => sum + c.unreadCount, 0);
    });
    
    // 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('DoctorComponent: Notification management updated', {
        totalNotifications: allNotifications.length,
        relevantNotifications: relevantNotifications.length,
        displayedNotifications: this.notifications.length,
        unreadCount: this.notificationCount,
        activeConversation: this.notificationService.getActiveConversationUserId()
      });
    });
    
    // Load safety alerts
    await this.loadSafetyAlerts();
    
    // Auto-open Safety Alerts tab if there are unacknowledged alerts
    if (this.unacknowledgedAlertsCount > 0) {
      this.activeTab = 'safety';
    }
    
    // Set up automatic refresh of alerts every 30 seconds
    this.startAlertsAutoRefresh();
    
    // Force check for unread messages after a short delay to ensure notifications are created
    setTimeout(async () => {
      await this.notificationService.checkForUnreadMessages();
    }, 3000);
  }
  
  ngOnDestroy() {
    // Clean up the alerts refresh interval
    if (this.alertsRefreshInterval) {
      clearInterval(this.alertsRefreshInterval);
    }
  }
  
  // Start automatic refresh of alerts every 30 seconds
  startAlertsAutoRefresh() {
    // Clear any existing interval
    if (this.alertsRefreshInterval) {
      clearInterval(this.alertsRefreshInterval);
    }
    
    // Refresh alerts every 30 seconds
    this.alertsRefreshInterval = setInterval(async () => {
      const previousCount = this.unacknowledgedAlertsCount;
      await this.loadSafetyAlerts();
      
      // If new alerts appeared and doctor is not on safety tab, show notification
      if (this.unacknowledgedAlertsCount > previousCount && this.activeTab !== 'safety') {
        this.logger.debug(`New alerts detected! Total: ${this.unacknowledgedAlertsCount}`);
        // Optional: You can add a toast notification here
      }
    }, 30000); // 30 seconds
  }

  ngAfterViewInit(): void {
    // ViewChild is available after view init
    // Ensure chat component is properly initialized
    if (this.chatComponent) {
      this.logger.debug('ChatComponent initialized:', this.chatComponent);
    } else {
      this.logger.warn('ChatComponent not available after view init');
    }
  }

  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');
      }

      // Check if user is actually a doctor
      if (this.currentUser.role !== 'DOCTOR') {
        this.auth.logout();
        this.router.navigateByUrl('/login');
        return;
      }

      // Load doctor profile first to get doctorId (most reliable source)
      // Then load appointments and availability using the correct doctor ID
      // Note: Backend needs doctor table ID, not user ID
      await this.loadDoctorProfile();
      
      // Load other data in parallel after doctor profile is loaded
      await Promise.all([
        this.loadAppointments(), // Will use doctorProfile.id or getDoctorIdByUserId()
        this.load2FAStatus(),
        this.loadAllDoctorRecords(),
        this.loadPatients(true) // Load all patients for dropdowns
      ]);
      
      // Load availability after doctorProfile is loaded (so we have doctorId)
      await this.loadAvailability();
      // Extract patients from appointments (this respects soft-delete flags)
      // This ensures the Patients tab only shows patients with visible appointments
      this.logger.debug('[DoctorComponent] Extracting patients from appointments, appointments count:', this.appointments.length);
      this.extractPatientsFromAppointments();
      this.logger.debug('[DoctorComponent] Extracted patients count:', this.patients.length);
      
      // Set doctorId for availability form
      if (this.doctorId) {
        this.newAvailability.doctorId = this.doctorId;
      }
    } 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.currentUser) return;
      
      // Priority: 1. Use doctorProfile.id (most reliable)
      //           2. Try getDoctorIdByUserId()
      //           3. Fail gracefully if no doctor ID found
      
      let doctorId: string | null = null;
      
      // First priority: Use doctorProfile.id if available
      if (this.doctorProfile?.id) {
        doctorId = this.doctorProfile.id;
      } else {
        // Second priority: Try to get doctor ID from user service
        try {
          doctorId = await this.userService.getDoctorIdByUserId(this.currentUser!.id);
        } catch (e: any) {
          this.logger.warn('Could not get doctor ID from user service:', e);
        }
      }
      
      if (doctorId) {
        this.doctorId = doctorId;
        try {
          this.appointments = await this.appointmentService.getAppointmentsByDoctorId(doctorId);
          this.logger.debug('[DoctorComponent] loadAppointments - loaded appointments:', this.appointments.length);
          // Extract patients immediately after loading appointments
          this.extractPatientsFromAppointments();
        } catch (e: any) {
          this.logger.error('Failed to load appointments with doctor ID:', e);
          this.appointments = [];
          if (e?.response?.status === 403) {
            this.error = 'Access denied: Unable to load appointments. Please refresh the page.';
          } else {
            this.error = 'Unable to load appointments. Please try again later.';
          }
        }
      } else {
        // No doctor ID found - cannot load appointments
        this.logger.warn('No doctor ID available. Cannot load appointments. Doctor profile may not be loaded yet.');
        this.appointments = [];
        // Don't set error here - doctor profile might still be loading
        // The error will be set if doctor profile fails to load
      }
    } catch (e: any) {
      this.logger.error('Error loading appointments:', e);
      this.appointments = [];
      if (!this.error) {
        this.error = 'Failed to load appointments. Please refresh the page.';
      }
    }
  }

  extractPatientsFromAppointments() {
    // Extract unique patients from appointments as fallback
    // This respects soft-delete: only appointments with deletedByDoctor=false are shown
    const patientMap = new Map<string, any>();
    this.logger.debug('[DoctorComponent] extractPatientsFromAppointments - appointments:', this.appointments.length);
    
    this.appointments.forEach((apt, index) => {
      // Only include appointments that are NOT deleted by doctor
      // (The backend already filters these, but double-check for safety)
      const patientKey = `${apt.patientFirstName}-${apt.patientLastName}`;
      const patientId = (apt as any).patientId;
      this.logger.debug(`[DoctorComponent] Appointment ${index}:`, {
        patientId,
        firstName: apt.patientFirstName,
        lastName: apt.patientLastName,
        hasPatientId: !!patientId
      });
      
      if (patientId && !patientMap.has(patientId)) {
        patientMap.set(patientId, {
          id: patientId, // Use patient ID as the key for uniqueness
          firstName: apt.patientFirstName,
          lastName: apt.patientLastName,
          email: '', // We don't have email from appointments
          displayName: `${apt.patientFirstName} ${apt.patientLastName}`
        });
      }
    });
    
    // Create a new array to trigger change detection
    this.patients = Array.from(patientMap.values());
    this.logger.debug('[DoctorComponent] extractPatientsFromAppointments - extracted patients:', this.patients.length, this.patients);
  }

  async loadPatients(forDropdowns: boolean = false) {
    try {
      // Always extract patients from appointments first (respects soft-delete)
      this.extractPatientsFromAppointments();
      
      // Only load all patients if needed for dropdowns (e.g., creating prescriptions)
      // For the Patients tab, we only want patients with appointments
      if (forDropdowns && this.patients.length === 0) {
        // For dropdowns, we might need all patients even if no appointments yet
        // But we should still merge with appointment-based patients
        const allPatients = await this.userService.getAllPatients();
        // Merge but don't replace - keep appointment-based patients first
        const existingIds = new Set(this.patients.map(p => p.id));
        const newPatients = allPatients.filter(p => !existingIds.has(p.id));
        this.patients = [...this.patients, ...newPatients];
      }
    } catch (e: any) {
      this.logger.error('Error loading patients:', e);
      // Fallback: extract from appointments
      this.extractPatientsFromAppointments();
    }
  }

  async loadAvailability() {
    // Priority: 1. Use doctorProfile.id (most reliable)
    //           2. Use existing doctorId if already set
    //           3. Try getDoctorIdByUserId()
    //           4. Fail gracefully if no doctor ID found
    
    // First priority: Use doctorProfile.id if available
    if (!this.doctorId && this.doctorProfile?.id) {
      this.doctorId = this.doctorProfile.id;
    }
    
    // Second priority: If still no doctorId, try to get it from user service
    if (!this.doctorId && this.currentUser?.id) {
      try {
        const doctorId = await this.userService.getDoctorIdByUserId(this.currentUser.id);
        if (doctorId) {
          this.doctorId = doctorId;
        }
      } catch (e) {
        this.logger.warn('Could not get doctor ID from user service:', e);
      }
    }
    
    // If still no doctorId, cannot load availability
    if (!this.doctorId) {
      this.logger.warn('No doctorId available, cannot load availability. Doctor profile may not be loaded yet.');
      this.availability = [];
      return;
    }
    
    try {
      if (this.dayFilter !== 'all') {
        this.availability = await this.availabilityService.getAvailabilityByDay(this.doctorId, this.dayFilter);
      } else {
        // Always load all availability slots (both active and inactive)
        this.availability = await this.availabilityService.getDoctorAvailability(this.doctorId);
      }
    } catch (e: any) {
      this.logger.error('Error loading availability:', e);
      this.availability = [];
    }
  }

  async createAvailability() {
    if (!this.newAvailability.doctorId || !this.newAvailability.startTime || !this.newAvailability.endTime) {
      this.error = 'Please fill in all required fields';
      return;
    }

    // Set doctorId from current user if not set
    if (!this.newAvailability.doctorId && this.doctorId) {
      this.newAvailability.doctorId = this.doctorId;
    }

    // Clear previous error
    this.error = null;

    try {
      await this.availabilityService.createAvailability(this.newAvailability);
      this.showAvailabilityForm = false;
      this.newAvailability = {
        doctorId: this.doctorId || '',
        dayOfWeek: 'MONDAY',
        startTime: '09:00',
        endTime: '17:00'
      };
      this.error = null;
      await this.loadAvailability();
    } catch (e: any) {
      this.error = e?.response?.data?.message || e?.response?.data?.error || 'Failed to create availability slot';
      this.logger.error('Error creating availability:', e);
    }
  }

  async deleteAvailability(availabilityId: string) {
    const confirmed = await this.modalService.confirm(
      'Are you sure you want to delete this availability slot?',
      'Delete Availability Slot',
      'Delete',
      'Cancel'
    );
    if (!confirmed) return;
    
    try {
      await this.availabilityService.deleteAvailability(availabilityId);
      await this.loadAvailability();
    } catch (e: any) {
      this.error = e?.response?.data?.message || 'Failed to delete availability slot';
    }
  }

  async deleteAllAvailability() {
    if (!this.doctorId) {
      this.error = 'Doctor ID not available';
      return;
    }
    const confirmed = await this.modalService.confirm(
      'Are you sure you want to delete ALL availability slots? This action cannot be undone.',
      'Delete All Availability Slots',
      'Delete All',
      'Cancel'
    );
    if (!confirmed) return;
    
    try {
      await this.availabilityService.deleteAllDoctorAvailability(this.doctorId);
      await this.loadAvailability();
    } catch (e: any) {
      this.error = e?.response?.data?.message || 'Failed to delete all availability slots';
    }
  }

  async createBulkAvailability() {
    if (!this.bulkAvailability.doctorId || !this.bulkAvailability.availabilities.length) {
      this.error = 'Please add at least one availability slot';
      return;
    }

    if (!this.doctorId) {
      this.error = 'Doctor ID not available';
      return;
    }

    this.bulkAvailability.doctorId = this.doctorId;

    // Clear previous error
    this.error = null;

    try {
      await this.availabilityService.createBulkAvailability(this.bulkAvailability);
      this.showBulkAvailabilityForm = false;
      this.bulkAvailability = {
        doctorId: this.doctorId || '',
        availabilities: []
      };
      this.error = null;
      await this.loadAvailability();
    } catch (e: any) {
      this.error = e?.response?.data?.message || e?.response?.data?.error || 'Failed to create bulk availability';
      this.logger.error('Error creating bulk availability:', e);
    }
  }

  addBulkAvailabilitySlot() {
    this.bulkAvailability.availabilities.push({
      dayOfWeek: 'MONDAY',
      startTime: '09:00',
      endTime: '17:00'
    });
  }

  removeBulkAvailabilitySlot(index: number) {
    this.bulkAvailability.availabilities.splice(index, 1);
  }


  onDayFilterChange() {
    this.loadAvailability();
  }

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

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

  getCompletedCount(): number {
    return this.appointments.filter(apt => apt.status === 'COMPLETED').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}`;
  }

  shouldShowManualPatientIdInput(): boolean {
    if (!this.newAppointment.patientId) {
      return true;
    }
    return !this.patients.some(p => p.id === this.newAppointment.patientId);
  }

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

  async createAppointment() {
    if (!this.newAppointment.patientId || !this.newAppointment.scheduledDate || !this.newAppointment.scheduledTime) {
      this.error = 'Please fill in all required fields';
      return;
    }

    if (!this.doctorId) {
      this.error = 'Doctor ID not available. Please refresh the page.';
      return;
    }

    try {
      await this.appointmentService.createAppointment({
        patientId: this.newAppointment.patientId,
        doctorId: this.doctorId,
        scheduledDate: this.newAppointment.scheduledDate,
        scheduledTime: this.newAppointment.scheduledTime,
        durationMinutes: this.newAppointment.durationInMinutes || 30
      });
      this.showCreateForm = false;
      this.newAppointment = {
        patientId: '',
        scheduledDate: '',
        scheduledTime: '',
        durationInMinutes: 30
      };
      await this.refresh();
    } catch (e: any) {
      this.error = e?.response?.data?.message || 'Failed to create appointment';
    }
  }

  async cancelAppointment(appointment: Appointment) {
    // Note: Appointment DTO doesn't include ID from backend
    // Backend needs to add ID to AppointmentResponseDto or use composite key
    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 confirmAppointment(appointment: Appointment) {
    if (!appointment.id) {
      this.error = 'Appointment ID not available. Backend needs to include ID in response.';
      return;
    }
    try {
      await this.appointmentService.confirmAppointment(appointment.id);
      await this.refresh();
    } catch (e: any) {
      this.error = e?.response?.data?.message || 'Failed to confirm appointment';
    }
  }

  async completeAppointment(appointment: Appointment) {
    if (!appointment.id) {
      this.error = 'Appointment ID not available. Backend needs to include ID in response.';
      return;
    }
    try {
      await this.appointmentService.completeAppointment(appointment.id);
      await this.refresh();
    } catch (e: any) {
      this.error = e?.response?.data?.message || 'Failed to complete appointment';
    }
  }

  setTab(tab: string) {
    this.activeTab = tab;
    // When switching to prescriptions tab, ensure data is loaded and filtered
    if (tab === 'prescriptions') {
      if (this.showAllRecords) {
        if (this.allPrescriptions.length === 0) {
          this.loadAllDoctorRecords();
        } else {
          this.applyPrescriptionFilters();
        }
      } else if (this.selectedPatientId) {
        if (this.prescriptions.length === 0) {
          this.loadPatientPrescriptions(this.selectedPatientId);
        } else {
          this.applyPrescriptionFilters();
        }
      } else {
        // If no patient selected, load all records
        this.showAllRecords = true;
        this.loadAllDoctorRecords();
      }
    }
  }

  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); // Format HH:MM
  }

  // New feature loading methods
  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(code?: string) {
    let disableCode: string | null | undefined = code;
    if (!disableCode) {
      disableCode = 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 (!disableCode) return;
    try {
      await this.twoFactorAuthService.disable2FA(disableCode);
      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'
      );
    }
  }

  async createMedicalRecord() {
    if (!this.newMedicalRecord.patientId || !this.newMedicalRecord.title || !this.newMedicalRecord.content) {
      this.error = 'Please fill in all required fields';
      return;
    }
    // Ensure doctorId is set from context
    if (!this.newMedicalRecord.doctorId) {
      this.newMedicalRecord.doctorId = this.doctorId || '';
    }
    try {
      const recordId = (this.newMedicalRecord as any).recordId;
      if (recordId) {
        // Update existing record
        await this.medicalRecordService.updateMedicalRecord(recordId, this.newMedicalRecord);
      } else {
        // Create new record
        await this.medicalRecordService.createMedicalRecord(this.newMedicalRecord);
      }
      this.showCreateMedicalRecord = false;
      this.newMedicalRecord = {
        patientId: '',
        doctorId: this.doctorId || '',
        recordType: 'NOTE',
        title: '',
        content: '',
        diagnosisCode: ''
      };
      // Clear record ID
      delete (this.newMedicalRecord as any).recordId;
      // Refresh all relevant data
      await Promise.all([
        this.selectedPatientId ? this.loadPatientMedicalRecords(this.selectedPatientId) : Promise.resolve(),
        this.loadAllDoctorRecords()
      ]);
    } catch (e: any) {
      this.logger.error('Error creating/updating medical record:', e);
      const recordId = (this.newMedicalRecord as any).recordId;
      const errorMessage = e?.response?.data?.message || 
                          e?.response?.data?.error || 
                          e?.message || 
                          (recordId ? 'Failed to update medical record' : 'Failed to create medical record');
      this.error = errorMessage;
      // Auto-hide error after 5 seconds
      setTimeout(() => {
        this.error = null;
      }, 5000);
    }
  }

  async createPrescription() {
    this.logger.debug('[CreatePrescription] initial state:', {
      selectedPatientId: this.selectedPatientId,
      doctorIdContext: this.doctorId,
      newPrescription: this.newPrescription
    });
    // Ensure patientId is set from current selection
    if (!this.newPrescription.patientId) {
      if (this.selectedPatientId) {
        this.newPrescription.patientId = this.selectedPatientId;
      } else if (Array.isArray(this.patients) && this.patients.length === 1 && this.patients[0]?.id) {
        // Fallback: if only one patient is loaded in context, preselect it
        this.newPrescription.patientId = this.patients[0].id;
        this.selectedPatientId = this.patients[0].id;
      }
    }
    // Ensure doctorId is set from profile/context
    if (!this.newPrescription.doctorId) {
      this.newPrescription.doctorId = this.doctorId || '';
    }

    // Apply sensible defaults required by backend
    if (this.newPrescription.quantity == null) {
      (this.newPrescription as any).quantity = 30;
    }
    if (this.newPrescription.refills == null) {
      (this.newPrescription as any).refills = 0;
    }
    if (!this.newPrescription.startDate) {
      (this.newPrescription as any).startDate = new Date().toISOString().split('T')[0];
    }

    // Normalize inputs
    this.newPrescription.medicationName = (this.newPrescription.medicationName || '').trim();
    this.newPrescription.dosage = (this.newPrescription.dosage || '').trim();
    this.newPrescription.frequency = (this.newPrescription.frequency || '').trim();

    // Collect missing fields for precise error
    const missing: string[] = [];
    if (!this.newPrescription.patientId) missing.push('patient');
    if (!this.newPrescription.doctorId) missing.push('doctor');
    if (!this.newPrescription.medicationName) missing.push('medication');
    if (!this.newPrescription.dosage) missing.push('dosage');
    if (!this.newPrescription.frequency) missing.push('frequency');
    if ((this.newPrescription as any).quantity == null || (this.newPrescription as any).quantity <= 0) missing.push('quantity');
    if (!(this.newPrescription as any).startDate) missing.push('start date');

    if (missing.length > 0) {
      this.error = `Please fill in all required fields (${missing.join(', ')})`;
      this.logger.warn('[CreatePrescription] missing fields:', missing, 'state:', {
        selectedPatientId: this.selectedPatientId,
        doctorIdContext: this.doctorId,
        newPrescription: this.newPrescription
      });
      return;
    }
    try {
      await this.prescriptionService.createPrescription(this.newPrescription);
      this.showCreatePrescription = false;
      this.newPrescription = {
        patientId: '',
        doctorId: this.doctorId || '',
        medicationName: '',
        dosage: '',
        frequency: '',
        quantity: 30,
        refills: 0,
        startDate: new Date().toISOString().split('T')[0]
      };
      
      // Refresh all relevant data including safety alerts
      const previousAlertCount = this.unacknowledgedAlertsCount;
      await Promise.all([
        this.selectedPatientId ? this.loadPatientPrescriptions(this.selectedPatientId) : Promise.resolve(),
        this.loadAllDoctorRecords(),
        this.loadSafetyAlerts() // Refresh safety alerts after prescription creation
      ]);
      
      // Check if new safety alerts were detected
      if (this.unacknowledgedAlertsCount > previousAlertCount) {
        const newAlertsCount = this.unacknowledgedAlertsCount - previousAlertCount;
        await this.modalService.alert(
          `${newAlertsCount} new safety alert${newAlertsCount > 1 ? 's' : ''} detected. Please review in the Safety Alerts tab.`,
          'warning',
          'Safety Alert Detected'
        );
        // Auto-open Safety Alerts tab if not already open
        if (this.activeTab !== 'safety') {
          this.activeTab = 'safety';
        }
      } else {
        await this.modalService.alert(
          'Prescription created successfully!',
          'success',
          'Success'
        );
      }
    } catch (e: any) {
      this.logger.error('Error creating prescription:', e);
      const errorMessage = e?.response?.data?.message || 
                          e?.response?.data?.error || 
                          e?.message || 
                          'Failed to create prescription';
      this.error = errorMessage;
      // Auto-hide error after 5 seconds
      setTimeout(() => {
        this.error = null;
      }, 5000);
    }
  }

  async createVitalSigns() {
    if (!this.newVitalSigns.patientId) {
      this.error = 'Please select a patient';
      return;
    }
    try {
      await this.medicalRecordService.createVitalSigns(this.newVitalSigns);
      this.showCreateVitalSigns = false;
      this.newVitalSigns = {
        patientId: '',
        temperature: undefined,
        bloodPressureSystolic: undefined,
        bloodPressureDiastolic: undefined,
        heartRate: undefined,
        respiratoryRate: undefined,
        oxygenSaturation: undefined,
        weight: undefined,
        height: undefined,
        notes: ''
      };
      // Refresh vital signs if patient is selected
      if (this.selectedPatientId) {
        await this.loadPatientVitalSigns(this.selectedPatientId);
      }
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to create vital signs';
    }
  }

  async deleteVitalSigns(vitalSignsId: string) {
    const confirmed = await this.modalService.confirm(
      'Are you sure you want to delete this vital signs record?',
      'Delete Vital Signs',
      'Delete',
      'Cancel'
    );
    if (!confirmed) {
      return;
    }
    try {
      await this.medicalRecordService.deleteVitalSigns(vitalSignsId);
      if (this.selectedPatientId) {
        await this.loadPatientVitalSigns(this.selectedPatientId);
      }
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to delete vital signs';
    }
  }

  async createLabResult() {
    // Auto-fill patientId from context if missing
    if (!this.newLabResult.patientId) {
      if (this.selectedPatientId) {
        this.newLabResult.patientId = this.selectedPatientId;
      } else if (Array.isArray(this.patients) && this.patients.length === 1) {
        this.newLabResult.patientId = this.patients[0].id;
      }
    }

    // If patientId is not in known patient IDs, try to resolve from userId
    if (this.newLabResult.patientId && Array.isArray(this.patients) && !this.patients.some(p => p.id === this.newLabResult.patientId)) {
      try {
        const resolved = await this.userService.getPatientIdByUserId(this.newLabResult.patientId as any);
        if (resolved) {
          this.newLabResult.patientId = resolved as any;
        }
      } catch {}
    }

    const missing: string[] = [];
    if (!this.newLabResult.patientId) missing.push('patient');
    if (!this.newLabResult.testName) missing.push('test name');
    if (!this.newLabResult.resultValue) missing.push('result value');

    if (missing.length) {
      this.error = `Please fill in all required fields: ${missing.join(', ')}`;
      return;
    }
    try {
      const labResultId = (this.newLabResult as any).labResultId;
      if (labResultId) {
        // Update existing lab result
        await this.medicalRecordService.updateLabResult(labResultId, this.newLabResult);
      } else {
        // Create new lab result
        await this.medicalRecordService.createLabResult(this.newLabResult);
      }
      this.showCreateLabResult = false;
      this.newLabResult = {
        patientId: undefined as any,
        doctorId: this.doctorId || '',
        testName: '',
        resultValue: '',
        status: 'PENDING',
        orderedDate: new Date().toISOString().split('T')[0]
      };
      // Clear lab result ID
      delete (this.newLabResult as any).labResultId;
      if (this.selectedPatientId) {
        await this.loadPatientLabResults(this.selectedPatientId);
      }
    } catch (e: any) {
      this.logger.error('[CreateLabResult] Error:', e);
      this.logger.error('[CreateLabResult] Response:', e?.response);
      this.logger.error('[CreateLabResult] Response Data:', e?.response?.data);
      this.logger.error('[CreateLabResult] Request payload:', this.newLabResult);
      // Extract detailed error message
      let errorMsg = 'Failed to create lab result';
      if (e?.response?.data) {
        if (typeof e.response.data === 'string') {
          errorMsg = e.response.data;
        } else if (e.response.data.error) {
          errorMsg = e.response.data.error;
        } else if (e.response.data.message) {
          errorMsg = e.response.data.message;
        } else if (e.response.data.errors) {
          errorMsg = JSON.stringify(e.response.data.errors);
        }
      } else if (e?.message) {
        errorMsg = e.message;
      }
      this.error = errorMsg;
    }
  }

  async deleteLabResult(labResultId: string) {
    const confirmed = await this.modalService.confirm(
      'Are you sure you want to delete this lab result?',
      'Delete Lab Result',
      'Delete',
      'Cancel'
    );
    if (!confirmed) {
      return;
    }
    try {
      await this.medicalRecordService.deleteLabResult(labResultId);
      if (this.selectedPatientId) {
        await this.loadPatientLabResults(this.selectedPatientId);
      }
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to delete lab result';
    }
  }

  editLabResult(labResult: any) {
    // Pre-fill form with lab result data
    this.newLabResult = {
      patientId: labResult.patientId,
      doctorId: labResult.doctorId,
      testName: labResult.testName,
      resultValue: labResult.resultValue,
      referenceRange: labResult.referenceRange,
      unit: labResult.unit,
      status: labResult.status,
      orderedDate: labResult.orderedDate,
      resultDate: labResult.resultDate,
      notes: labResult.notes
    };
    this.showCreateLabResult = true;
    // Store lab result ID for update
    (this.newLabResult as any).labResultId = labResult.id;
  }

  async loadPatientMedicalRecords(patientId: string) {
    try {
      this.medicalRecords = await this.medicalRecordService.getMedicalRecordsByPatientId(patientId);
    } catch (e: any) {
      this.logger.error('Error loading medical records:', e);
      this.medicalRecords = [];
    }
  }

  async loadPatientPrescriptions(patientId: string) {
    try {
      this.prescriptions = await this.prescriptionService.getPrescriptionsByPatientId(patientId);
      this.applyPrescriptionFilters();
    } catch (e: any) {
      this.logger.error('Error loading prescriptions:', e);
      this.prescriptions = [];
      this.filteredPrescriptions = [];
    }
  }

  async loadPatientLabResults(patientId: string) {
    try {
      this.labResults = await this.medicalRecordService.getLabResultsByPatientId(patientId);
    } catch (e: any) {
      this.logger.error('Error loading lab results:', e);
      this.labResults = [];
    }
  }

  selectPatient(patientId: string) {
    this.selectedPatientId = patientId;
    this.newMedicalRecord.patientId = patientId;
    this.newPrescription.patientId = patientId;
    this.newVitalSigns.patientId = patientId;
    this.newLabResult.patientId = patientId;
    Promise.all([
      this.loadPatientMedicalRecords(patientId),
      this.loadPatientPrescriptions(patientId),
      this.loadPatientLabResults(patientId),
      this.loadPatientVitalSigns(patientId)
    ]);
  }

  async loadPatientVitalSigns(patientId: string) {
    try {
      [this.vitalSigns, this.latestVitalSigns] = await Promise.all([
        this.medicalRecordService.getVitalSignsByPatientId(patientId),
        this.medicalRecordService.getLatestVitalSignsByPatientId(patientId)
      ]);
    } catch (e: any) {
      this.logger.error('Error loading vital signs:', e);
      this.vitalSigns = [];
      this.latestVitalSigns = null;
    }
  }

  async loadAllDoctorRecords() {
    if (!this.doctorId) return;
    try {
      [this.allMedicalRecords, this.allPrescriptions] = await Promise.all([
        this.medicalRecordService.getMedicalRecordsByDoctorId(this.doctorId),
        this.prescriptionService.getPrescriptionsByDoctorId(this.doctorId)
      ]);
      this.applyPrescriptionFilters();
    } catch (e: any) {
      this.logger.error('Error loading all doctor records:', e);
      this.allMedicalRecords = [];
      this.allPrescriptions = [];
      this.filteredPrescriptions = [];
    }
  }
  
  // Enterprise Prescription Management Methods
  applyPrescriptionFilters() {
    const prescriptionsToFilter = this.showAllRecords ? this.allPrescriptions : this.prescriptions;
    // Initialize with all prescriptions if empty array
    let filtered = prescriptionsToFilter && prescriptionsToFilter.length > 0 ? [...prescriptionsToFilter] : [];
    
    // Search filter
    if (this.prescriptionSearchTerm) {
      const searchLower = this.prescriptionSearchTerm.toLowerCase();
      filtered = filtered.filter(p => 
        p.medicationName?.toLowerCase().includes(searchLower) ||
        p.prescriptionNumber?.toLowerCase().includes(searchLower) ||
        p.patientName?.toLowerCase().includes(searchLower) ||
        p.doctorName?.toLowerCase().includes(searchLower) ||
        p.pharmacyName?.toLowerCase().includes(searchLower)
      );
    }
    
    // Status filter
    if (this.prescriptionStatusFilter !== 'all') {
      filtered = filtered.filter(p => p.status === this.prescriptionStatusFilter);
    }
    
    // Date filter
    if (this.prescriptionDateFilter !== 'all') {
      const now = new Date();
      const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
      
      filtered = filtered.filter(p => {
        const startDate = new Date(p.startDate);
        
        switch (this.prescriptionDateFilter) {
          case 'today':
            return startDate >= today;
          case 'week':
            const weekAgo = new Date(today);
            weekAgo.setDate(weekAgo.getDate() - 7);
            return startDate >= weekAgo;
          case 'month':
            const monthAgo = new Date(today);
            monthAgo.setMonth(monthAgo.getMonth() - 1);
            return startDate >= monthAgo;
          case 'year':
            const yearAgo = new Date(today);
            yearAgo.setFullYear(yearAgo.getFullYear() - 1);
            return startDate >= yearAgo;
          case 'custom':
            if (this.prescriptionDateFrom && this.prescriptionDateTo) {
              const fromDate = new Date(this.prescriptionDateFrom);
              const toDate = new Date(this.prescriptionDateTo);
              toDate.setHours(23, 59, 59, 999);
              return startDate >= fromDate && startDate <= toDate;
            }
            return true;
          default:
            return true;
        }
      });
    }
    
    // Sorting
    filtered.sort((a, b) => {
      let aValue: any, bValue: any;
      
      switch (this.prescriptionSortBy) {
        case 'medicationName':
          aValue = a.medicationName || '';
          bValue = b.medicationName || '';
          break;
        case 'patientName':
          aValue = a.patientName || a.patientId || '';
          bValue = b.patientName || b.patientId || '';
          break;
        case 'status':
          aValue = a.status || '';
          bValue = b.status || '';
          break;
        case 'startDate':
          aValue = new Date(a.startDate).getTime();
          bValue = new Date(b.startDate).getTime();
          break;
        case 'createdAt':
        default:
          aValue = new Date(a.createdAt).getTime();
          bValue = new Date(b.createdAt).getTime();
          break;
      }
      
      if (aValue < bValue) return this.prescriptionSortOrder === 'asc' ? -1 : 1;
      if (aValue > bValue) return this.prescriptionSortOrder === 'asc' ? 1 : -1;
      return 0;
    });
    
    this.filteredPrescriptions = filtered;
  }
  
  onPrescriptionFilterChange() {
    this.applyPrescriptionFilters();
  }
  
  togglePrescriptionSort(column: string) {
    if (this.prescriptionSortBy === column) {
      this.prescriptionSortOrder = this.prescriptionSortOrder === 'asc' ? 'desc' : 'asc';
    } else {
      this.prescriptionSortBy = column;
      this.prescriptionSortOrder = 'desc';
    }
    this.applyPrescriptionFilters();
  }
  
  togglePrescriptionSelection(prescriptionId: string) {
    const index = this.selectedPrescriptions.indexOf(prescriptionId);
    if (index > -1) {
      this.selectedPrescriptions.splice(index, 1);
    } else {
      this.selectedPrescriptions.push(prescriptionId);
    }
  }
  
  toggleSelectAllPrescriptions() {
    const prescriptionsToSelect = this.filteredPrescriptions.length > 0 
      ? this.filteredPrescriptions 
      : (this.showAllRecords ? this.allPrescriptions : this.prescriptions);
    
    if (this.selectedPrescriptions.length === prescriptionsToSelect.length) {
      this.selectedPrescriptions = [];
    } else {
      this.selectedPrescriptions = prescriptionsToSelect.map(p => p.id);
    }
  }
  
  async bulkUpdatePrescriptionStatus(status: 'ACTIVE' | 'COMPLETED' | 'CANCELLED' | 'DISCONTINUED') {
    if (this.selectedPrescriptions.length === 0) {
      this.error = 'Please select at least one prescription';
      return;
    }
    
    const confirmed = await this.modalService.confirm(
      `Are you sure you want to update ${this.selectedPrescriptions.length} prescription(s) to ${status}?`,
      'Update Prescription Status',
      'Update',
      'Cancel'
    );
    if (!confirmed) {
      return;
    }
    
    try {
      await Promise.all(
        this.selectedPrescriptions.map(id => 
          this.prescriptionService.updatePrescriptionStatus(id, status)
        )
      );
      this.selectedPrescriptions = [];
      await this.refreshPrescriptions();
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to update prescriptions';
    }
  }
  
  async refreshPrescriptions() {
    if (this.showAllRecords) {
      await this.loadAllDoctorRecords();
    } else if (this.selectedPatientId) {
      await this.loadPatientPrescriptions(this.selectedPatientId);
      this.applyPrescriptionFilters();
    }
  }
  
  getPrescriptionStatistics() {
    // Use the source data, not filtered, for statistics
    const prescriptions = this.showAllRecords ? this.allPrescriptions : this.prescriptions;
    // Fallback to filtered if source is empty
    const sourcePrescriptions = prescriptions && prescriptions.length > 0 ? prescriptions : this.filteredPrescriptions;
    const total = sourcePrescriptions.length;
    const active = sourcePrescriptions.filter(p => p.status === 'ACTIVE').length;
    const completed = sourcePrescriptions.filter(p => p.status === 'COMPLETED').length;
    const cancelled = sourcePrescriptions.filter(p => p.status === 'CANCELLED').length;
    const discontinued = sourcePrescriptions.filter(p => p.status === 'DISCONTINUED').length;
    const ePrescriptionsSent = sourcePrescriptions.filter(p => p.ePrescriptionSent).length;
    
    // Calculate recent activity (last 30 days)
    const thirtyDaysAgo = new Date();
    thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
    const recent = sourcePrescriptions.filter(p => {
      const createdDate = new Date(p.createdAt);
      return createdDate >= thirtyDaysAgo;
    }).length;
    
    return {
      total,
      active,
      completed,
      cancelled,
      discontinued,
      ePrescriptionsSent,
      recent,
      completionRate: total > 0 ? ((completed / total) * 100).toFixed(1) : '0'
    };
  }
  
  exportPrescriptions() {
    const prescriptions = this.filteredPrescriptions.length > 0 ? this.filteredPrescriptions : 
                         (this.showAllRecords ? this.allPrescriptions : this.prescriptions);
    
    // Create CSV content
    const headers = ['Prescription #', 'Medication', 'Patient', 'Dosage', 'Frequency', 'Quantity', 'Refills', 'Status', 'Start Date', 'End Date', 'E-Prescription Sent'];
    const rows = prescriptions.map(p => [
      p.prescriptionNumber || '',
      p.medicationName || '',
      p.patientName || p.patientId || '',
      p.dosage || '',
      p.frequency || '',
      p.quantity?.toString() || '',
      p.refills?.toString() || '',
      p.status || '',
      p.startDate || '',
      p.endDate || '',
      p.ePrescriptionSent ? 'Yes' : 'No'
    ]);
    
    const csvContent = [
      headers.join(','),
      ...rows.map(row => row.map(cell => `"${cell}"`).join(','))
    ].join('\n');
    
    // Download CSV
    const blob = new Blob([csvContent], { type: 'text/csv' });
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = `prescriptions_${new Date().toISOString().split('T')[0]}.csv`;
    link.click();
    window.URL.revokeObjectURL(url);
  }
  
  printPrescription(prescription: Prescription) {
    const printWindow = window.open('', '_blank');
    if (!printWindow) return;
    
    printWindow.document.write(`
      <!DOCTYPE html>
      <html>
        <head>
          <title>Prescription - ${prescription.prescriptionNumber}</title>
          <style>
            body { font-family: Arial, sans-serif; padding: 20px; max-width: 800px; margin: 0 auto; }
            .header { border-bottom: 2px solid #333; padding-bottom: 20px; margin-bottom: 20px; }
            .prescription-info { margin: 20px 0; }
            .section { margin: 15px 0; }
            .label { font-weight: bold; margin-right: 10px; }
            table { width: 100%; border-collapse: collapse; margin: 20px 0; }
            th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
            .footer { margin-top: 40px; padding-top: 20px; border-top: 2px solid #333; }
          </style>
        </head>
        <body>
          <div class="header">
            <h1>Prescription</h1>
            <p><strong>Prescription #:</strong> ${prescription.prescriptionNumber}</p>
            <p><strong>Date:</strong> ${new Date(prescription.createdAt).toLocaleDateString()}</p>
          </div>
          <div class="prescription-info">
            <div class="section">
              <p><span class="label">Patient:</span> ${prescription.patientName || prescription.patientId}</p>
              <p><span class="label">Doctor:</span> ${prescription.doctorName || prescription.doctorId}</p>
            </div>
            <div class="section">
              <h2>Medication Information</h2>
              <table>
                <tr><th>Medication</th><td>${prescription.medicationName}</td></tr>
                <tr><th>Dosage</th><td>${prescription.dosage}</td></tr>
                <tr><th>Frequency</th><td>${prescription.frequency}</td></tr>
                <tr><th>Quantity</th><td>${prescription.quantity}</td></tr>
                <tr><th>Refills</th><td>${prescription.refills || 0}</td></tr>
                <tr><th>Start Date</th><td>${new Date(prescription.startDate).toLocaleDateString()}</td></tr>
                ${prescription.endDate ? `<tr><th>End Date</th><td>${new Date(prescription.endDate).toLocaleDateString()}</td></tr>` : ''}
              </table>
            </div>
            ${prescription.instructions ? `<div class="section"><p><span class="label">Instructions:</span> ${prescription.instructions}</p></div>` : ''}
            ${prescription.pharmacyName ? `
              <div class="section">
                <h2>Pharmacy Information</h2>
                <p><span class="label">Pharmacy:</span> ${prescription.pharmacyName}</p>
                ${prescription.pharmacyAddress ? `<p><span class="label">Address:</span> ${prescription.pharmacyAddress}</p>` : ''}
                ${prescription.pharmacyPhone ? `<p><span class="label">Phone:</span> ${prescription.pharmacyPhone}</p>` : ''}
              </div>
            ` : ''}
            <div class="footer">
              <p><strong>Status:</strong> ${prescription.status}</p>
              ${prescription.ePrescriptionSent ? `<p><strong>E-Prescription Sent:</strong> Yes (${prescription.ePrescriptionSentAt ? new Date(prescription.ePrescriptionSentAt).toLocaleDateString() : 'N/A'})</p>` : ''}
            </div>
          </div>
        </body>
      </html>
    `);
    
    printWindow.document.close();
    printWindow.print();
  }

  async toggleRecordsView() {
    this.showAllRecords = !this.showAllRecords;
    this.selectedPrescriptions = [];
    if (this.showAllRecords) {
      await this.loadAllDoctorRecords();
    } else {
      if (this.selectedPatientId) {
        await this.loadPatientPrescriptions(this.selectedPatientId);
      } else {
        // If no patient selected, just clear filters
        this.applyPrescriptionFilters();
      }
    }
  }

  async deleteMedicalRecord(recordId: string) {
    const confirmed = await this.modalService.confirm(
      'Are you sure you want to delete this medical record? This action cannot be undone.',
      'Delete Medical Record',
      'Delete',
      'Cancel'
    );
    if (!confirmed) {
      return;
    }
    try {
      await this.medicalRecordService.deleteMedicalRecord(recordId);
      // Refresh data
      if (this.showAllRecords) {
        await this.loadAllDoctorRecords();
      } else if (this.selectedPatientId) {
        await this.loadPatientMedicalRecords(this.selectedPatientId);
      }
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to delete medical record';
    }
  }

  async deletePrescription(prescriptionId: string) {
    const confirmed = await this.modalService.confirm(
      'Are you sure you want to delete this prescription? This action cannot be undone.',
      'Delete Prescription',
      'Delete',
      'Cancel'
    );
    if (!confirmed) {
      return;
    }
    try {
      await this.prescriptionService.deletePrescription(prescriptionId);
      // Refresh data
      if (this.showAllRecords) {
        await this.loadAllDoctorRecords();
      } else if (this.selectedPatientId) {
        await this.loadPatientPrescriptions(this.selectedPatientId);
      }
      this.selectedPrescriptions = [];
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to delete prescription';
    }
  }

  editMedicalRecord(record: MedicalRecord) {
    // Pre-fill form with record data
    this.newMedicalRecord = {
      patientId: record.patientId,
      doctorId: record.doctorId,
      appointmentId: record.appointmentId,
      recordType: record.recordType,
      title: record.title,
      content: record.content,
      diagnosisCode: record.diagnosisCode
    };
    this.showCreateMedicalRecord = true;
    // Store record ID for update
    (this.newMedicalRecord as any).recordId = record.id;
  }

  async updatePrescriptionStatus(prescriptionId: string, status: 'ACTIVE' | 'COMPLETED' | 'CANCELLED' | 'DISCONTINUED') {
    try {
      await this.prescriptionService.updatePrescriptionStatus(prescriptionId, status);
      // Refresh data
      if (this.showAllRecords) {
        await this.loadAllDoctorRecords();
      } else if (this.selectedPatientId) {
        await this.loadPatientPrescriptions(this.selectedPatientId);
      }
      this.selectedPrescriptions = [];
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to update prescription status';
    }
  }

  async markEPrescriptionSent(prescriptionId: string) {
    try {
      await this.prescriptionService.markEPrescriptionSent(prescriptionId);
      // Refresh data
      if (this.showAllRecords) {
        await this.loadAllDoctorRecords();
      } else if (this.selectedPatientId) {
        await this.loadPatientPrescriptions(this.selectedPatientId);
      }
      this.selectedPrescriptions = [];
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to mark e-prescription as sent';
    }
  }

  editPrescription(prescription: Prescription) {
    this.selectedPrescription = prescription;
    this.newPrescription = {
      patientId: prescription.patientId,
      doctorId: prescription.doctorId,
      appointmentId: prescription.appointmentId,
      medicationName: prescription.medicationName,
      medicationCode: prescription.medicationCode,
      dosage: prescription.dosage,
      frequency: prescription.frequency,
      quantity: prescription.quantity,
      refills: prescription.refills,
      instructions: prescription.instructions,
      startDate: prescription.startDate,
      endDate: prescription.endDate,
      pharmacyName: prescription.pharmacyName,
      pharmacyAddress: prescription.pharmacyAddress,
      pharmacyPhone: prescription.pharmacyPhone
    };
    this.showUpdatePrescription = true;
    (this.newPrescription as any).prescriptionId = prescription.id;
  }

  async updatePrescription() {
    if (!this.newPrescription.patientId || !this.newPrescription.medicationName || !this.newPrescription.dosage || !this.newPrescription.frequency) {
      this.error = 'Please fill in all required fields';
      return;
    }
    try {
      const prescriptionId = (this.newPrescription as any).prescriptionId;
      if (!prescriptionId) {
        this.error = 'Prescription ID not found';
        return;
      }
      await this.prescriptionService.updatePrescription(prescriptionId, this.newPrescription);
      this.showUpdatePrescription = false;
      this.selectedPrescription = null;
      this.newPrescription = {
        patientId: '',
        doctorId: this.doctorId || '',
        medicationName: '',
        dosage: '',
        frequency: '',
        quantity: 30,
        refills: 0,
        startDate: new Date().toISOString().split('T')[0]
      };
      delete (this.newPrescription as any).prescriptionId;
      // Refresh data
      await Promise.all([
        this.selectedPatientId ? this.loadPatientPrescriptions(this.selectedPatientId) : Promise.resolve(),
        this.loadAllDoctorRecords()
      ]);
      this.selectedPrescriptions = [];
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to update prescription';
    }
  }

  get isEditingMedicalRecord(): boolean {
    return !!(this.newMedicalRecord as any).recordId;
  }

  get isEditingLabResult(): boolean {
    return !!(this.newLabResult as any).labResultId;
  }

  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();
      });
  }

  async loadDoctorProfile() {
    try {
      this.doctorProfile = await this.userService.getDoctorProfile();
      // Set doctorId from profile (this is the most reliable source)
      if (this.doctorProfile?.id) {
        this.doctorId = this.doctorProfile.id;
        
        // If doctorId was set, reload appointments and availability with correct ID
        // This ensures appointments and availability use the correct doctor ID
        if (this.currentUser) {
          // Reload appointments if they failed to load before
          if (!this.appointments || this.appointments.length === 0) {
            this.loadAppointments();
          }
          // Reload availability if it failed to load before
          if (!this.availability || this.availability.length === 0) {
            this.loadAvailability();
          }
        }
      } else {
        this.logger.error('Doctor profile loaded but does not contain ID');
        this.doctorProfile = null;
        this.error = 'Unable to load doctor profile. Please refresh the page or contact support.';
      }
    } catch (e: any) {
      this.logger.error('Failed to load doctor profile:', e);
      this.doctorProfile = null;
      this.error = 'Unable to load doctor profile. Please refresh the page or contact support.';
    }
  }

  async updateDoctorProfile(event?: {userData: UserUpdateRequest, doctorData: DoctorUpdateRequest}) {
    try {
      const userData = event?.userData || this.editUserData;
      const doctorData = event?.doctorData || this.editDoctorData;
      
      // Update user profile if fields are provided
      const hasUserChanges = userData.firstName || userData.lastName || userData.phoneNumber;
      if (hasUserChanges) {
        await this.userService.updateUserProfile(userData);
      }
      
      // Update doctor profile
      await this.userService.updateDoctorProfile(doctorData);
      await this.loadDoctorProfile();
      await this.loadUserAndAppointments();
      this.showEditProfile = false;
      this.editUserData = {
        firstName: '',
        lastName: '',
        phoneNumber: ''
      };
      this.editDoctorData = {
        medicalLicenseNumber: '',
        specialization: '',
        yearsOfExperience: undefined,
        biography: '',
        consultationFee: undefined,
        defaultDurationMinutes: undefined
      };
    } catch (e: any) {
      this.error = e?.response?.data?.message || 'Failed to update doctor profile';
    }
  }

  editProfile() {
    // If already in edit mode, toggle it off (for cancel)
    if (this.showEditProfile) {
      this.showEditProfile = false;
      return;
    }
    
    // Ensure currentUser is loaded
    if (!this.currentUser) {
      this.logger.error('Current user not loaded');
      return;
    }
    // Ensure doctorProfile is loaded
    if (!this.doctorProfile) {
      this.logger.error('Doctor profile not loaded');
      return;
    }
    this.editUserData = {
      firstName: this.currentUser.firstName || '',
      lastName: this.currentUser.lastName || '',
      phoneNumber: this.currentUser.phoneNumber || ''
    };
    this.editDoctorData = {
      medicalLicenseNumber: this.doctorProfile.medicalLicenseNumber || '',
      specialization: this.doctorProfile.specialization || '',
      yearsOfExperience: this.doctorProfile.yearsOfExperience,
      biography: this.doctorProfile.biography || '',
      consultationFee: this.doctorProfile.consultationFee,
      defaultDurationMinutes: this.doctorProfile.defaultDurationMinutes
    };
    this.showEditProfile = true;
  }

  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);
      });
    }
  }

  toggleProfileMenu(): void {
    this.showProfileMenu = !this.showProfileMenu;
    if (this.showProfileMenu) {
      this.showNotifications = false;
    }
  }

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


  toggleChatMenu(): void {
    this.showChatMenu = !this.showChatMenu;
    if (this.showChatMenu) {
      this.showNotifications = false;
      this.showProfileMenu = false;
      // Refresh conversations when opening the menu
      if (this.chatComponent) {
        this.chatComponent.refreshConversations();
      }
    } else {
      // Clear search when closing
      this.clearChatSearch();
    }
  }

  async openChatConversation(otherUserId: string): Promise<void> {
    if (this.chatComponent) {
      // Find the conversation
      const conversation = this.chatComponent.conversations.find(c => c.otherUserId === otherUserId);
      if (conversation) {
        // Select the conversation in chat component
        await this.chatComponent.selectConversation(conversation);
        // Close the menu and open the chat widget
        this.showChatMenu = false;
        this.showChatWidget = true;
      }
    }
  }

  async openChatWithUser(userId: string): Promise<void> {
    this.logger.debug('[DoctorComponent] openChatWithUser called with userId:', userId);
    if (this.chatComponent) {
      // Always ensure chat widget is visible
      this.showChatWidget = true;
      this.showChatMenu = false;
      
      // Try to find existing conversation
      const existingConversation = this.chatComponent.conversations.find(c => c.otherUserId === userId);
      if (existingConversation) {
        this.logger.debug('[DoctorComponent] Found existing conversation, selecting it');
        await this.chatComponent.selectConversation(existingConversation);
      } else {
        // Start a new conversation
        this.logger.debug('[DoctorComponent] No existing conversation, creating new one');
        await this.chatComponent.openConversation(userId);
      }
      // Clear search
      this.clearChatSearch();
      this.logger.debug('[DoctorComponent] Chat widget should now be visible, showChatWidget:', this.showChatWidget);
    } else {
      this.logger.error('[DoctorComponent] chatComponent is not available');
    }
  }

  toggleBlockedUsers(event?: Event): void {
    if (event) {
      event.stopPropagation();
    }
    this.showBlockedUsers = !this.showBlockedUsers;
    if (this.showBlockedUsers) {
      this.loadBlockedUsers();
      // Close chat menu when opening blocked users
      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;
    }
  }

  handleUnblockClick(user: ChatUser, event: Event): void {
    this.logger.debug('=== handleUnblockClick CALLED ===', user, event);
    alert('Button clicked! User: ' + user.firstName + ' ' + user.lastName);
    event.stopPropagation();
    event.preventDefault();
    this.unblockUser(user);
  }

  async unblockUser(user: ChatUser): Promise<void> {
    this.logger.debug('=== unblockUser METHOD CALLED ===', user);
    try {
      this.logger.debug('Unblocking user:', user.userId, user);
      this.logger.debug('User ID type:', typeof user.userId);
      this.logger.debug('User ID value:', user.userId);
      
      // Ensure userId is a string and trim any whitespace
      const userId = String(user.userId).trim();
      if (!userId || userId === 'undefined' || userId === 'null') {
        throw new Error('Invalid user ID: ' + userId);
      }
      
      this.logger.debug('Formatted user ID:', userId);
      this.logger.debug('Calling chatService.unblockUser with:', userId);
      
      await this.chatService.unblockUser(userId);
      
      // Remove from blocked users list
      this.blockedUsers = this.blockedUsers.filter(u => u.userId !== user.userId);
      
      // Refresh conversations to show unblocked user
      if (this.chatComponent) {
        await this.chatComponent.refreshConversations();
      }
      
      // Show success message
      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);
      this.logger.error('Error details:', {
        message: error?.message,
        response: error?.response?.data,
        status: error?.response?.status,
        userId: user.userId
      });
      
      let errorMessage = 'Failed to unblock user. Please try again.';
      if (error?.response?.data?.message) {
        errorMessage = error.response.data.message;
      } else if (error?.response?.data?.error) {
        errorMessage = error.response.data.error;
      } else if (error?.message) {
        errorMessage = error.message;
      }
      
      this.logger.error('Final error message:', errorMessage);
      
      await this.modalService.alert(
        errorMessage,
        'error',
        'Unblock Error'
      );
    }
  }

  private searchTimeout: any = null;

  async onChatSearch(event: Event): Promise<void> {
    const input = event.target as HTMLInputElement;
    const query = input.value.trim();
    this.chatSearchQuery = query;
    
    // Clear previous timeout
    if (this.searchTimeout) {
      clearTimeout(this.searchTimeout);
    }

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

    const queryLower = query.toLowerCase();

    // Filter existing conversations
    if (this.chatComponent?.conversations && this.chatComponent.conversations.length > 0) {
      this.filteredConversations = this.chatComponent.conversations.filter(conv =>
        conv.otherUserName.toLowerCase().includes(queryLower)
      );
    } else {
      this.filteredConversations = [];
    }

    // Debounce API search - only search if query is at least 2 characters
    if (query.length < 2) {
      this.chatSearchResults = [];
      return;
    }

    // Debounce the API call to avoid too many requests
    this.searchTimeout = setTimeout(async () => {
      try {
        if (this.currentUser?.role === 'DOCTOR') {
          const users = await this.chatService.searchPatients(query);
          this.logger.debug('Search patients results:', users);
          // Filter out users we already have conversations with
          const existingUserIds = this.chatComponent?.conversations?.map(c => c.otherUserId) || [];
          this.chatSearchResults = users.filter(user => 
            !existingUserIds.includes(user.userId)
          );
          this.logger.debug('Filtered search results:', this.chatSearchResults);
        } else if (this.currentUser?.role === 'PATIENT') {
          const users = await this.chatService.searchDoctors(query);
          this.logger.debug('Search doctors results:', users);
          const existingUserIds = this.chatComponent?.conversations?.map(c => c.otherUserId) || [];
          this.chatSearchResults = users.filter(user => 
            !existingUserIds.includes(user.userId)
          );
          this.logger.debug('Filtered search results:', this.chatSearchResults);
        }
      } catch (error) {
        this.logger.error('Error searching users:', error);
        this.chatSearchResults = [];
      }
    }, 300); // Wait 300ms after user stops typing
  }

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

  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' });
  }

  onImageError(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-small') || 
        avatarCircle.classList.contains('avatar-circle-medium'))) {
      avatarCircle.style.display = 'flex';
    }
  }

  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;
    }
  }

  @HostListener('document:click', ['$event'])
  onDocumentClick(event: MouseEvent): void {
    const target = event.target as HTMLElement;
    
    // Don't close if clicking on unblock button or its children
    if (target.closest('.unblock-button-dropdown')) {
      return;
    }
    
    if (!target.closest('.notification-container')) {
      this.showNotifications = false;
    }
    if (!target.closest('.profile-menu-container')) {
      this.showProfileMenu = false;
    }
    if (!target.closest('.chat-menu-container')) {
      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);
    }
    
    // Navigate to messages tab
    this.activeTab = 'chat';
    
    // Close notification dropdown
    this.showNotifications = 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();
  }

  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 doctor profile if available
        if (this.currentUser) {
          this.doctorProfile = await this.userService.getDoctorProfile();
        }
      } 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'
        );
      }
    }
  }
  
  // Patient Safety Methods
  async loadSafetyAlerts() {
    if (!this.doctorId) return;
    try {
      this.unacknowledgedCriticalResults = await this.patientSafetyService.getUnacknowledgedCriticalResultsByDoctorId(this.doctorId);
      this.unacknowledgedAlerts = await this.patientSafetyService.getAllUnacknowledgedAlerts();
      const previousCount = this.unacknowledgedAlertsCount;
      this.unacknowledgedAlertsCount = this.unacknowledgedAlerts.length + this.unacknowledgedCriticalResults.length;
      
      // Auto-open Safety Alerts tab if alerts appeared for the first time
      if (this.unacknowledgedAlertsCount > 0 && previousCount === 0 && this.activeTab !== 'safety') {
        this.activeTab = 'safety';
      }
    } catch (error: any) {
      this.logger.error('Error loading safety alerts:', error);
    }
  }
  
  async acknowledgeClinicalAlert(alertId: string) {
    try {
      await this.patientSafetyService.acknowledgeAlert(alertId);
      await this.loadSafetyAlerts();
    } catch (error: any) {
      this.logger.error('Error acknowledging alert:', error);
      await this.modalService.alert(
        'Failed to acknowledge alert',
        'error',
        'Error'
      );
    }
  }
  
  async resolveClinicalAlert(alertId: string) {
    try {
      await this.patientSafetyService.resolveAlert(alertId);
      await this.loadSafetyAlerts();
    } catch (error: any) {
      this.logger.error('Error resolving alert:', error);
      await this.modalService.alert(
        'Failed to resolve alert',
        'error',
        'Error'
      );
    }
  }
  
  async acknowledgeCriticalResult(resultId: string) {
    try {
      await this.patientSafetyService.acknowledgeCriticalResult(resultId, {});
      await this.loadSafetyAlerts();
    } catch (error: any) {
      this.logger.error('Error acknowledging critical result:', error);
      await this.modalService.alert(
        'Failed to acknowledge critical result',
        'error',
        'Error'
      );
    }
  }
  
  async createClinicalAlert() {
    if (!this.newAlert.patientId || !this.newAlert.title || !this.newAlert.description) {
      await this.modalService.alert(
        'Please fill in all required fields (Patient, Title, Description)',
        'warning',
        'Validation Error'
      );
      return;
    }
    
    try {
      await this.patientSafetyService.createAlert({
        patientId: this.newAlert.patientId,
        alertType: this.newAlert.alertType,
        severity: this.newAlert.severity,
        title: this.newAlert.title,
        description: this.newAlert.description,
        medicationName: this.newAlert.medicationName || undefined,
        relatedPrescriptionId: this.newAlert.relatedPrescriptionId || undefined
      });
      
      // Reset form
      this.newAlert = {
        patientId: '',
        alertType: 'DRUG_INTERACTION',
        severity: 'WARNING',
        title: '',
        description: '',
        medicationName: '',
        relatedPrescriptionId: null
      };
      this.showCreateAlertForm = false;
      
      // Refresh alerts
      await this.loadSafetyAlerts();
      
      await this.modalService.alert(
        'Alert created successfully!',
        'success',
        'Success'
      );
    } catch (error: any) {
      this.logger.error('Error creating alert:', error);
      await this.modalService.alert(
        error?.response?.data?.message || 'Failed to create alert',
        'error',
        'Error'
      );
    }
  }
  
  toggleCreateAlertForm() {
    this.showCreateAlertForm = !this.showCreateAlertForm;
    if (this.showCreateAlertForm && !this.newAlert.patientId && this.patients.length > 0) {
      // Pre-select first patient if available
      this.newAlert.patientId = this.patients[0].id;
    }
  }
  
  getRelativeTime(dateString: string): string {
    const date = new Date(dateString);
    const now = new Date();
    const diffMs = now.getTime() - date.getTime();
    const diffMins = Math.floor(diffMs / 60000);
    const diffHours = Math.floor(diffMins / 60);
    const diffDays = Math.floor(diffHours / 24);
    
    if (diffMins < 1) return 'Just now';
    if (diffMins < 60) return `${diffMins}m ago`;
    if (diffHours < 24) return `${diffHours}h ago`;
    if (diffDays < 30) return `${diffDays}d ago`;
    return date.toLocaleDateString();
  }
  
  async handleSafetyCheckRequest() {
    // Refresh safety alerts when requested from child component (e.g., after prescription creation)
    const previousAlertCount = this.unacknowledgedAlertsCount;
    await this.loadSafetyAlerts();
    
    // Check if new safety alerts were detected
    if (this.unacknowledgedAlertsCount > previousAlertCount) {
      const newAlertsCount = this.unacknowledgedAlertsCount - previousAlertCount;
      await this.modalService.alert(
        `${newAlertsCount} new safety alert${newAlertsCount > 1 ? 's' : ''} detected. Please review in the Safety Alerts tab.`,
        'warning',
        'Safety Alert Detected'
      );
      // Auto-open Safety Alerts tab if not already open
      if (this.activeTab !== 'safety') {
        this.activeTab = 'safety';
      }
    }
  }
  
  async handlePatientRemoved() {
    this.logger.debug('[handlePatientRemoved] Starting refresh...');
    // Refresh appointments FIRST (they're filtered by deletedByDoctor), 
    // then extract patients from the updated appointments
    await this.loadAppointments();
    this.logger.debug('[handlePatientRemoved] Appointments loaded:', this.appointments.length);
    // Now extract patients from appointments (will exclude deleted ones)
    // This ensures only patients with visible (non-deleted) appointments are shown
    const beforeCount = this.patients.length;
    this.extractPatientsFromAppointments();
    this.logger.debug('[handlePatientRemoved] Patients before:', beforeCount, 'after:', this.patients.length);
    this.logger.debug('[handlePatientRemoved] Patient IDs:', this.patients.map(p => p.id));
    // Don't load all patients here - we want only those with appointments
    // The removed patient will be filtered out automatically
  }
  
  async handleCreateAppointmentRequest(patient: any) {
    this.logger.debug('[DoctorComponent] handleCreateAppointmentRequest - patient:', patient);
    // Select the patient and open create appointment form
    this.selectedPatientId = patient.id;
    this.newAppointment.patientId = patient.id;
    
    // Ensure the patient is in the patients array for the dropdown
    // Check if patient exists in current patients list
    const patientExists = this.patients.some(p => p.id === patient.id);
    if (!patientExists) {
      // Add patient to the list if not already there
      this.patients = [...this.patients, {
        id: patient.id,
        userId: patient.userId,
        firstName: patient.firstName || '',
        lastName: patient.lastName || '',
        displayName: `${patient.firstName || ''} ${patient.lastName || ''}`.trim(),
        email: patient.email || '',
        phoneNumber: patient.phoneNumber || ''
      }];
      this.logger.debug('[DoctorComponent] Added patient to list:', patient.id);
    }
    
    this.showCreateForm = true;
    // Switch to create appointment tab to show the form
    this.activeTab = 'create';
    this.logger.debug('[DoctorComponent] handleCreateAppointmentRequest - patient ID:', patient.id, 'activeTab:', this.activeTab);
  }
  
  async handleStartChatRequest(data: any) {
    try {
      this.logger.debug('[DoctorComponent] handleStartChatRequest called with data:', data);
      // Open chat with the patient
      if (this.chatComponent) {
        // Use openChatWithUser which will create a new conversation if it doesn't exist
        await this.openChatWithUser(data.userId);
        this.logger.debug('[DoctorComponent] Chat opened successfully with userId:', data.userId);
      } else {
        this.logger.error('[DoctorComponent] ChatComponent not available');
        await this.modalService.alert(
          'Chat feature is not available at the moment',
          'warning',
          'Chat Unavailable'
        );
      }
    } catch (error: any) {
      this.logger.error('[DoctorComponent] Error starting chat:', error);
      await this.modalService.alert(
        error?.message || 'Failed to start chat',
        'error',
        'Error'
      );
    }
  }
}

