<template>
  <NuxtLayout name="default">
    <div class="dashboard-container">
      <header class="dashboard-header">
        <div>
          <h1 class="font-display text-3xl font-bold tracking-tight text-m-text">
            Monitoring
          </h1>
        </div>
      </header>

      <div class="content-grid">
        <div class="content-main">
          <section class="storage-section">
            <div class="storage-section-header">
              <h2 class="font-display text-xl font-semibold text-m-text">Stockage</h2>
              <span class="font-mono text-[10px] uppercase tracking-widest text-m-muted">Volumes</span>
            </div>
            <div class="storage-grid">
              <DiagramStorage
                v-for="(item, idx) in diagramItems"
                :key="item.key"
                :item="item"
                :style="{ animationDelay: `${idx * 150}ms` }"
                class="animate-fade-in-up"
              />
            </div>
          </section>

          <div class="dashboard-grid">
            <div class="grid-left">
              <StatusSite class="animate-fade-in-up" style="animation-delay: 100ms" />
            </div>

            <div class="grid-middle">
              <Speedtest class="animate-fade-in-up speedtest-card-mobile" style="animation-delay: 150ms" />
            </div>
          </div>
        </div>

        <div class="content-aside">
          <MessageDiscord class="animate-fade-in-up" style="animation-delay: 300ms" />
        </div>
      </div>
    </div>
  </NuxtLayout>
</template>

<script setup lang="ts">
definePageMeta({layout: false})
import {computed, onMounted, ref} from "vue"
import { useApiAuthHeader } from "~/composables/useApiAuth"

type DiskSourceResult = {
  key: string
  label: string
  ok: boolean
  output: string
}

type DiskApiResponse = {
  results: DiskSourceResult[]
}

type DiagramItem = {
  key: string
  loading: boolean
  hostName: string
  statusColorClass: string
  chartRadius: number
  chartCircumference: number
  chartOffset: number
  remainingPercentText: string
  usedText: string
  totalText: string
}

const selectedBackup = ref<string | null>(null)
const rawResults = ref<DiskSourceResult[]>([])
const loading = ref(false)
const apiAuthHeader = useApiAuthHeader()
const chartRadius = 52
const chartCircumference = 2 * Math.PI * chartRadius

const getHostName = (output: string, fallback: string) => {
  const hostMatch = output.match(/Name:\s*(.+)/i)
  return hostMatch?.[1]?.trim() || fallback
}

const getDiskValues = (output: string) => {
  if (!output || output.startsWith("Erreur:")) return null

  const availableLine = output
    .split("\n")
    .find((line) => line.toLowerCase().includes("espace disponible"))
  const usageLine = output
    .split("\n")
    .find((line) => line.toLowerCase().includes("espace utilise / espace total"))

  const availableRaw = availableLine?.match(/:\s*(\d+(?:[.,]\d+)?)\s*GB/i)?.[1]
  const usedRaw = usageLine?.match(/:\s*(\d+(?:[.,]\d+)?)\s*GB/i)?.[1]
  const totalRaw = usageLine?.match(/\/\s*(\d+(?:[.,]\d+)?)\s*GB/i)?.[1]

  const availableGb = availableRaw ? Number.parseFloat(availableRaw.replace(",", ".")) : null
  const usedGb = usedRaw ? Number.parseFloat(usedRaw.replace(",", ".")) : null
  const totalGb = totalRaw ? Number.parseFloat(totalRaw.replace(",", ".")) : null

  if (
      availableGb === null ||
      usedGb === null ||
      totalGb === null ||
      !Number.isFinite(availableGb) ||
      !Number.isFinite(usedGb) ||
      !Number.isFinite(totalGb) ||
      totalGb <= 0
  ) {
      return null
  }

  return {availableGb, usedGb, totalGb}
}

const diagramItems = computed<DiagramItem[]>(() => {
  return rawResults.value.map((result) => {
    const diskValues = getDiskValues(result.output)
    const remainingPercent =
      diskValues === null
        ? null
        : Math.max(
            0,
            Math.min(100, Math.round((diskValues.availableGb / diskValues.totalGb) * 100))
          )

    return {
      key: result.key,
      loading: loading.value,
      hostName: getHostName(result.output, result.label),
      statusColorClass:
        remainingPercent !== null && remainingPercent <= 30 ? "status-error" : "status-success",
      chartRadius,
      chartCircumference,
      chartOffset: chartCircumference - ((remainingPercent ?? 0) / 100) * chartCircumference,
      remainingPercentText:
        loading.value ? "..." : remainingPercent === null ? "--%" : `${remainingPercent}%`,
      usedText: loading.value ? "..." : diskValues ? `${diskValues.usedGb.toFixed(2)} GB` : "--",
      totalText: loading.value ? "..." : diskValues ? `${diskValues.totalGb.toFixed(2)} GB` : "--"
    }
  })
})

const runScript = async () => {
  loading.value = true
  rawResults.value = []

  try {
    const output = await $fetch<DiskApiResponse>("/api/disk", {
      headers: apiAuthHeader
    })
    rawResults.value = output.results
  } catch (error) {
    rawResults.value = [
      {
        key: "error",
        label: "Source indisponible",
        ok: false,
        output: "Erreur lors de l'opération"
      }
    ]
  } finally {
    loading.value = false
  }
}

onMounted(() => {
  runScript()
})
</script>

<style scoped>
.dashboard-container {
  padding: 2rem 2.5rem;
}

.dashboard-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid rgba(80, 140, 255, 0.08);
}

.storage-section {
  margin-bottom: 1.5rem;
}

.storage-section-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 0.75rem;
}

.storage-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  border-radius: 12px;
  background: rgb(var(--m-secondary));
  padding: 0.75rem;
}

.content-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 1.5rem;
  align-items: start;
}

.content-main {
  min-width: 0;
}

.content-aside {
  min-width: 0;
}

.dashboard-grid {
  display: grid;
  grid-template-columns: 280px minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}

.grid-left,
.grid-middle,
.grid-right {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
}

@media (max-width: 1180px) {
  .content-grid {
    grid-template-columns: 1fr;
  }

  .content-aside {
    grid-column: 1 / -1;
  }
}

@media (max-width: 820px) {
  .dashboard-container {
    padding: 4.5rem 1.25rem 1.25rem;
  }

  .dashboard-header {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
  }

  .storage-grid,
  .content-grid,
  .dashboard-grid {
    grid-template-columns: 1fr;
  }

  .backup-selector {
    order: 2;
  }

  .backup-list-mobile {
    order: 3;
  }

  .speedtest-card-mobile {
    order: 4;
  }

  .content-aside {
    grid-column: auto;
    order: 5;
  }
}
</style>
