import { fetchEncounter, fetchObservations } from '@/api/encounters'
import { fetchAlerts } from '@/api/alerts'
import { fetchOrders, fetchSepsisBundle } from '@/api/clinical'
import { alertTypeLabel, bundleElementLabel } from '@/api/normalize'
import { formatAllergiesDisplay } from '@/composables/patientFormat'
import { formatDepartment, complianceStatusLabel, outstandingElements } from '@/composables/sepsisFormat'

const VITAL_CODES = ['HEART_RATE', 'RESP_RATE', 'SYSTOLIC_BP', 'DIASTOLIC_BP', 'SPO2', 'TEMP_C']

export function extractLatestVitals(observations) {
  const map = {}
  for (const obs of observations ?? []) {
    if (!VITAL_CODES.includes(obs.observationCode)) continue
    const existing = map[obs.observationCode]
    if (!existing || new Date(obs.recordedAt) > new Date(existing.recordedAt)) {
      map[obs.observationCode] = obs
    }
  }
  return map
}

export function formatVitalsSummary(vitals) {
  const parts = []
  if (vitals.HEART_RATE) parts.push(`HR ${vitals.HEART_RATE.value} bpm`)
  if (vitals.RESP_RATE) parts.push(`RR ${vitals.RESP_RATE.value}/min`)
  if (vitals.SYSTOLIC_BP && vitals.DIASTOLIC_BP) {
    parts.push(`BP ${vitals.SYSTOLIC_BP.value}/${vitals.DIASTOLIC_BP.value} mmHg`)
  } else if (vitals.SYSTOLIC_BP) {
    parts.push(`BP ${vitals.SYSTOLIC_BP.value} mmHg`)
  }
  if (vitals.SPO2) parts.push(`SpO₂ ${vitals.SPO2.value}%`)
  if (vitals.TEMP_C) parts.push(`Temp ${vitals.TEMP_C.value}°C`)
  return parts.join(' · ') || 'No recent vitals'
}

export function formatAlertsSummary(alerts) {
  if (!alerts?.length) return 'No open alerts'
  return alerts.map(alert => alertTypeLabel(alert.alertType)).join('; ')
}

export function formatPendingOrdersSummary(orders) {
  if (!orders?.length) return ''
  return orders.map(order => order.description).join('; ')
}

export function buildWardSummary(encounters, department) {
  const activeBundles = encounters.filter(
    patient =>
      patient.sepsisActive
      || patient.sepsisBundleStatus === 'IN_PROGRESS'
      || patient.sepsisBundleStatus === 'InProgress',
  ).length

  return {
    department: department ? formatDepartment(department) : 'All departments',
    patientCount: encounters.length,
    criticalCount: encounters.filter(patient => (patient.news2Score ?? 0) >= 7).length,
    alertCount: encounters.reduce((sum, patient) => sum + (patient.openAlertCount ?? 0), 0),
    activeBundles,
  }
}

export function buildSbar(wardPatient, encounter, enrichment) {
  const patient = encounter?.patient ?? {}
  const scores = [
    wardPatient.news2Score != null ? `NEWS2 ${wardPatient.news2Score}` : null,
    wardPatient.sofaScore != null
      ? `SOFA ${wardPatient.sofaScore}${wardPatient.sofaDelta ? ` (Δ+${wardPatient.sofaDelta})` : ''}`
      : null,
    wardPatient.gcsScore != null ? `GCS ${wardPatient.gcsScore}` : null,
    `qSOFA ${wardPatient.qsofaScore ?? 0}`,
  ].filter(Boolean).join(', ')

  const assessmentParts = [scores]
  const vitals = formatVitalsSummary(enrichment.vitals)
  if (vitals !== 'No recent vitals') assessmentParts.push(vitals)
  const alerts = formatAlertsSummary(enrichment.openAlerts)
  if (alerts !== 'No open alerts') assessmentParts.push(alerts)

  let recommendation = formatPendingOrdersSummary(enrichment.pendingOrders)
  const bundle = enrichment.bundle
  if (bundle) {
    const outstanding = outstandingElements(bundle)
      .map(element => bundleElementLabel(element.elementType))
      .join(', ')
    const bundleNote = `Sepsis bundle: ${complianceStatusLabel(bundle.complianceStatus)}${
      outstanding ? ` — outstanding: ${outstanding}` : ''
    }`
    recommendation = recommendation ? `${recommendation}; ${bundleNote}` : bundleNote
  }
  if (enrichment.openAlerts?.length) {
    const alertNote = `${enrichment.openAlerts.length} open alert(s) require attention`
    recommendation = recommendation ? `${recommendation}; ${alertNote}` : alertNote
  }

  return {
    situation: encounter?.admissionReason ?? 'Admission reason not documented',
    background: `Allergies: ${formatAllergiesDisplay(patient.allergies)}`,
    assessment: assessmentParts.join('. '),
    recommendation: recommendation || 'No pending actions documented',
  }
}

export function buildPatientReport(wardPatient, enrichment) {
  return {
    encounterId: wardPatient.encounterId,
    name: `${wardPatient.firstName} ${wardPatient.lastName}`.trim(),
    mrn: wardPatient.mrn,
    room: wardPatient.roomBed ?? '—',
    department: formatDepartment(wardPatient.department),
    attending: wardPatient.attendingPhysician ?? '—',
    news2: wardPatient.news2Score,
    sofa: wardPatient.sofaScore,
    sofaDelta: wardPatient.sofaDelta,
    gcs: wardPatient.gcsScore,
    qsofa: wardPatient.qsofaScore,
    alertsSummary: formatAlertsSummary(enrichment.openAlerts),
    pendingOrders: formatPendingOrdersSummary(enrichment.pendingOrders) || 'None',
    vitalsSummary: formatVitalsSummary(enrichment.vitals),
    sbar: buildSbar(wardPatient, enrichment.encounter, enrichment),
  }
}

export async function loadHandoffEnrichment(encounters) {
  const entries = await Promise.all(
    encounters.map(async wardPatient => {
      const id = wardPatient.encounterId
      const [enc, alertsData, ordersData, observations, bundle] = await Promise.all([
        fetchEncounter(id).catch(() => null),
        fetchAlerts(id, 'OPEN').catch(() => ({ items: [] })),
        fetchOrders(id).catch(() => ({ items: [] })),
        fetchObservations(id, { limit: 50 }).catch(() => []),
        fetchSepsisBundle(id).catch(() => null),
      ])
      const orders = ordersData.items ?? ordersData ?? []
      return [
        id,
        {
          encounter: enc,
          openAlerts: alertsData.items ?? [],
          pendingOrders: orders.filter(
            order => order.status === 'Pending' || order.status === 'InProgress',
          ),
          vitals: extractLatestVitals(observations),
          bundle,
        },
      ]
    }),
  )
  return Object.fromEntries(entries)
}

export async function buildHandoffReport(encounters, department, generatedBy) {
  const enrichment = await loadHandoffEnrichment(encounters)
  return {
    generatedAt: new Date().toISOString(),
    generatedBy,
    summary: buildWardSummary(encounters, department),
    patients: encounters.map(patient =>
      buildPatientReport(patient, enrichment[patient.encounterId]),
    ),
  }
}

export function formatReportTimestamp(iso) {
  if (!iso) return ''
  return new Date(iso).toLocaleString([], {
    year: 'numeric',
    month: 'short',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
  })
}
