/**
 * Patient API Client
 * API functions for patient management
 */

import { getAuthHeaders } from "../context/AuthContext";

const API_BASE = import.meta.env.VITE_API_BASE || "/api";

async function patientFetch<T>(path: string, init?: RequestInit): Promise<T> {
  const url = `${API_BASE}${path}`;
  
  const response = await fetch(url, {
    ...init,
    headers: {
      "Content-Type": "application/json",
      ...getAuthHeaders(),
      ...init?.headers,
    },
  });
  
  const text = await response.text();
  
  if (!response.ok) {
    const error = text ? JSON.parse(text) : { message: "Request failed" };
    throw new Error(error.message || `Request failed: ${response.status}`);
  }
  
  return text ? JSON.parse(text) : ({} as T);
}

// ============================================
// TYPES
// ============================================

export type Patient = {
  id: number;
  mrn: string | null;
  first_name: string;
  last_name: string;
  date_of_birth: string | null;
  gender: "male" | "female" | "other" | null;
  email: string | null;
  phone: string | null;
  address: string | null;
  diagnosis: string | null;
  curve_type: string | null;
  medical_history: string | null;
  referring_physician: string | null;
  insurance_info: string | null;
  notes: string | null;
  is_active: number;
  created_by: number | null;
  created_by_username: string | null;
  created_at: string;
  updated_at: string;
  case_count?: number;
  last_visit?: string | null;
};

export type PatientCase = {
  case_id: string;
  case_type: string;
  status: string;
  current_step: string | null;
  visit_date: string | null;
  notes: string | null;
  analysis_result: any;
  landmarks_data: any;
  body_scan_path: string | null;
  body_scan_url: string | null;
  created_at: string;
  updated_at: string;
};

export type PatientInput = {
  mrn?: string;
  firstName: string;
  lastName: string;
  dateOfBirth?: string;
  gender?: "male" | "female" | "other";
  email?: string;
  phone?: string;
  address?: string;
  diagnosis?: string;
  curveType?: string;
  medicalHistory?: string;
  referringPhysician?: string;
  insuranceInfo?: string;
  notes?: string;
};

export type PatientListResponse = {
  patients: Patient[];
  total: number;
  limit: number;
  offset: number;
};

export type PatientStats = {
  total: number;
  active: number;
  inactive: number;
  withCases: number;
  byGender: Record<string, number>;
  recentPatients: number;
};

// ============================================
// API FUNCTIONS
// ============================================

/**
 * Create a new patient
 */
export async function createPatient(data: PatientInput): Promise<{ patient: Patient }> {
  return patientFetch("/patients", {
    method: "POST",
    body: JSON.stringify(data),
  });
}

/**
 * List patients with optional filters
 */
export async function listPatients(params?: {
  search?: string;
  isActive?: boolean | "all";
  limit?: number;
  offset?: number;
  sortBy?: string;
  sortOrder?: "ASC" | "DESC";
}): Promise<PatientListResponse> {
  const searchParams = new URLSearchParams();
  if (params?.search) searchParams.set("search", params.search);
  if (params?.isActive !== undefined) {
    searchParams.set("isActive", params.isActive === "all" ? "all" : String(params.isActive));
  }
  if (params?.limit) searchParams.set("limit", params.limit.toString());
  if (params?.offset) searchParams.set("offset", params.offset.toString());
  if (params?.sortBy) searchParams.set("sortBy", params.sortBy);
  if (params?.sortOrder) searchParams.set("sortOrder", params.sortOrder);
  
  const query = searchParams.toString();
  return patientFetch(`/patients${query ? `?${query}` : ""}`);
}

/**
 * Get patient by ID with their cases
 */
export async function getPatient(patientId: number): Promise<{ patient: Patient; cases: PatientCase[] }> {
  return patientFetch(`/patients/${patientId}`);
}

/**
 * Update patient
 */
export async function updatePatient(
  patientId: number,
  data: Partial<PatientInput> & { isActive?: boolean }
): Promise<{ patient: Patient }> {
  return patientFetch(`/patients/${patientId}`, {
    method: "PUT",
    body: JSON.stringify(data),
  });
}

/**
 * Archive patient (soft delete - preserves all data)
 */
export async function archivePatient(patientId: number): Promise<{ patientId: number; archived: boolean; message: string }> {
  return patientFetch(`/patients/${patientId}/archive`, {
    method: "POST",
  });
}

/**
 * Unarchive patient (restore)
 */
export async function unarchivePatient(patientId: number): Promise<{ patientId: number; archived: boolean; message: string }> {
  return patientFetch(`/patients/${patientId}/unarchive`, {
    method: "POST",
  });
}

/**
 * Delete patient - DEPRECATED: Use archivePatient instead
 * This now archives instead of deleting
 */
export async function deletePatient(patientId: number, hard = false): Promise<{ message: string }> {
  return patientFetch(`/patients/${patientId}${hard ? "?hard=true" : ""}`, {
    method: "DELETE",
  });
}

/**
 * Create a case for a patient
 */
export async function createPatientCase(
  patientId: number,
  data?: { notes?: string; visitDate?: string }
): Promise<{ caseId: string; patientId: number; status: string }> {
  return patientFetch(`/patients/${patientId}/cases`, {
    method: "POST",
    body: JSON.stringify(data || {}),
  });
}

/**
 * Get patient statistics
 */
export async function getPatientStats(): Promise<{ stats: PatientStats }> {
  return patientFetch("/patients-stats");
}

// ============================================
// UTILITY FUNCTIONS
// ============================================

/**
 * Format patient name
 */
export function formatPatientName(patient: Patient | { first_name: string; last_name: string }): string {
  return `${patient.first_name} ${patient.last_name}`;
}

/**
 * Calculate patient age from date of birth
 */
export function calculateAge(dateOfBirth: string | null): number | null {
  if (!dateOfBirth) return null;
  const today = new Date();
  const birth = new Date(dateOfBirth);
  let age = today.getFullYear() - birth.getFullYear();
  const monthDiff = today.getMonth() - birth.getMonth();
  if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
    age--;
  }
  return age;
}

/**
 * Format date for display
 */
export function formatDate(date: string | null): string {
  if (!date) return "-";
  return new Date(date).toLocaleDateString();
}
