import { Component, Input, Output, EventEmitter, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { MedicalRecordService, MedicalRecord, MedicalRecordRequest, VitalSigns, VitalSignsRequest, LabResultRequest } from '../../../../services/medical-record.service';
import { UserService, PatientProfile } from '../../../../services/user.service';
import { ModalService } from '../../../../services/modal.service';
import { LoggerService } from '../../../../services/logger.service';

@Component({
  selector: 'app-ehr',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './ehr.component.html',
  styleUrl: './ehr.component.scss'
})
export class EhrComponent implements OnInit, OnChanges {
  @Input() doctorId: string | null = null;
  @Input() selectedPatientId: string | null = null;
  @Input() patients: any[] = [];
  @Output() patientSelected = new EventEmitter<string>();
  @Output() dataChanged = new EventEmitter<void>();

  // State
  showAllRecords = false;
  activeTab: 'records' | 'vitals' | 'labResults' = 'records';
  loading = false;
  error: string | null = null;
  
  // Local patient selection for dropdown (separate from Input)
  localSelectedPatientId: string | null = null;
  
  // Patient search
  patientSearchQuery: string = '';
  filteredPatients: any[] = [];

  // Medical Records
  medicalRecords: MedicalRecord[] = [];
  allMedicalRecords: MedicalRecord[] = [];
  showCreateMedicalRecord = false;
  newMedicalRecord: MedicalRecordRequest = {
    patientId: '',
    doctorId: '',
    recordType: 'NOTE',
    title: '',
    content: '',
    diagnosisCode: ''
  };

  // Vital Signs
  vitalSigns: VitalSigns[] = [];
  latestVitalSigns: VitalSigns | null = null;
  showCreateVitalSigns = false;
  newVitalSigns: VitalSignsRequest = {
    patientId: '',
    temperature: undefined,
    bloodPressureSystolic: undefined,
    bloodPressureDiastolic: undefined,
    heartRate: undefined,
    respiratoryRate: undefined,
    oxygenSaturation: undefined,
    weight: undefined,
    height: undefined,
    notes: ''
  };

  // Lab Results
  labResults: any[] = [];
  showCreateLabResult = false;
  showUpdateLabResult = false;
  selectedLabResult: any = null;
  newLabResult: LabResultRequest = {
    patientId: undefined as any,
    doctorId: '',
    testName: '',
    resultValue: '',
    status: 'PENDING',
    orderedDate: new Date().toISOString().split('T')[0]
  };

  // Patient Profile Modal
  selectedPatientProfile: PatientProfile | null = null;
  showPatientProfileModal = false;

  constructor(
    private medicalRecordService: MedicalRecordService,
    private userService: UserService,
    private modalService: ModalService,
    private logger: LoggerService
  ) {}

  ngOnInit() {
    if (this.doctorId) {
      this.newMedicalRecord.doctorId = this.doctorId;
      this.newLabResult.doctorId = this.doctorId;
      this.loadAllDoctorRecords();
    }
    // Initialize local selection from Input if provided, but don't auto-load
    // This allows parent to set initial selection, but user must explicitly choose
    if (this.selectedPatientId) {
      this.localSelectedPatientId = this.selectedPatientId;
    }
    // Initialize filtered patients
    this.filterPatients();
  }

  ngOnChanges(changes: SimpleChanges) {
    if (changes['doctorId'] && this.doctorId) {
      this.newMedicalRecord.doctorId = this.doctorId;
      this.newLabResult.doctorId = this.doctorId;
      if (!this.allMedicalRecords.length) {
        this.loadAllDoctorRecords();
      }
    }
    // Update local selection when Input changes, but don't auto-load data
    // User must explicitly select a patient from the dropdown
    if (changes['selectedPatientId']) {
      if (this.selectedPatientId) {
        this.localSelectedPatientId = this.selectedPatientId;
      } else {
        this.localSelectedPatientId = null;
        this.showAllRecords = true;
      }
    }
    // Update filtered patients when patients list changes
    if (changes['patients']) {
      this.filterPatients();
    }
  }

  async loadAllDoctorRecords() {
    if (!this.doctorId) return;
    try {
      this.loading = true;
      this.allMedicalRecords = await this.medicalRecordService.getMedicalRecordsByDoctorId(this.doctorId);
    } catch (e: any) {
      this.logger.error('Error loading all doctor records:', e);
      this.error = e?.response?.data?.error || 'Failed to load medical records';
      this.allMedicalRecords = [];
    } finally {
      this.loading = false;
    }
  }

  async loadPatientData() {
    if (!this.localSelectedPatientId) return;
    await Promise.all([
      this.loadPatientMedicalRecords(),
      this.loadPatientVitalSigns(),
      this.loadPatientLabResults()
    ]);
  }

  async loadPatientMedicalRecords() {
    if (!this.localSelectedPatientId) return;
    try {
      this.loading = true;
      this.medicalRecords = await this.medicalRecordService.getMedicalRecordsByPatientId(this.localSelectedPatientId);
    } catch (e: any) {
      this.logger.error('Error loading medical records:', e);
      this.error = e?.response?.data?.error || 'Failed to load medical records';
      this.medicalRecords = [];
    } finally {
      this.loading = false;
    }
  }

  async loadPatientVitalSigns() {
    if (!this.localSelectedPatientId) return;
    try {
      this.loading = true;
      [this.vitalSigns, this.latestVitalSigns] = await Promise.all([
        this.medicalRecordService.getVitalSignsByPatientId(this.localSelectedPatientId),
        this.medicalRecordService.getLatestVitalSignsByPatientId(this.localSelectedPatientId)
      ]);
    } catch (e: any) {
      this.logger.error('Error loading vital signs:', e);
      this.error = e?.response?.data?.error || 'Failed to load vital signs';
      this.vitalSigns = [];
      this.latestVitalSigns = null;
    } finally {
      this.loading = false;
    }
  }

  async loadPatientLabResults() {
    if (!this.localSelectedPatientId) return;
    try {
      this.loading = true;
      this.labResults = await this.medicalRecordService.getLabResultsByPatientId(this.localSelectedPatientId);
    } catch (e: any) {
      this.logger.error('Error loading lab results:', e);
      this.error = e?.response?.data?.error || 'Failed to load lab results';
      this.labResults = [];
    } finally {
      this.loading = false;
    }
  }

  selectPatient(patientId: string | null) {
    if (!patientId) {
      // Clear selection
      this.localSelectedPatientId = null;
      this.selectedPatientId = null;
      this.showAllRecords = true;
      this.patientSelected.emit('');
      // Clear patient-specific data
      this.medicalRecords = [];
      this.vitalSigns = [];
      this.latestVitalSigns = null;
      this.labResults = [];
      return;
    }
    
    // User explicitly selected a patient - load their data
    this.localSelectedPatientId = patientId;
    this.selectedPatientId = patientId;
    this.showAllRecords = false;
    this.patientSelected.emit(patientId);
    this.loadPatientData();
  }

  async toggleRecordsView() {
    this.showAllRecords = !this.showAllRecords;
    if (this.showAllRecords) {
      await this.loadAllDoctorRecords();
      // Clear patient selection when showing all records
      this.localSelectedPatientId = null;
    } else if (this.localSelectedPatientId) {
      // Only load if patient is explicitly selected
      await this.loadPatientData();
    }
  }

  // Medical Records Methods
  openCreateMedicalRecord() {
    this.showCreateMedicalRecord = !this.showCreateMedicalRecord;
    if (this.showCreateMedicalRecord) {
      this.newMedicalRecord = {
        patientId: this.localSelectedPatientId || '',
        doctorId: this.doctorId || '',
        recordType: 'NOTE',
        title: '',
        content: '',
        diagnosisCode: ''
      };
    }
  }

  async createMedicalRecord() {
    if (!this.newMedicalRecord.patientId || !this.newMedicalRecord.title || !this.newMedicalRecord.content) {
      this.error = 'Please fill in all required fields';
      return;
    }
    if (!this.newMedicalRecord.doctorId) {
      this.newMedicalRecord.doctorId = this.doctorId || '';
    }
    try {
      this.loading = true;
      const recordId = (this.newMedicalRecord as any).recordId;
      if (recordId) {
        await this.medicalRecordService.updateMedicalRecord(recordId, this.newMedicalRecord);
      } else {
        await this.medicalRecordService.createMedicalRecord(this.newMedicalRecord);
      }
      this.showCreateMedicalRecord = false;
      this.newMedicalRecord = {
        patientId: '',
        doctorId: this.doctorId || '',
        recordType: 'NOTE',
        title: '',
        content: '',
        diagnosisCode: ''
      };
      delete (this.newMedicalRecord as any).recordId;
      await Promise.all([
        this.localSelectedPatientId ? this.loadPatientMedicalRecords() : Promise.resolve(),
        this.loadAllDoctorRecords()
      ]);
      this.dataChanged.emit();
    } 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);
    } finally {
      this.loading = false;
    }
  }

  editMedicalRecord(record: MedicalRecord) {
    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;
    (this.newMedicalRecord as any).recordId = record.id;
  }

  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 {
      this.loading = true;
      await this.medicalRecordService.deleteMedicalRecord(recordId);
      if (this.showAllRecords) {
        await this.loadAllDoctorRecords();
      } else if (this.localSelectedPatientId) {
        await this.loadPatientMedicalRecords();
      }
      this.dataChanged.emit();
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to delete medical record';
    } finally {
      this.loading = false;
    }
  }

  // Vital Signs Methods
  openCreateVitalSigns() {
    this.showCreateVitalSigns = !this.showCreateVitalSigns;
    if (this.showCreateVitalSigns) {
      this.newVitalSigns = {
        patientId: this.localSelectedPatientId || '',
        temperature: undefined,
        bloodPressureSystolic: undefined,
        bloodPressureDiastolic: undefined,
        heartRate: undefined,
        respiratoryRate: undefined,
        oxygenSaturation: undefined,
        weight: undefined,
        height: undefined,
        notes: ''
      };
    }
  }

  async createVitalSigns() {
    if (!this.newVitalSigns.patientId) {
      this.error = 'Please select a patient';
      return;
    }
    try {
      this.loading = true;
      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: ''
      };
      if (this.localSelectedPatientId) {
        await this.loadPatientVitalSigns();
      }
      this.dataChanged.emit();
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to create vital signs';
    } finally {
      this.loading = false;
    }
  }

  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 {
      this.loading = true;
      await this.medicalRecordService.deleteVitalSigns(vitalSignsId);
      if (this.localSelectedPatientId) {
        await this.loadPatientVitalSigns();
      }
      this.dataChanged.emit();
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to delete vital signs';
    } finally {
      this.loading = false;
    }
  }

  // Lab Results Methods
  openCreateLabResult() {
    this.showCreateLabResult = !this.showCreateLabResult;
    this.showUpdateLabResult = false;
    if (this.showCreateLabResult) {
      this.newLabResult = {
        patientId: undefined as any,
        doctorId: this.doctorId || '',
        testName: '',
        resultValue: '',
        status: 'PENDING',
        orderedDate: new Date().toISOString().split('T')[0]
      };
      if (this.localSelectedPatientId) {
        this.newLabResult.patientId = this.localSelectedPatientId as any;
      }
      delete (this.newLabResult as any).labResultId;
    }
  }

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

    // 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 {
      this.loading = true;
      const labResultId = (this.newLabResult as any).labResultId;
      if (labResultId) {
        await this.medicalRecordService.updateLabResult(labResultId, this.newLabResult);
      } else {
        await this.medicalRecordService.createLabResult(this.newLabResult);
      }
      this.showCreateLabResult = false;
      this.showUpdateLabResult = false;
      this.newLabResult = {
        patientId: undefined as any,
        doctorId: this.doctorId || '',
        testName: '',
        resultValue: '',
        status: 'PENDING',
        orderedDate: new Date().toISOString().split('T')[0]
      };
      delete (this.newLabResult as any).labResultId;
      if (this.localSelectedPatientId) {
        await this.loadPatientLabResults();
      }
      this.dataChanged.emit();
    } catch (e: any) {
      this.logger.error('[CreateLabResult] Error:', e);
      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?.message) {
        errorMsg = e.message;
      }
      this.error = errorMsg;
    } finally {
      this.loading = false;
    }
  }

  editLabResult(labResult: any) {
    this.selectedLabResult = labResult;
    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;
    this.showUpdateLabResult = true;
    (this.newLabResult as any).labResultId = labResult.id;
  }

  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 {
      this.loading = true;
      await this.medicalRecordService.deleteLabResult(labResultId);
      if (this.localSelectedPatientId) {
        await this.loadPatientLabResults();
      }
      this.dataChanged.emit();
    } catch (e: any) {
      this.error = e?.response?.data?.error || 'Failed to delete lab result';
    } finally {
      this.loading = false;
    }
  }

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

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

  getCurrentRecords() {
    return this.showAllRecords ? this.allMedicalRecords : this.medicalRecords;
  }

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

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

  cancelMedicalRecordForm() {
    this.showCreateMedicalRecord = false;
    delete (this.newMedicalRecord as any).recordId;
  }

  cancelLabResultForm() {
    this.showCreateLabResult = false;
    this.showUpdateLabResult = false;
    delete (this.newLabResult as any).labResultId;
  }

  async viewPatientProfile(patientId: string) {
    try {
      this.selectedPatientProfile = await this.userService.getPatientProfileById(patientId);
      this.showPatientProfileModal = true;
    } catch (e: any) {
      this.error = e?.message || 'Failed to load patient profile';
      this.logger.error('Failed to load patient profile:', e);
    }
  }

  closePatientProfileModal() {
    this.showPatientProfileModal = false;
    this.selectedPatientProfile = null;
  }

  filterPatients() {
    if (!this.patientSearchQuery || this.patientSearchQuery.trim() === '') {
      this.filteredPatients = this.patients || [];
      return;
    }

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

  onPatientSearchChange() {
    this.filterPatients();
  }

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