import { Injectable } from '@angular/core';
import axios from 'axios';
import { LoggerService } from './logger.service';

import { BASE_URL } from '../config/api.config';

function authHeaders() {
  const token = localStorage.getItem('jwtToken');
  return { Authorization: `Bearer ${token}` };
}

export interface MedicalRecord {
  id: string;
  patientId: string;
  patientName?: string;
  doctorId: string;
  doctorName?: string;
  appointmentId?: string;
  recordType: 'DIAGNOSIS' | 'LAB_RESULT' | 'IMAGING' | 'VITAL_SIGNS' | 'NOTE' | 'PROCEDURE' | 'TREATMENT_PLAN' | 'OTHER';
  title: string;
  content: string;
  diagnosisCode?: string;
  createdAt: string;
}

export interface MedicalRecordRequest {
  patientId: string;
  doctorId: string;
  appointmentId?: string;
  recordType: 'DIAGNOSIS' | 'LAB_RESULT' | 'IMAGING' | 'VITAL_SIGNS' | 'NOTE' | 'PROCEDURE' | 'TREATMENT_PLAN' | 'OTHER';
  title: string;
  content: string;
  diagnosisCode?: string;
}

export interface VitalSigns {
  id: string;
  patientId: string;
  patientName?: string;
  doctorId?: string;
  doctorName?: string;
  temperature?: number;
  bloodPressureSystolic?: number;
  bloodPressureDiastolic?: number;
  heartRate?: number;
  respiratoryRate?: number;
  oxygenSaturation?: number;
  weight?: number; // maps from backend weightKg
  height?: number; // maps from backend heightCm
  bmi?: number;
  notes?: string;
  recordedAt: string;
}

export interface VitalSignsRequest {
  patientId: string;
  doctorId?: string;
  appointmentId?: string;
  temperature?: number;
  bloodPressureSystolic?: number;
  bloodPressureDiastolic?: number;
  heartRate?: number;
  respiratoryRate?: number;
  oxygenSaturation?: number;
  weight?: number; // will be sent as weightKg
  height?: number; // will be sent as heightCm
  notes?: string;
}

export interface LabResult {
  id: string;
  patientId: string;
  patientName?: string;
  doctorId?: string;
  doctorName?: string;
  medicalRecordId?: string;
  testName: string;
  resultValue: string;
  referenceRange?: string;
  unit?: string;
  status: 'NORMAL' | 'ABNORMAL' | 'CRITICAL' | 'PENDING';
  orderedDate: string; // maps from backend performedAt
  resultDate?: string; // not provided by backend; reserved for UI
  notes?: string; // not provided by backend; reserved for UI
  resultFileUrl?: string;
}

export interface LabResultRequest {
  patientId: string;
  doctorId?: string;
  medicalRecordId?: string;
  testName: string;
  resultValue: string;
  referenceRange?: string;
  unit?: string;
  status: 'NORMAL' | 'ABNORMAL' | 'CRITICAL' | 'PENDING';
  orderedDate: string; // will be sent as performedAt
  resultDate?: string;
  notes?: string;
}

@Injectable({ providedIn: 'root' })
export class MedicalRecordService {
  constructor(private logger: LoggerService) {}
  // Medical Records
  async getMedicalRecordsByPatientId(patientId: string): Promise<MedicalRecord[]> {
    try {
      const res = await axios.get(`${BASE_URL}/api/v3/medical-records/patient/${patientId}`, { headers: authHeaders() });
      return res.data;
    } catch (error: any) {
      if (error?.response?.status === 403) {
        throw new Error('Access denied: You can only view records for your own patients');
      }
      throw error;
    }
  }

  async getMedicalRecordsByDoctorId(doctorId: string): Promise<MedicalRecord[]> {
    try {
      const res = await axios.get(`${BASE_URL}/api/v3/medical-records/doctor/${doctorId}`, { headers: authHeaders() });
      return res.data;
    } catch (error: any) {
      if (error?.response?.status === 403) {
        throw new Error('Access denied: You can only view your own records');
      }
      throw error;
    }
  }

