<template>
  <div class="h-full min-h-0 flex flex-col">
    <AppHeader
      title="Live Capture"
      description="Bedside observation recording — lighter than backfill digitization."
    />

    <div class="flex-1 overflow-y-auto p-4 sm:p-6 lg:p-8">
      <div class="max-w-5xl mx-auto space-y-6">
        <!-- Mode selector -->
        <div class="flex border-b border-line" role="tablist">
          <button
            type="button"
            role="tab"
            :aria-selected="mode === 'new'"
            @click="mode = 'new'"
            class="px-5 py-3 text-sm font-semibold border-b-2 -mb-px transition-colors"
            :class="mode === 'new'
              ? 'border-primary-600 text-primary-700'
              : 'border-transparent text-ink-secondary hover:text-ink-strong'"
          >
            New Encounter
          </button>
          <button
            type="button"
            role="tab"
            :aria-selected="mode === 'existing'"
            @click="mode = 'existing'"
            class="px-5 py-3 text-sm font-semibold border-b-2 -mb-px transition-colors"
            :class="mode === 'existing'
              ? 'border-primary-600 text-primary-700'
              : 'border-transparent text-ink-secondary hover:text-ink-strong'"
          >
            Existing Encounter
          </button>
        </div>

        <!-- 1. Patient -->
        <section v-if="mode === 'new'" class="card space-y-4">
          <header>
            <p class="workstation-form-legend">1 · Patient</p>
            <h2 class="text-base font-semibold text-ink-strong mt-1">Select patient</h2>
          </header>
          <PatientSearch v-model="patientId" />
        </section>

        <!-- 2. Encounter -->
        <section class="card space-y-4">
          <header>
            <p class="workstation-form-legend">{{ mode === 'new' ? '2' : '1' }} · Encounter</p>
            <h2 class="text-base font-semibold text-ink-strong mt-1">
              {{ mode === 'new' ? 'Encounter details' : 'Existing encounter' }}
            </h2>
          </header>

          <div v-if="mode === 'new'" class="grid grid-cols-1 sm:grid-cols-2 gap-4">
            <div>
              <label for="lc-department" class="block text-sm font-semibold text-ink mb-2">
                Department
              </label>
              <select id="lc-department" v-model="department" class="form-input">
                <option value="">Select department...</option>
                <option v-for="dept in departments" :key="dept.value" :value="dept.value">
                  {{ dept.label }}
                </option>
              </select>
            </div>
            <div>
              <label for="lc-room" class="block text-sm font-semibold text-ink mb-2">
                Room / Bed
              </label>
              <input
                id="lc-room"
                v-model="roomBed"
                type="text"
                class="form-input"
                placeholder="e.g. 4B-12"
              />
            </div>
            <div class="sm:col-span-2">
              <label for="lc-reason" class="block text-sm font-semibold text-ink mb-2">
                Admission Reason
              </label>
              <input
                id="lc-reason"
                v-model="admissionReason"
                type="text"
                class="form-input"
                placeholder="Chief complaint or reason"
              />
            </div>
          </div>

          <div v-else>
            <label for="lc-encounter" class="block text-sm font-semibold text-ink mb-2">
              Encounter ID
            </label>
            <input
              id="lc-encounter"
              v-model="encounterId"
              type="text"
              class="form-input font-mono"
              placeholder="Enter existing encounter UUID"
            />
          </div>
        </section>

        <!-- 3. Observations -->
        <section class="card space-y-4">
          <header class="flex flex-wrap items-end justify-between gap-3">
            <div>
              <p class="workstation-form-legend">
                {{ mode === 'new' ? '3' : '2' }} · Observations
              </p>
              <h2 class="text-base font-semibold text-ink-strong mt-1">
                Vitals ({{ observations.length }}/10)
              </h2>
            </div>
            <button
              type="button"
              class="text-sm font-semibold text-primary-700 hover:text-primary-800 disabled:opacity-50"
              :disabled="observations.length >= 10"
              @click="addObservation"
            >
              + Add Observation
            </button>
          </header>

          <div class="space-y-3">
            <ObservationRow
              v-for="obs in observations"
              :key="obs.id"
              :observation="obs"
              :can-delete="observations.length > 1"
              @update="(field, value) => handleObsUpdate(obs.id, field, value)"
              @delete="removeObservationById"
            />
          </div>
          <p v-if="observations.length >= 10" class="text-xs text-ink-disabled">
            Maximum 10 observations per submission.
          </p>
        </section>

        <!-- 4. Attestation -->
        <section class="card space-y-4">
          <header>
            <p class="workstation-form-legend">
              {{ mode === 'new' ? '4' : '3' }} · Attestation
            </p>
            <h2 class="text-base font-semibold text-ink-strong mt-1">
              Clinician attestation
            </h2>
          </header>

          <label class="flex items-start gap-3 cursor-pointer">
            <input
              v-model="clinicianAttestation"
              type="checkbox"
              class="w-5 h-5 mt-0.5 rounded-input border-line-strong text-clinical-safe focus:ring-primary-500"
            />
            <span class="text-sm text-ink">
              I attest that I have directly observed or performed these measurements and they are
              accurate to the best of my clinical judgment.
            </span>
          </label>

          <div class="pt-2 border-t border-line">
            <label for="lc-password" class="block text-sm font-semibold text-ink mb-2">
              Password confirmation
            </label>
            <p class="text-xs text-ink-secondary mb-2">
              Re-enter your password to confirm this clinical attestation.
            </p>
            <input
              id="lc-password"
              v-model="passwordConfirm"
              type="password"
              class="form-input max-w-sm"
              placeholder="Current password"
              autocomplete="current-password"
            />
          </div>
        </section>

        <!-- 5. Submit -->
        <section class="space-y-4">
          <div class="flex flex-col sm:flex-row sm:items-center gap-3">
            <button
              type="button"
              class="btn-primary text-base px-8 py-3"
              :disabled="!canSubmit || store.loading"
              @click="submit"
            >
              {{ store.loading ? 'Submitting...' : 'Record Vitals' }}
            </button>
            <button
              v-if="lastResult"
              type="button"
              class="text-sm font-medium text-ink-secondary hover:text-ink-strong"
              @click="resetForm"
            >
              Record More Vitals
            </button>
          </div>

          <InlineError
            v-if="errorMessage"
            title="Submission failed"
            :message="errorMessage"
            preserved="Your observation rows and attestation were kept."
            retry-label="Try again"
            @retry="submit"
          />

          <!-- API-backed outcome only -->
          <div v-if="lastResult" class="promotion-outcome space-y-3">
            <p class="font-semibold text-clinical-safe">
              Vitals recorded and promoted successfully
            </p>
            <dl class="grid grid-cols-1 sm:grid-cols-2 gap-2 text-sm text-ink">
              <div>
                <dt class="text-ink-secondary">Batch</dt>
                <dd class="font-mono">{{ lastResult.batchId.substring(0, 8) }}…</dd>
              </div>
              <div>
                <dt class="text-ink-secondary">Encounter</dt>
                <dd class="font-mono">{{ lastResult.encounterId.substring(0, 8) }}…</dd>
              </div>
              <div>
                <dt class="text-ink-secondary">Observations promoted</dt>
                <dd>{{ lastResult.observations.length }}</dd>
              </div>
              <div>
                <dt class="text-ink-secondary">Promoted at</dt>
                <dd>{{ new Date(lastResult.promotedAt).toLocaleString() }}</dd>
              </div>
            </dl>
          </div>

          <div
            v-if="lastResult && lastResult.criticalAlertCount > 0"
            class="clinical-signal clinical-signal--critical"
            role="alert"
          >
            <p class="font-semibold text-clinical-critical">
              Critical alerts ({{ lastResult.criticalAlertCount }})
            </p>
            <div class="mt-3 space-y-2">
              <div
                v-for="obs in lastResult.observations.filter(o => o.criticalAlert)"
                :key="obs.liveObservationId"
                class="rounded-input border border-[#FECDCA] bg-surface p-3"
              >
                <p class="font-medium text-clinical-danger">
                  {{ formatCode(obs.observationCode) }}: {{ obs.value }} {{ obs.unit }}
                </p>
                <p class="text-sm text-ink mt-1">{{ obs.criticalAlert!.message }}</p>
                <p class="text-xs text-ink-secondary mt-1">
                  Severity: {{ obs.criticalAlert!.severity }}
                  · Threshold ({{ obs.criticalAlert!.thresholdBound.replace('_', ' ') }}):
                  {{ obs.criticalAlert!.thresholdValue }}
                </p>
              </div>
            </div>
          </div>
        </section>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue'
