<template>
  <div class="status-card card-glow">
    <div class="card-header">
      <h2 class="card-title">Status Backup</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.folder}`"
      class="status-row"
      :class="row.status === 200 ? 'row-ok' : 'row-error'"
    >
      <div class="flex items-center gap-3">
        <span class="status-dot" :class="row.status === 200 ? 'dot-ok' : 'dot-error'" />
        <span class="font-display text-sm font-semibold text-m-text">
          {{ row.label }}
        </span>
      </div>
      <div class="flex flex-col items-end gap-1 text-right">
        <span class="font-mono text-xs" :class="row.status === 200 ? 'text-m-success' : 'text-m-error'">
          {{ statusLabel(row.status) }}
        </span>
        <span class="font-mono text-[10px] text-m-muted">
          {{ formatBackupLabel(row) }}
        </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
  folder: string
  ok: boolean
  status: number
  checkedAt: string
  latestBackup: string | null
  latestBackupAt: string | null
  backupDate: string | null
  expectedBackupDate: string
  error?: string
}

interface StatusResponse {
  results: StatusRow[]
}

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

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

const statusLabel = (status: number) => {
  if (status === 200) return "Backup OK"
  if (status === 0) return "Backup KO"
  return `KO (${status})`
}

const formatBackupLabel = (row: StatusRow) => {
  if (!row.ok && row.backupDate) {
    return `Trouve ${row.backupDate} · attendu ${row.expectedBackupDate}`
  }

  if (row.latestBackupAt) {
    const backupDate = new Date(row.latestBackupAt)
    if (!Number.isNaN(backupDate.getTime())) {
      return backupDate.toLocaleString("fr-FR", {
        day: "2-digit",
        month: "2-digit",
        year: "numeric",
        hour: "2-digit",
        minute: "2-digit"
      })
    }
  }

  if (row.backupDate) {
    return row.backupDate
  }

  return row.error || "Aucun backup"
}

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",
        folder: "error",
        ok: false,
        status: 0,
        checkedAt: new Date().toISOString(),
        latestBackup: null,
        latestBackupAt: null,
        backupDate: null,
        expectedBackupDate: "",
        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;
  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;
}

.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>