  async getMedicalRecordsByPatientIdAndType(patientId: string, recordType: MedicalRecord['recordType']): Promise<MedicalRecord[]> {
    try {
      const res = await axios.get(`${BASE_URL}/api/v3/medical-records/patient/${patientId}/type/${recordType}`, { headers: authHeaders() });
      return res.data;
    } catch (error: any) {
      if (error?.response?.status === 403) {
        throw new Error('Access denied: You can only view records for your own patients');
      }
      throw error;
    }
  }

  async getMedicalRecordsByAppointmentId(appointmentId: string): Promise<MedicalRecord[]> {
    try {
      const res = await axios.get(`${BASE_URL}/api/v3/medical-records/appointment/${appointmentId}`, { headers: authHeaders() });
      return res.data;
    } catch (error: any) {
      if (error?.response?.status === 403) {
        throw new Error('Access denied: You can only view records for your own appointments');
      }
      throw error;
    }
  }

  async getMedicalRecordById(id: string): Promise<MedicalRecord> {
    try {
      const res = await axios.get(`${BASE_URL}/api/v3/medical-records/${id}`, { headers: authHeaders() });
      return res.data;
    } catch (error: any) {
      if (error?.response?.status === 403) {
        throw new Error('Access denied: You can only view records for your own patients');
      }
      throw error;
    }
  }

  async createMedicalRecord(request: MedicalRecordRequest): Promise<MedicalRecord> {
    try {
      const res = await axios.post(`${BASE_URL}/api/v3/medical-records`, request, { headers: authHeaders() });
      return res.data;
    } catch (error: any) {
      if (error?.response?.status === 403) {
        throw new Error('Access denied: You can only create records for yourself');
      }
      if (error?.response?.status === 400 && error?.response?.data?.message) {
        throw new Error(error.response.data.message);
      }
      throw error;
    }
  }

  async updateMedicalRecord(id: string, request: MedicalRecordRequest): Promise<MedicalRecord> {
    try {
      const res = await axios.put(`${BASE_URL}/api/v3/medical-records/${id}`, request, { headers: authHeaders() });
      return res.data;
    } catch (error: any) {
      if (error?.response?.status === 403) {
        throw new Error('Access denied: You can only update records for your own patients');
      }
      if (error?.response?.status === 400 && error?.response?.data?.message) {
        throw new Error(error.response.data.message);
      }
      throw error;
    }
  }

  async deleteMedicalRecord(id: string): Promise<void> {
    try {
      await axios.delete(`${BASE_URL}/api/v3/medical-records/${id}`, { headers: authHeaders() });
    } catch (error: any) {
      if (error?.response?.status === 403) {
        throw new Error('Access denied: You can only delete records for your own patients');
      }
      throw error;
    }
  }

  // Vital Signs
  async getVitalSignsByPatientId(patientId: string): Promise<VitalSigns[]> {
    const res = await axios.get(`${BASE_URL}/api/v3/vital-signs/patient/${patientId}`, { headers: authHeaders() });
    return (res.data || []).map((vs: any) => ({
      ...vs,
      weight: vs?.weightKg ?? vs?.weight,
      height: vs?.heightCm ?? vs?.height
    }));
  }

  async getLatestVitalSignsByPatientId(patientId: string): Promise<VitalSigns | null> {
    try {
      const res = await axios.get(`${BASE_URL}/api/v3/vital-signs/patient/${patientId}/latest`, { headers: authHeaders() });
      const vs = res.data;
      if (!vs) return null;
      return {
        ...vs,
        weight: vs?.weightKg ?? vs?.weight,
        height: vs?.heightCm ?? vs?.height
      };
    } catch (error: any) {
      // Return null for 404 (not found) or 400 (no vital signs) - both are acceptable
      if (error?.response?.status === 404 || error?.response?.status === 400) {
        return null;
      }
      throw error;
    }
  }

  async createVitalSigns(request: VitalSignsRequest): Promise<VitalSigns> {
    const payload: any = {
      patientId: request.patientId,
      appointmentId: request.appointmentId,
      temperature: request.temperature,
      bloodPressureSystolic: request.bloodPressureSystolic,
      bloodPressureDiastolic: request.bloodPressureDiastolic,
      heartRate: request.heartRate,
      respiratoryRate: request.respiratoryRate,
      oxygenSaturation: request.oxygenSaturation,
      weightKg: request.weight,
      heightCm: request.height,
      notes: request.notes
    };
    const res = await axios.post(`${BASE_URL}/api/v3/vital-signs`, payload, { headers: authHeaders() });
    const vs = res.data;
    return { ...vs, weight: vs?.weightKg ?? vs?.weight, height: vs?.heightCm ?? vs?.height };
  }

