<script setup>
import { ref, watch, computed, onBeforeUnmount } from 'vue'
import { useRoute } from 'vue-router'
import { storeToRefs } from 'pinia'
import { usePolling } from '@/composables/usePolling'
import { useReplayControls } from '@/composables/useReplayControls'
import { useAlertStore } from '@/stores/alerts'
import { useScoringStore } from '@/stores/scoring'
import * as encountersApi from '@/api/encounters'
import * as clinicalApi from '@/api/clinical'
import VitalsPanel from '@/components/patient/VitalsPanel.vue'
import ScoresPanel from '@/components/patient/ScoresPanel.vue'
import SofaScorePanel from '@/components/patient/SofaScorePanel.vue'
import AlertsList from '@/components/patient/AlertsList.vue'
import OrdersPanel from '@/components/patient/OrdersPanel.vue'
import SepsisBundlePanel from '@/components/patient/SepsisBundlePanel.vue'
import TrendsGrid from '@/components/charts/TrendsGrid.vue'
import News2History from '@/components/charts/News2History.vue'
import ReplayControls from '@/components/replay/ReplayControls.vue'
import AlertReasoning from '@/components/alerts/AlertReasoning.vue'
import Skeleton from '@/components/ui/Skeleton.vue'

const route = useRoute()
const alertStore = useAlertStore()
const scoringStore = useScoringStore()
const { alerts } = storeToRefs(alertStore)
const { qsofa, sofa } = storeToRefs(scoringStore)
const {
  isPaused,
  speed,
  progress,
  formattedTime,
  currentMs,
  scenarioEndMs,
  scenarioStartMs,
  pause,
  resume,
  setSpeed,
  jumpToTimestamp,
  isAtOrBefore,
  setScenarioBounds,
  syncToEnd,
  stopPlayback,
} = useReplayControls()

const encounter = ref(null)
const loading = ref(true)
const observations = ref([])
const news2History = ref([])
const medications = ref([])
const sepsisBundle = ref(null)
const orders = ref([])
const selectedAlert = ref(null)
let nextAlertIndex = 0

const openAlerts = computed(() =>
  alerts.value.filter(a => a.status === 'Open' || a.status === 'Escalated'),
)

const replayObservations = computed(() =>
  observations.value.filter(o => isAtOrBefore(o.recordedAt)),
)

const replayNews2History = computed(() =>
  news2History.value.filter(h => isAtOrBefore(h.calculatedAt)),
)

function collectScenarioTimes() {
  return [
    ...observations.value.map(o => new Date(o.recordedAt).getTime()),
    ...news2History.value.map(h => new Date(h.calculatedAt).getTime()),
    ...alerts.value.map(a => new Date(a.triggeredAt).getTime()),
  ].filter(Number.isFinite)
}

function syncReplayBounds() {
  const times = collectScenarioTimes()
  if (!times.length) return

  const atEnd = currentMs.value >= scenarioEndMs.value - 1_000
  setScenarioBounds(Math.min(...times), Math.max(...times))
  if (atEnd || scenarioEndMs.value === scenarioStartMs.value) {
    syncToEnd()
  }
}

async function loadAll() {
  const id = route.params.encounterId
  loading.value = true
  try {
    const [enc, obs, history, meds, bundle, ord] = await Promise.all([
      encountersApi.fetchEncounter(id),
      encountersApi.fetchObservations(id),
      clinicalApi.fetchNews2History(id).catch(() => []),
      clinicalApi.fetchMedications(id).catch(() => []),
      clinicalApi.fetchSepsisBundle(id),
      clinicalApi.fetchOrders(id).catch(() => ({ items: [] })),
    ])
    await alertStore.loadAlerts(id)
    encounter.value = enc
    observations.value = obs
    news2History.value = history
    medications.value = meds
    sepsisBundle.value = bundle
    orders.value = ord.items ?? ord
    scoringStore.startPolling(id)
    syncReplayBounds()
  } finally {
    loading.value = false
  }
}

function onSelectAlert(alert) {
  selectedAlert.value = alert
  jumpToTimestamp(alert.triggeredAt)
}

function jumpToNextAlert() {
  const sorted = [...openAlerts.value].sort(
    (a, b) => new Date(a.triggeredAt) - new Date(b.triggeredAt),
  )
  if (!sorted.length) return

  const alert = sorted[nextAlertIndex % sorted.length]
  selectedAlert.value = alert
  nextAlertIndex++
  jumpToTimestamp(alert.triggeredAt)

  document.getElementById(`alert-row-${alert.id}`)?.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
  document.getElementById('clinical-review')?.scrollIntoView({ behavior: 'smooth', block: 'start' })
}

usePolling(loadAll, 5_000)

watch(() => route.params.encounterId, () => {
  selectedAlert.value = null
  nextAlertIndex = 0
  pause()
  scoringStore.stopPolling()
  loadAll()
})

watch(openAlerts, (list) => {
  nextAlertIndex = 0
  if (selectedAlert.value && !list.some(a => a.id === selectedAlert.value.id)) {
    selectedAlert.value = null
  }
})

watch([observations, news2History, alerts], syncReplayBounds, { deep: true })

onBeforeUnmount(() => {
  stopPlayback()
  scoringStore.stopPolling()
})
</script>

<template>
  <Skeleton v-if="loading && !encounter" :rows="6" />
  <div v-else-if="encounter" class="w-full min-w-0 space-y-8">
    <div class="flex flex-wrap items-center gap-4">
      <RouterLink to="/ward" class="text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200">
        &larr; Ward
      </RouterLink>
      <h1 class="text-xl font-bold dark:text-white">
        {{ encounter.patient?.firstName }} {{ encounter.patient?.lastName }}
      </h1>
    </div>

    <div class="grid min-w-0 gap-4 sm:grid-cols-2 lg:grid-cols-3">
      <ScoresPanel />
      <VitalsPanel :observations="replayObservations" />
      <AlertsList
        :encounter-id="route.params.encounterId"
        :selected-id="selectedAlert?.id"
        @select="onSelectAlert"
      />
    </div>

    <AlertReasoning
      v-if="selectedAlert"
      :alert="selectedAlert"
      :medications="medications"
    />

    <div class="grid min-w-0 gap-4 lg:grid-cols-2">
      <SofaScorePanel :encounter-id="route.params.encounterId" />
      <OrdersPanel :orders="orders" />
    </div>

    <SepsisBundlePanel
      :bundle="sepsisBundle"
      :qsofa="qsofa"
      :sofa="sofa"
    />

    <div id="clinical-review" class="w-full min-w-0 space-y-8">
      <TrendsGrid :observations="replayObservations" />
      <News2History v-if="replayNews2History.length" :history="replayNews2History" />
      <ReplayControls
        :alerts="openAlerts"
        :is-paused="isPaused"
        :progress="progress"
        :formatted-time="formattedTime"
        :speed="speed"
        @pause="pause()"
        @resume="resume()"
        @set-speed="setSpeed"
        @jump-to-alert="jumpToNextAlert"
      />
    </div>
  </div>
</template>