<template>
  <div class="status-card card-glow">
    <div class="card-header">
      <h2 class="card-title">Status App</h2>
      <span class="font-mono text-[10px] text-m-muted tracking-widest uppercase">Services</span>
    </div>

    <template v-if="loading">
      <div
        v-for="n in 3"
        :key="`skeleton-${n}`"
        class="status-row animate-shimmer"
      >
        <div class="flex items-center gap-3">
          <CircleSkeleton custom-class="h-3 w-3" />
          <TextSkeleton custom-class="h-4 w-20" />
        </div>
        <TextSkeleton custom-class="h-4 w-16" />
      </div>
    </template>

    <div
      v-for="row in rows"
      v-else
      :key="`${row.label}-${row.url}`"
      class="status-row"
      :class="row.ok ? 'row-ok' : 'row-error'"
    >
      <div class="status-copy">
        <div class="flex items-center gap-3">
          <span class="status-dot" :class="row.ok ? 'dot-ok' : 'dot-error'" />
          <span class="font-display text-sm font-semibold text-m-text">
            {{ row.label }}
          </span>
        </div>
        <p class="status-detail">
          {{ row.detail }}
        </p>
      </div>
      <div class="status-meta">
        <span class="font-mono text-xs" :class="row.ok ? 'text-m-success' : 'text-m-error'">
          {{ statusLabel(row) }}
        </span>
        <span class="status-time">
          {{ formatCheckedAt(row.checkedAt) }}
        </span>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import CircleSkeleton from "~/components/skeleton/CircleSkeleton.vue"
import TextSkeleton from "~/components/skeleton/TextSkeleton.vue"
import {onBeforeUnmount, onMounted, ref} from "vue"
import { apiFetch } from "~/composables/useApiAuth"

interface StatusRow {
  label: string
  url: string
  ok: boolean
  status: number
  checkedAt: string
  detail: string
  error?: string
}

interface StatusResponse {
  results: StatusRow[]
}

const props = withDefaults(
    defineProps<{
      endpoint?: string
      refreshMs?: number
    }>(),
    {
      endpoint: "/api/version-status",
      refreshMs: 30000
    }
)

const rows = ref<StatusRow[]>([])
const loading = ref(true)
const initialized = ref(false)
let timer: ReturnType<typeof setInterval> | null = null

const statusLabel = (row: StatusRow) => {
  if (row.ok) return "OK"
  if (row.status === 0) return "DOWN"
  return `KO (${row.status})`
}

const formatCheckedAt = (checkedAt: string) => {
  const date = new Date(checkedAt)

  if (Number.isNaN(date.getTime())) {
    return checkedAt
  }

  return date.toLocaleTimeString("fr-FR", {
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit"
  })
}

const checkStatus = async () => {
  if (!initialized.value) {
    loading.value = true
  }
  try {
    const data = await apiFetch<StatusResponse>(props.endpoint)
    rows.value = data.results
  } catch (error) {
    rows.value = [
      {
        label: "Erreur",
        url: props.endpoint,
        ok: false,
        status: 0,
        checkedAt: new Date().toISOString(),
        detail: "Lecture du statut impossible",
        error: error instanceof Error ? error.message : String(error)
      }
    ]
  } finally {
    initialized.value = true
    loading.value = false
  }
}

onMounted(() => {
  checkStatus()
  timer = setInterval(checkStatus, props.refreshMs)
})

onBeforeUnmount(() => {
  if (timer) {
    clearInterval(timer)
    timer = null
  }
})
</script>

<style scoped>
.status-card {
  background:
    linear-gradient(180deg, rgb(var(--m-secondary) / 0.78), rgb(var(--m-secondary) / 0.92));
  border-radius: 20px;
  padding: 1.25rem;
  border: 1px solid rgb(var(--m-border) / 0.32);
  box-shadow: inset 0 1px 0 rgb(255 255 255 / 0.03);
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  transition: background-color 0.4s ease, border-color 0.2s ease;
}

.card-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 0.25rem;
}

.card-title {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  color: rgb(var(--m-text));
}

.status-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: 3.2rem;
  padding: 0.85rem 1rem;
  border-radius: 14px;
  background: rgb(var(--m-tertiary) / 0.75);
  border: 1px solid rgb(var(--m-border) / 0.2);
  transition: all 0.2s ease;
}

.status-copy {
  min-width: 0;
}

.status-detail {
  margin: 0.35rem 0 0;
  color: rgb(var(--m-muted));
  font-size: 0.78rem;
  line-height: 1.4;
}

.status-meta {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.2rem;
  flex-shrink: 0;
}

.status-time {
  font-size: 0.72rem;
  color: rgb(var(--m-muted));
}

.row-ok {
  border-color: rgb(var(--m-success) / 0.08);
}

.row-error {
  border-color: rgb(var(--m-error) / 0.1);
  background: rgb(var(--m-error) / 0.04);
}

.status-dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  flex-shrink: 0;
}

.dot-ok {
  background: rgb(var(--m-success));
  box-shadow: 0 0 6px rgb(var(--m-success) / 0.5);
}

.dot-error {
  background: rgb(var(--m-error));
  box-shadow: 0 0 6px rgb(var(--m-error) / 0.5);
  animation: pulse-glow 2s ease-in-out infinite;
}
</style>
