import { Component, Input, OnInit, OnChanges, SimpleChanges, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { UserService } from '../../../../services/user.service';
import { AppointmentService } from '../../../../services/appointment.service';
import { ModalService } from '../../../../services/modal.service';
import { ChatService } from '../../../../services/chat.service';
import { LoggerService } from '../../../../services/logger.service';

@Component({
  selector: 'app-patients',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './patients.component.html',
  styleUrl: './patients.component.scss'
})
export class PatientsComponent implements OnInit, OnChanges {
  @Input() patients: any[] = []; // Fallback from appointments
  @Output() patientRemoved = new EventEmitter<void>();
  @Output() patientSelected = new EventEmitter<any>();
  @Output() createAppointmentRequested = new EventEmitter<any>();
  @Output() startChatRequested = new EventEmitter<any>();
  
  loading = false;
  loadingPatients = false;
  searchTerm: string = '';
  filteredPatients: any[] = [];
  allPatients: any[] = []; // All patients from system

  constructor(
    private userService: UserService,
    private appointmentService: AppointmentService,
    private modalService: ModalService,
    private chatService: ChatService,
    private cdr: ChangeDetectorRef,
    private logger: LoggerService
  ) {}

  async ngOnInit() {
    this.logger.debug('[PatientsComponent] ngOnInit - patients:', this.patients.length);
    // Load all patients from system
    await this.loadAllPatients();
    // Initialize filtered patients
    this.applySearch();
  }

  async loadAllPatients() {
    try {
      this.loadingPatients = true;
      const patients = await this.userService.getAllPatients();
      this.logger.debug('[PatientsComponent] Loaded all patients from system:', patients.length);
      
      // Map PatientProfile to the format we need
      // PatientProfile has firstName, lastName, email, phoneNumber directly (not nested in user)
      // Now also includes userId for chat functionality
      this.allPatients = patients.map(p => ({
        id: p.id,
        userId: p.userId, // Include userId for chat functionality
        firstName: p.firstName || '',
        lastName: p.lastName || '',
        email: p.email || '',
        phoneNumber: p.phoneNumber || '',
        displayName: `${p.firstName || ''} ${p.lastName || ''}`.trim(),
        bloodType: p.bloodType,
        allergies: p.allergies || []
      }));
      
      // Merge with patients from appointments (if any) to avoid duplicates
      const existingIds = new Set(this.allPatients.map(p => p.id));
      const newPatients = this.patients.filter(p => p.id && !existingIds.has(p.id));
      this.allPatients = [...this.allPatients, ...newPatients];
      
      // Update patients array to include all
      this.patients = this.allPatients;
      this.applySearch();
    } catch (error: any) {
      this.logger.error('[PatientsComponent] Error loading all patients:', error);
      // Fallback to patients from input
      this.patients = this.patients || [];
      this.applySearch();
    } finally {
      this.loadingPatients = false;
      this.cdr.detectChanges();
    }
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes['patients'] && !changes['patients'].firstChange) {
      this.logger.debug('[PatientsComponent] ngOnChanges - patients changed:', {
        previousValue: changes['patients'].previousValue?.length,
        currentValue: changes['patients'].currentValue?.length
      });
      // Merge with all patients if needed
      if (this.allPatients.length > 0) {
        const existingIds = new Set(this.allPatients.map(p => p.id));
        const newPatients = this.patients.filter(p => p.id && !existingIds.has(p.id));
        this.allPatients = [...this.allPatients, ...newPatients];
        this.patients = this.allPatients;
      }
      this.applySearch();
    }
  }

  applySearch() {
    this.logger.debug('[PatientsComponent] applySearch called', {
      searchTerm: this.searchTerm,
      patientsCount: this.patients.length,
      filteredCount: this.filteredPatients.length
    });
    
    // If no search term, show all patients
    if (!this.searchTerm || this.searchTerm.trim() === '') {
      this.filteredPatients = [...this.patients];
      this.logger.debug('[PatientsComponent] No search term, showing all patients:', this.filteredPatients.length);
      return;
    }

    // Filter patients based on search term
    const search = this.searchTerm.toLowerCase().trim();
    this.logger.debug('[PatientsComponent] Filtering with search term:', search);
    
    this.filteredPatients = this.patients.filter(patient => {
      // Search by name (first name + last name)
      const fullName = `${patient.firstName || ''} ${patient.lastName || ''}`.toLowerCase();
      const nameMatch = fullName.includes(search);
      
      // Search by email
      const emailMatch = patient.email && patient.email.toLowerCase().includes(search);
      
      // Search by phone number
      const phoneMatch = patient.phoneNumber && patient.phoneNumber.toLowerCase().includes(search);
      
      const matches = nameMatch || emailMatch || phoneMatch;
      if (matches) {
        this.logger.debug('[PatientsComponent] Patient matches:', patient.firstName, patient.lastName);
      }
      return matches;
    });
    
    this.logger.debug('[PatientsComponent] Filtered results:', this.filteredPatients.length);
  }

  onSearchChange() {
    this.logger.debug('[PatientsComponent] onSearchChange called, searchTerm:', this.searchTerm);
    this.applySearch();
    this.cdr.detectChanges(); // Force change detection
  }

  clearSearch() {
    this.searchTerm = '';
    this.applySearch();
  }

  async loadPatients() {
    // Reload all patients from system
    await this.loadAllPatients();
  }
  
  async createAppointment(patient: any) {
    this.createAppointmentRequested.emit(patient);
  }
  
  async startChat(patient: any) {
    try {
      // Get the user ID for the patient
      // PatientProfile now includes userId directly
      let userId: string | null = patient.userId || null;
      
      // If userId is not available, try to find it by searching (fallback)
      if (!userId) {
        this.logger.warn('[PatientsComponent] userId not found in patient object, searching...', patient);
        
        // Try searching by full name
        if (patient.firstName && patient.lastName) {
          try {
            const fullName = `${patient.firstName} ${patient.lastName}`;
            const chatUsers = await this.chatService.searchPatients(fullName);
            const matchingUser = chatUsers.find(u => 
              u.firstName?.toLowerCase() === patient.firstName?.toLowerCase() &&
              u.lastName?.toLowerCase() === patient.lastName?.toLowerCase()
            );
            if (matchingUser) {
              userId = matchingUser.userId;
              this.logger.debug('[PatientsComponent] Found user ID by name search:', userId);
            }
          } catch (e) {
            this.logger.warn('[PatientsComponent] Could not search by name:', e);
          }
        }
      }
      
      if (!userId) {
        this.logger.error('[PatientsComponent] Could not find user ID for patient:', {
          id: patient.id,
          userId: patient.userId,
          firstName: patient.firstName,
          lastName: patient.lastName,
          email: patient.email
        });
        await this.modalService.alert(
          `Could not find patient user information for ${patient.firstName} ${patient.lastName}. The patient may not be available for chat.`,
          'error',
          'Error'
        );
        return;
      }
      
      // Start chat with patient
      this.logger.debug('[PatientsComponent] Starting chat with userId:', userId);
      this.startChatRequested.emit({
        userId: userId,
        patientId: patient.id,
        patientName: `${patient.firstName} ${patient.lastName}`
      });
    } catch (error: any) {
      this.logger.error('[PatientsComponent] Error starting chat:', error);
      await this.modalService.alert(
        error?.message || 'Failed to start chat with patient',
        'error',
        'Error'
      );
    }
  }
  
  viewPatient(patient: any) {
    this.patientSelected.emit(patient);
  }

  async removePatientFromHistory(patient: any) {
    const confirmed = await this.modalService.confirm(
      `Are you sure you want to remove ${patient.firstName} ${patient.lastName} from your history? This will hide all appointments with this patient from your view. This action cannot be undone.`,
      'Remove Patient from History',
      'warning'
    );
    
    if (!confirmed) return;

    try {
      this.loading = true;
      await this.appointmentService.removePatientFromHistory(patient.id);
      await this.modalService.alert(
        'Patient removed from history successfully',
        'success',
        'Success'
      );
      
      // Remove from local list immediately (optimistic update)
      this.patients = this.patients.filter(p => p.id !== patient.id);
      this.filteredPatients = this.filteredPatients.filter(p => p.id !== patient.id);
      
      // Emit event to parent to refresh data (will update the @Input binding)
      this.patientRemoved.emit();
    } catch (error: any) {
      this.logger.error('Error removing patient from history:', error);
      await this.modalService.alert(
        error?.message || 'Failed to remove patient from history',
        'error',
        'Error'
      );
    } finally {
      this.loading = false;
    }
  }
}