import { useLiveCaptureStore } from '../stores/liveCapture'
import { useToast } from '../composables/useToast'
import AppHeader from '../components/AppHeader.vue'
import PatientSearch from '../components/PatientSearch.vue'
import InlineError from '../components/InlineError.vue'
import ObservationRow from '../components/ObservationRow.vue'
import type { ObservationRowModel } from '../components/ObservationRow.vue'
import type { LiveCaptureObservationInput } from '../types'

const store = useLiveCaptureStore()
const toast = useToast()

const mode = ref<'new' | 'existing'>('new')
const patientId = ref<string | undefined>()
const department = ref('')
const roomBed = ref('')
const admissionReason = ref('')
const encounterId = ref('')
const clinicianAttestation = ref(false)
const passwordConfirm = ref('')
const errorMessage = ref('')

const lastResult = computed(() => store.lastResult)

const departments = [
  { value: 'Emergency Department', label: 'Emergency Department' },
  { value: 'Internal Medicine', label: 'Internal Medicine' },
  { value: 'General Medicine', label: 'General Medicine' },
  { value: 'Surgery', label: 'Surgery' },
  { value: 'ICU', label: 'ICU' },
  { value: 'NICU', label: 'NICU' },
  { value: 'Medical-Surgical', label: 'Medical-Surgical' },
  { value: 'Outpatient Clinic', label: 'Outpatient Clinic' },
  { value: 'Pediatrics', label: 'Pediatrics' },
  { value: 'Obstetrics & Gynecology', label: 'Obstetrics & Gynecology' },
  { value: 'Labor & Delivery', label: 'Labor & Delivery' },
  { value: 'Cardiology', label: 'Cardiology' },
  { value: 'Orthopedics', label: 'Orthopedics' },
  { value: 'Neurology', label: 'Neurology' },
  { value: 'Oncology', label: 'Oncology' },
  { value: 'Radiology', label: 'Radiology' },
  { value: 'Laboratory', label: 'Laboratory' },
  { value: 'Psychiatry', label: 'Psychiatry' },
  { value: 'Physical Therapy', label: 'Physical Therapy' },
  { value: 'Anesthesiology', label: 'Anesthesiology' },
]

