<template>
  <NuxtLayout name="default">
    <template #sidebar>
      <div class="flex flex-col">
        <DiagramStorage
          v-for="item in diagramItems"
          :key="item.key"
          :loading="loading"
          :host-name="item.hostName"
          :status-color-class="item.statusColorClass"
          :chart-radius="chartRadius"
          :chart-circumference="chartCircumference"
          :chart-offset="item.chartOffset"
          :remaining-percent-text="item.remainingPercentText"
          :used-text="item.usedText"
          :total-text="item.totalText"
        />
      </div>
    </template>

    <p class="font-bold text-4xl my-6 mx-4">Écran de monitoring</p>

    <div class="flex">
      <div class="flex flex-col gap-4">
        <StatusSite />
        <BackupButtonSee @select="selectedBackup = $event" />
      </div>

      <div class="flex flex-col gap-4">
        <Speedtest />
        <BackupList :folder="selectedBackup" />
        <MessageDiscord/>
      </div>
    </div>
  </NuxtLayout>
</template>

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

type SourceKey = "remote" | "local"
type DiskCommandResult = { ok: boolean; output: string }
type DiskApiResponse = {
  remote?: string | DiskCommandResult
  local?: string | DiskCommandResult
}

const selectedBackup = ref<string | null>(null)
const rawResults = ref<Record<SourceKey, string>>({
  remote: "",
  local: ""
})
const loading = ref(false)
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 getOutputText = (entry: unknown) => {
  if (typeof entry === "string") return entry
  if (entry && typeof entry === "object" && "output" in entry) {
    const output = (entry as DiskCommandResult).output
    return typeof output === "string" ? output : String(output)
  }
  return ""
}

const diagramItems = computed(() => {
  return [
    { key: "remote" as const, fallbackHost: "Serveur distant", output: rawResults.value.remote },
    { key: "local" as const, fallbackHost: "Machine locale", output: rawResults.value.local }
  ].map((item) => {
    const diskValues = getDiskValues(item.output)
    const remainingPercent =
      diskValues === null
        ? null
        : Math.max(
            0,
            Math.min(100, Math.round((diskValues.availableGb / diskValues.totalGb) * 100))
          )

    const chartOffset = chartCircumference - ((remainingPercent ?? 0) / 100) * chartCircumference
    const statusColorClass =
      remainingPercent !== null && remainingPercent <= 30 ? "m-error" : "m-success"

    return {
      key: item.key,
      hostName: getHostName(item.output, item.fallbackHost),
      statusColorClass,
      chartOffset,
      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 = {
    remote: "",
    local: ""
  }

  try {
    const output = await $fetch<DiskApiResponse | string>("/api/disk")

    if (typeof output === "string") {
      rawResults.value = {
        remote: output,
        local: "Erreur: sortie locale indisponible"
      }
      return
    }

    rawResults.value = {
      remote: getOutputText(output.remote),
      local: getOutputText(output.local)
    }
  } catch (error) {
    const message = `Erreur: ${error instanceof Error ? error.message : String(error)}`
    rawResults.value = {
      remote: message,
      local: message
    }
  } finally {
    loading.value = false
  }
}
onMounted(() => {
  runScript()
})
</script>