  async deleteVitalSigns(id: string): Promise<void> {
    await axios.delete(`${BASE_URL}/api/v3/vital-signs/${id}`, { headers: authHeaders() });
  }

  // Lab Results
  async getLabResultsByPatientId(patientId: string): Promise<LabResult[]> {
    const res = await axios.get(`${BASE_URL}/api/v3/lab-results/patient/${patientId}`, { headers: authHeaders() });
    return (res.data || []).map((lr: any) => ({
      ...lr,
      orderedDate: lr?.performedAt ?? lr?.orderedDate
    }));
  }

  async getLabResultById(id: string): Promise<LabResult> {
    const res = await axios.get(`${BASE_URL}/api/v3/lab-results/${id}`, { headers: authHeaders() });
    return res.data;
  }

  async createLabResult(request: LabResultRequest): Promise<LabResult> {
    // Validate required fields
    if (!request.patientId || (typeof request.patientId === 'string' && request.patientId.trim() === '')) {
      throw new Error('Patient ID is required');
    }
    if (!request.testName || (typeof request.testName === 'string' && request.testName.trim() === '')) {
      throw new Error('Test name is required');
    }
    if (!request.resultValue || (typeof request.resultValue === 'string' && request.resultValue.trim() === '')) {
      throw new Error('Result value is required');
    }
    
    // Validate UUID format for patientId
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
    if (typeof request.patientId === 'string' && !uuidRegex.test(request.patientId)) {
      throw new Error('Patient ID must be a valid UUID');
    }
    
    const performedAtIso = request.orderedDate ? new Date(`${request.orderedDate}T00:00:00Z`).toISOString() : undefined;
    // Build payload with ONLY fields that exist in LabResultRequestDto
    const payload: any = {
      patientId: request.patientId,
      testName: request.testName,
      resultValue: request.resultValue || null,
      status: (request.status?.toUpperCase() || 'PENDING') as 'PENDING' | 'NORMAL' | 'ABNORMAL' | 'CRITICAL'
    };
    // Add optional fields only if they have values
    if (request.medicalRecordId) payload.medicalRecordId = request.medicalRecordId;
    if (request.unit) payload.unit = request.unit;
    if (request.referenceRange) payload.referenceRange = request.referenceRange;
    if (performedAtIso) payload.performedAt = performedAtIso;
    
    this.logger.debug('[MedicalRecordService] Sending lab result payload:', JSON.stringify(payload, null, 2));
    
    try {
      const res = await axios.post(`${BASE_URL}/api/v3/lab-results`, payload, { headers: authHeaders() });
      const lr = res.data;
      return { ...lr, orderedDate: lr?.performedAt ? new Date(lr.performedAt).toISOString().split('T')[0] : lr?.orderedDate };
    } catch (error: any) {
      this.logger.error('[MedicalRecordService] Lab result creation failed:', error?.response?.data || error);
      throw error;
    }
  }

  async updateLabResult(id: string, request: LabResultRequest): Promise<LabResult> {
    const performedAtIso = request.orderedDate ? new Date(`${request.orderedDate}T00:00:00Z`).toISOString() : undefined;
    const payload: any = {
      patientId: request.patientId,
      testName: request.testName,
      resultValue: request.resultValue,
      status: request.status?.toUpperCase() || 'PENDING'
    };
    // Add optional fields only if they have values
    if (request.medicalRecordId) payload.medicalRecordId = request.medicalRecordId;
    if (request.unit) payload.unit = request.unit;
    if (request.referenceRange) payload.referenceRange = request.referenceRange;
    if (performedAtIso) payload.performedAt = performedAtIso;
    const res = await axios.put(`${BASE_URL}/api/v3/lab-results/${id}`, payload, { headers: authHeaders() });
    const lr = res.data;
    return { ...lr, orderedDate: lr?.performedAt ?? lr?.orderedDate };
  }

  async deleteLabResult(id: string): Promise<void> {
    await axios.delete(`${BASE_URL}/api/v3/lab-results/${id}`, { headers: authHeaders() });
  }
}

