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

@Component({
  selector: 'app-create-appointment',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './create-appointment.component.html',
  styleUrl: './create-appointment.component.scss'
})
export class CreateAppointmentComponent implements OnInit, OnChanges {
  @Input() patients: any[] = [];
  @Input() doctorId: string | null = null;
  @Input() selectedPatientId: string | null = null;
  @Output() appointmentCreated = new EventEmitter<void>();
  
  error: string | null = null;
  successMessage: string | null = null;
  showPopup: boolean = false;
  popupType: 'success' | 'error' = 'success';
  creatingAppointment: boolean = false; // Loading state during creation
  
  // Patient search
  patientSearchQuery: string = '';
  filteredPatients: any[] = [];
  allRegisteredPatients: any[] = []; // All patients in the system
  loadingPatients: boolean = false;
  selectedPatientName: string = ''; // Store selected patient name for display
  
  newAppointment = {
    patientId: '',
    scheduledDate: '',
    scheduledTime: '',
    durationInMinutes: 30
  };

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

  async ngOnInit() {
    // Load all registered patients from the system first
    await this.loadAllPatients();
    
    // Auto-fill patient ID if provided
    if (this.selectedPatientId) {
      this.newAppointment.patientId = this.selectedPatientId;
      this.logger.debug('[CreateAppointmentComponent] Auto-filled patient ID on init:', this.selectedPatientId);
      // Find and set the patient name
      const allPatients = [...this.allRegisteredPatients, ...(this.patients || [])];
      const selectedPatient = allPatients.find(p => p.id === this.selectedPatientId);
      if (selectedPatient) {
        this.selectedPatientName = selectedPatient.displayName || `${selectedPatient.firstName} ${selectedPatient.lastName}`;
      }
    }
    
    // Initialize filtered patients
    this.filterPatients();
  }

  ngOnChanges(changes: SimpleChanges) {
    // Auto-fill patient ID when selectedPatientId changes
    if (changes['selectedPatientId'] && this.selectedPatientId) {
      this.newAppointment.patientId = this.selectedPatientId;
      this.logger.debug('[CreateAppointmentComponent] Auto-filled patient ID on change:', this.selectedPatientId);
      // Find and set the patient name
      const allPatients = [...this.allRegisteredPatients, ...(this.patients || [])];
      const selectedPatient = allPatients.find(p => p.id === this.selectedPatientId);
      if (selectedPatient) {
        this.selectedPatientName = selectedPatient.displayName || `${selectedPatient.firstName} ${selectedPatient.lastName}`;
      }
    }
    // Update filtered patients when patients list changes (for backward compatibility)
    if (changes['patients']) {
      this.filterPatients();
    }
  }