function nowLocal(): string {
  const d = new Date()
  d.setMinutes(d.getMinutes() - d.getTimezoneOffset())
  return d.toISOString().slice(0, 16)
}

function makeObservation(): ObservationRowModel {
  return {
    id: crypto.randomUUID(),
    observationCode: '',
    value: null,
    unit: '',
    recordedAt: nowLocal(),
    note: '',
  }
}

const observations = ref<ObservationRowModel[]>([makeObservation()])

function addObservation() {
  if (observations.value.length < 10) {
    observations.value.push(makeObservation())
  }
}

function removeObservationById(id: string) {
  if (observations.value.length <= 1) return
  observations.value = observations.value.filter((o) => o.id !== id)
}

function handleObsUpdate(id: string, field: string, value: unknown) {
  const obs = observations.value.find((o) => o.id === id)
  if (!obs) return
  ;(obs as Record<string, unknown>)[field] = value
}

function toSubmitPayload(): LiveCaptureObservationInput[] {
  return observations.value.map(({ observationCode, value, unit, recordedAt, note }) => ({
    observationCode,
    value,
    unit: unit ?? '',
    recordedAt: new Date(recordedAt ?? nowLocal()).toISOString(),
    note: note ?? '',
  }))
}

function formatCode(code: string): string {
  return code.replace(/_/g, ' ')
}

const canSubmit = computed(() => {
  const hasValidObs = observations.value.every(
    o => o.observationCode && o.value !== null && o.unit && o.recordedAt,
  )
  if (!hasValidObs || !clinicianAttestation.value || !passwordConfirm.value) return false

  if (mode.value === 'new') {
    return !!patientId.value && !!department.value && !!admissionReason.value
  }
  return !!encounterId.value.trim()
})

async function submit() {
  errorMessage.value = ''
  store.reset()

  const obs = toSubmitPayload()

  try {
    if (mode.value === 'new') {
      await store.openEncounterWithVitals(
        patientId.value!,
        department.value,
        roomBed.value,
        admissionReason.value,
        obs,
        clinicianAttestation.value,
        passwordConfirm.value,
      )
    } else {
      await store.recordObservations(
        encounterId.value.trim(),
        obs,
        clinicianAttestation.value,
        passwordConfirm.value,
      )
    }
    passwordConfirm.value = ''
    const result = store.lastResult
    if (result && result.criticalAlertCount > 0) {
      toast.warning(`Vitals recorded — ${result.criticalAlertCount} CRITICAL alert(s) generated`)
    } else {
      toast.success('Vitals recorded and promoted successfully')
    }
  } catch (e: unknown) {
    const msg = e instanceof Error ? e.message : 'Submission failed'
    errorMessage.value = msg
    toast.error(msg)
  }
}

function resetForm() {
  store.reset()
  errorMessage.value = ''
  observations.value = [makeObservation()]
  clinicianAttestation.value = false
  passwordConfirm.value = ''
  if (mode.value === 'existing') {
    encounterId.value = ''
  }
}
</script>
