<template>
  <details
    ref="root"
    class="mt-2 group workstation-form-section !p-3"
    data-testid="audit-trail-panel"
    @toggle="onToggle"
  >
    <summary
      class="text-sm font-medium text-primary-700 cursor-pointer hover:text-primary-800 list-none flex items-center gap-2"
    >
      <span
        class="inline-flex h-5 w-5 items-center justify-center rounded border border-line text-xs text-ink-secondary group-open:rotate-90 transition-transform"
        aria-hidden="true"
      >
        ›
      </span>
      Audit trail
      <span v-if="events.length > 0" class="text-ink-secondary font-normal">
        ({{ events.length }}{{ hasMore ? '+' : '' }} events)
      </span>
    </summary>

    <div class="mt-3">
      <p v-if="loading && events.length === 0" class="text-sm text-ink-secondary">
        Loading events…
      </p>
      <p v-else-if="error" class="text-sm text-clinical-danger" role="alert">
        {{ error }}
      </p>
      <p v-else-if="!loading && events.length === 0" class="text-sm text-ink-secondary">
        No audit events for this batch yet.
      </p>
      <ol v-else class="space-y-0" data-testid="audit-trail-timeline">
        <li
          v-for="event in events"
          :key="event.id"
          class="flex gap-3"
        >
          <div class="w-[5.5rem] shrink-0 pt-0.5 text-right">
            <time
              class="block text-[11px] leading-snug text-ink-secondary tabular-nums"
              :datetime="event.occurredAt"
            >
              {{ formatDateTime(event.occurredAt) }}
            </time>
          </div>

          <div class="observation-card__rail self-stretch" aria-hidden="true">
            <span class="observation-card__dot" />
            <span class="mt-1 w-px flex-1 bg-line" />
          </div>

          <div class="min-w-0 flex-1 pb-4">
            <p class="text-sm font-bold leading-snug text-ink-strong">
              {{ formatEventType(event.eventType) }}
            </p>
            <p class="mt-0.5 text-xs text-ink">
              {{ event.actorFullName || event.actorUsername || '—' }}
            </p>
            <p
              v-if="summarizePayload(event.metadataJson) !== '—'"
              class="mt-1 text-xs text-ink-secondary"
            >
              {{ summarizePayload(event.metadataJson) }}
            </p>
          </div>
        </li>
      </ol>

      <button
        v-if="hasMore"
        type="button"
        class="mt-1 text-sm font-medium text-primary-700 hover:text-primary-800 disabled:opacity-50"
        :disabled="loading"
        data-testid="audit-trail-load-more"
        @click="loadMore"
      >
        {{ loading ? 'Loading…' : 'Load more' }}
      </button>
    </div>
  </details>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useBatchStore } from '../stores/batches'

const props = defineProps<{
  batchId: string
}>()

const batchStore = useBatchStore()
const { events, eventsLoading: loading, eventsError: error, eventsHasMore: hasMore } =
  storeToRefs(batchStore)

const root = ref<HTMLDetailsElement | null>(null)
let loadedForBatchId: string | null = null

watch(
  () => props.batchId,
  async (id) => {
    loadedForBatchId = null
    batchStore.clearEvents()
    if (root.value?.open) {
      loadedForBatchId = id
      await batchStore.fetchEvents(id)
    }
  }
)

async function onToggle(e: Event) {
  const el = e.currentTarget as HTMLDetailsElement
  if (!el.open) return
  if (loadedForBatchId === props.batchId) return
  loadedForBatchId = props.batchId
  await batchStore.fetchEvents(props.batchId)
}

async function loadMore() {
  await batchStore.fetchEvents(props.batchId, batchStore.eventsNextCursor ?? undefined)
}

function formatEventType(type: string): string {
  return type
    .toLowerCase()
    .replace(/_/g, ' ')
    .replace(/\b\w/g, (c) => c.toUpperCase())
}

function formatDateTime(iso: string): string {
  try {
    return new Date(iso).toLocaleString(undefined, {
      dateStyle: 'short',
      timeStyle: 'short',
    })
  } catch {
    return iso
  }
}

function summarizePayload(metadataJson: string | null): string {
  if (!metadataJson) return '—'
  try {
    const meta = JSON.parse(metadataJson) as Record<string, unknown>
    const parts: string[] = []
    const prev = meta.previousStatus ?? meta.previous_status ?? meta.fromStatus
    const next = meta.newStatus ?? meta.new_status ?? meta.toStatus ?? meta.status
    if (typeof prev === 'string' && typeof next === 'string') {
      parts.push(`${prev} → ${next}`)
    } else if (typeof next === 'string') {
      parts.push(String(next))
    }
    const reason = meta.reason ?? meta.rejectionReason
    if (typeof reason === 'string' && reason.trim()) {
      parts.push(reason.trim().length > 80 ? `${reason.trim().slice(0, 80)}…` : reason.trim())
    }
    return parts.length > 0 ? parts.join(' · ') : '—'
  } catch {
    return '—'
  }
}
</script>