  async loadAllPatients() {
    try {
      this.loadingPatients = true;
      const allPatients = await this.userService.getAllPatients();
      // Convert PatientProfile to the format expected by the component
      this.allRegisteredPatients = allPatients.map(patient => ({
        id: patient.id,
        userId: patient.userId,
        firstName: patient.firstName,
        lastName: patient.lastName,
        displayName: `${patient.firstName} ${patient.lastName}`,
        email: patient.email,
        phoneNumber: patient.phoneNumber
      }));
      this.logger.debug('[CreateAppointmentComponent] Loaded all registered patients:', this.allRegisteredPatients.length);
      // Update filtered patients after loading
      this.filterPatients();
    } catch (e: any) {
      this.logger.error('[CreateAppointmentComponent] Failed to load all patients:', e);
      // Fall back to the patients passed from parent if loading fails
      this.allRegisteredPatients = this.patients || [];
    } finally {
      this.loadingPatients = false;
    }
  }

  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;
    }
    // Check both all registered patients and the passed patients list
    const allPatients = [...this.allRegisteredPatients, ...(this.patients || [])];
    return !allPatients.some(p => p.id === this.newAppointment.patientId);
  }

  async createAppointment() {
    // Clear previous messages - but keep selectedPatientName for display
    this.error = null;
    this.successMessage = null;
    this.showPopup = false; // Ensure popup is closed
    
    if (!this.newAppointment.patientId || !this.newAppointment.scheduledDate || !this.newAppointment.scheduledTime) {
      this.error = 'Please fill in all required fields';
      this.showErrorPopup('Please fill in all required fields: Patient, Date, and Time are required.');
      return;
    }

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

    this.creatingAppointment = true;
    
    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
      });
      
      // Success - clear form and show success message
      const patientName = this.selectedPatientName || 'Patient';
      const appointmentDate = new Date(this.newAppointment.scheduledDate).toLocaleDateString();
      const appointmentTime = this.newAppointment.scheduledTime;
      
      this.newAppointment = {
        patientId: '',
        scheduledDate: '',
        scheduledTime: '',
        durationInMinutes: 30
      };
      this.selectedPatientName = '';
      this.patientSearchQuery = '';
      this.error = null;
      
      // Show comprehensive success message
      const successMsg = `Appointment created successfully! Scheduled for ${appointmentDate} at ${appointmentTime} with ${patientName}.`;
      this.logger.debug('[CreateAppointment] Showing success popup:', successMsg);
      
      // Set success message first (for inline display)
      this.successMessage = successMsg;
      this.popupType = 'success';
      this.showPopup = true;
      
      // Force change detection immediately
      this.cdr.detectChanges();
      
      this.logger.debug('[CreateAppointment] showPopup after setting:', this.showPopup);
      this.logger.debug('[CreateAppointment] successMessage after setting:', this.successMessage);
      
      // Verify popup element exists in DOM after a short delay
      setTimeout(() => {
        // Try to find popup in the component's view first
        const popupElement = document.querySelector('app-create-appointment .notification-popup') || 
                            document.querySelector('.notification-popup');
        this.logger.debug('[CreateAppointment] Popup element in DOM:', popupElement);
        if (popupElement) {
          const styles = window.getComputedStyle(popupElement);
          this.logger.debug('[CreateAppointment] Popup computed styles:', {
            display: styles.display,
            visibility: styles.visibility,
            opacity: styles.opacity,
            zIndex: styles.zIndex,
            position: styles.position,
            top: styles.top,
            right: styles.right
          });
          
          // Force show if hidden
          if (styles.display === 'none' || styles.visibility === 'hidden' || parseFloat(styles.opacity) === 0) {
            this.logger.warn('[CreateAppointment] Popup is hidden! Forcing visibility...');
            (popupElement as HTMLElement).style.setProperty('display', 'block', 'important');
            (popupElement as HTMLElement).style.setProperty('visibility', 'visible', 'important');
            (popupElement as HTMLElement).style.setProperty('opacity', '1', 'important');
          }
        } else {
          this.logger.error('[CreateAppointment] Popup element NOT found in DOM!');
          this.logger.debug('[CreateAppointment] showPopup value:', this.showPopup);
          this.logger.debug('[CreateAppointment] popupType value:', this.popupType);
          this.logger.debug('[CreateAppointment] successMessage value:', this.successMessage);
          
          // Try to manually create and append popup to body as fallback
          this.createFallbackPopup(successMsg);
        }
      }, 100);
      
      this.appointmentCreated.emit();
      
      // Auto-close popup after 5 seconds
      setTimeout(() => {
        this.closePopup();
        this.cdr.detectChanges();
      }, 5000);
      
      // Reload patients after creating appointment
      await this.loadAllPatients();
    } catch (e: any) {
      this.logger.error('Error creating appointment:', e);
      
      // Extract error message from various possible locations
      let errorMessage = 'Failed to create appointment';
      let shouldRedirect = false;
      
      if (e?.response?.data) {
        errorMessage = e.response.data.message || 
                      e.response.data.error || 
                      e.response.data.details ||
                      (typeof e.response.data === 'string' ? e.response.data : errorMessage);
      } else if (e?.message) {
        errorMessage = e.message;
      }
      
      // Provide more specific error messages based on status code
      if (e?.response?.status === 401) {
        errorMessage = 'Your session has expired. Please refresh the page or log in again.';
        // Don't auto-redirect - let user decide
        shouldRedirect = false; // Changed: don't auto-redirect, let user handle it
      } else if (e?.response?.status === 400) {
        if (!errorMessage || errorMessage === 'Failed to create appointment') {
          errorMessage = 'Invalid appointment details. Please check all fields and try again.';
        }
      } else if (e?.response?.status === 403) {
        errorMessage = 'You do not have permission to create appointments.';
      } else if (e?.response?.status === 404) {
        errorMessage = 'Doctor or patient not found. Please refresh the page.';
      } else if (e?.response?.status === 409) {
        errorMessage = errorMessage || 'This appointment conflicts with an existing appointment.';
      }
      
      this.error = errorMessage;
      // Show comprehensive error message
      const errorMsg = `Failed to create appointment: ${errorMessage}`;
      this.showErrorPopup(errorMsg);
      
      // Only redirect if we got a 401 from the server and user hasn't manually dismissed
      // Note: Removed auto-redirect to prevent redirect loops - user can manually refresh/login
      // if (shouldRedirect) {
      //   setTimeout(() => {
      //     window.location.href = '/login';
      //   }, 3000);
      // }
    } finally {
      this.creatingAppointment = false;
    }
  }

  showSuccessPopup(message: string) {
    this.logger.debug('[showSuccessPopup] Called with message:', message);
    this.successMessage = message;
    this.popupType = 'success';
    this.showPopup = true;
    this.logger.debug('[showSuccessPopup] showPopup set to:', this.showPopup);
    this.logger.debug('[showSuccessPopup] successMessage set to:', this.successMessage);
    this.logger.debug('[showSuccessPopup] popupType set to:', this.popupType);
    
    // Force change detection
    this.cdr.detectChanges();
    
    // Keep success message visible longer so user can see it
    setTimeout(() => {
      this.closePopup();
      this.cdr.detectChanges();
      // Keep success message visible even after popup closes
      // It will be cleared when user starts creating a new appointment
    }, 5000); // Auto-close after 5 seconds (increased from 3)
  }

  showErrorPopup(message: string) {
    this.error = message;
    this.popupType = 'error';
    this.showPopup = true;
    
    // For authentication errors, show longer and don't auto-close
    const autoCloseDelay = message.includes('session') || message.includes('expired') || message.includes('log in') 
      ? 8000  // 8 seconds for auth errors so user can read
      : 5000; // 5 seconds for other errors
      
    setTimeout(() => {
      this.closePopup();
    }, autoCloseDelay);
  }

  refreshPage() {
    window.location.reload();
  }

  closePopup() {
    this.showPopup = false;
    // Don't clear successMessage here - keep it visible in inline message
    // Only clear error when popup closes (user dismissed it)
    if (this.popupType === 'error') {
      // Keep error visible in inline message
    }
  }

  filterPatients() {
    // Use all registered patients for search, but also include patients from parent (for backward compatibility)
    const allPatients = [...this.allRegisteredPatients];
    // Add patients from parent that aren't already in allRegisteredPatients
    (this.patients || []).forEach(patient => {
      if (!allPatients.some(p => p.id === patient.id)) {
        allPatients.push(patient);
      }
    });

    if (!this.patientSearchQuery || this.patientSearchQuery.trim() === '') {
      this.filteredPatients = allPatients;
      // Update selected patient name if patient is still in the list
      if (this.newAppointment.patientId) {
        const selectedPatient = allPatients.find(p => p.id === this.newAppointment.patientId);
        if (selectedPatient) {
          this.selectedPatientName = selectedPatient.displayName || `${selectedPatient.firstName} ${selectedPatient.lastName}`;
        } else {
          // Clear selection if patient is no longer in the list
          this.newAppointment.patientId = '';
          this.selectedPatientName = '';
        }
      }
      return;
    }

    const query = this.patientSearchQuery.toLowerCase().trim();
    this.filteredPatients = allPatients.filter(patient => {
      const firstName = (patient.firstName || '').toLowerCase();
      const lastName = (patient.lastName || '').toLowerCase();
      const fullName = `${firstName} ${lastName}`.trim();
      const displayName = (patient.displayName || fullName).toLowerCase();
      const email = (patient.email || '').toLowerCase();
      
      return firstName.includes(query) || 
             lastName.includes(query) || 
             fullName.includes(query) ||
             displayName.includes(query) ||
             email.includes(query);
    });

    // Auto-fill if exactly one patient is found
    if (this.filteredPatients.length === 1) {
      const foundPatient = this.filteredPatients[0];
      if (this.newAppointment.patientId !== foundPatient.id) {
        this.newAppointment.patientId = foundPatient.id;
        this.selectedPatientName = foundPatient.displayName || `${foundPatient.firstName} ${foundPatient.lastName}`;
        // Don't show popup for auto-selection - just update the name
        // The green banner below the dropdown will show the patient is selected
      }
    } else if (this.filteredPatients.length === 0) {
      // Clear selection if no patients found
      this.newAppointment.patientId = '';
      this.selectedPatientName = '';
    }
  }

  onPatientSearchChange() {
    this.filterPatients();
  }

  clearPatientSearch() {
    this.patientSearchQuery = '';
    this.filterPatients();
  }

  createFallbackPopup(message: string) {
    // Create a fallback popup directly in the DOM if Angular isn't rendering it
    const existingPopup = document.getElementById('appointment-success-popup');
    if (existingPopup) {
      existingPopup.remove();
    }
    
    const popup = document.createElement('div');
    popup.id = 'appointment-success-popup';
    popup.className = 'notification-popup popup-success';
    popup.style.cssText = 'position: fixed !important; top: 20px !important; right: 20px !important; z-index: 99999 !important; min-width: 350px; max-width: 500px; background: white !important; border-radius: 8px; box-shadow: 0 10px 25px rgba(0,0,0,0.2) !important; border: 2px solid #4caf50; animation: slideInRight 0.3s ease-out; display: block !important; visibility: visible !important; opacity: 1 !important; pointer-events: auto !important;';
    
    popup.innerHTML = `
      <div style="display: flex; align-items: flex-start; gap: 1rem; padding: 1.5rem; position: relative;">
        <div style="flex-shrink: 0; width: 48px; height: 48px; border-radius: 50%; display: flex; align-items: center; justify-content: center; background: rgba(76, 175, 80, 0.1);">
          <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="width: 24px; height: 24px; color: #4caf50;">
            <path d="M20 6L9 17L4 12" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
            <path d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2Z" stroke="currentColor" stroke-width="2"/>
          </svg>
        </div>
        <div style="flex: 1;">
          <h3 style="margin: 0 0 0.5rem 0; font-size: 1.25rem; font-weight: 600; color: #333;">✓ Success!</h3>
          <p style="margin: 0; font-size: 0.95rem; color: #666; line-height: 1.5;">${message}</p>
        </div>
        <button type="button" onclick="this.parentElement.parentElement.remove()" style="position: absolute; top: 0.75rem; right: 0.75rem; background: none; border: none; cursor: pointer; padding: 0.25rem; color: #999; opacity: 0.7;" aria-label="Close">
          <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style="width: 20px; height: 20px;">
            <path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
          </svg>
        </button>
      </div>
      <div style="height: 4px; background: linear-gradient(90deg, #4caf50, #66bb6a); animation: progressBar 5s linear;"></div>
    `;
    
    document.body.appendChild(popup);
    this.logger.debug('[CreateAppointment] Fallback popup created and appended to body');
    
    // Auto-remove after 5 seconds
    setTimeout(() => {
      if (popup.parentElement) {
        popup.remove();
      }
    }, 5000);
  }

  showPatientFoundNotification(patient: any) {
    const patientName = patient.displayName || `${patient.firstName} ${patient.lastName}`;
    // Show a simple inline message for patient selection, not the appointment creation popup
    // Don't use the same popup system - just update the selectedPatientName which shows in the green banner
    // The successMessage and popup are only for appointment creation
    this.logger.debug(`Patient found and selected: ${patientName}`);
  }

  onPatientSelect(patientId: string) {
    if (patientId) {
      const selectedPatient = this.filteredPatients.find(p => p.id === patientId);
      if (selectedPatient) {
        this.selectedPatientName = selectedPatient.displayName || `${selectedPatient.firstName} ${selectedPatient.lastName}`;
        // Don't show popup for patient selection - just update the name
        // The green banner below the dropdown will show the patient is selected
        // Clear search after selection to show all patients in dropdown
        this.patientSearchQuery = '';
        this.filterPatients();
      }
    } else {
      this.selectedPatientName = '';
    }
  }
}