<template>
  <v-card
    border
    class="my-6"
    rounded
    style="border-radius: 10px; border: 2px solid grey"
    variant="elevated">
    <v-card-title>
      <v-row align="center" class="w-100" style="margin-top: 1px">
        <v-col class="v-col-12 v-col-lg-1 mb-3">
          <v-row :class="mobile ? 'mt-1' : ''" class="flex-nowrap ms-1 d-flex align-items-center">
            <div
              :class="
                updateFailed
                  ? 'pulsating-circle-error'
                  : packageCount.building > 0
                    ? 'pulsating-circle-amber'
                    : 'pulsating-circle-green'
              "
              class="circle-offset flex-circle" />
            <span class="ms-2">
              {{
                updateFailed
                  ? 'Could not fetch data.'
                  : packageCount.building > 0
                    ? 'Building'
                    : 'Idle'
              }}
            </span>
          </v-row>
        </v-col>
        <v-col v-if="packageCount.building > 0" class="v-col-12 v-col-lg-8 mb-3">
          <v-progress-linear
            :max="packageCount.built + packageCount.building + packageCount.queued"
            :model-value="packageCount.built"
            color="light-blue"
            height="10"
            rounded
            striped></v-progress-linear>
        </v-col>
        <v-col
          :class="mobile ? 'mt-n3' : 'text-end ms-auto'"
          class="text-grey v-col-12 v-col-lg-2 mb-3"
          cols="auto"
          style="font-size: 13px">
          <template v-if="!updateFailed">
            Last updated
            {{
              lastUpdatedSeconds > 59
                ? rtf.format(-Math.floor(lastUpdatedSeconds / 60), 'minutes')
                : rtf.format(-lastUpdatedSeconds, 'seconds')
            }}
          </template>

          <template v-else>Please try again later.</template>
        </v-col>
      </v-row>
    </v-card-title>
    <v-card-text
      v-if="packageCount.building > 0 || packageCount.queued > 0"
      class="d-flex flex-column">
      <v-list v-if="packageCount.building > 0" class="mb-4" width="100%">
        <v-list-subheader>Building</v-list-subheader>
        <v-list-item v-for="(pkg, index) in packages.building" :key="index">
          <template v-slot:prepend>
            <div class="pulsating-circle-amber me-4" />
          </template>
          <v-list-item-title>
            {{ pkg.pkgbase }}
            <span class="text-grey">({{ pkg.repo }})</span>
          </v-list-item-title>
          <v-list-item-subtitle>{{ pkg.arch_version }}</v-list-item-subtitle>
        </v-list-item>
      </v-list>
      <v-sheet class="ps-4" color="transparent" rounded width="100%">
        <h4 class="mb-2 font-weight-light text-grey">Queued</h4>
        <QueuedPackagesList :packages="packages.queued" />
      </v-sheet>
    </v-card-text>
  </v-card>
</template>

<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import type { Packages } from '@/types/Packages'
import { Package } from '@/types/Package'
import { useDisplay } from 'vuetify'
import QueuedPackagesList from './QueuedPackagesList.vue'

const BASE_URL = 'https://api.alhp.dev/packages'
const UPDATE_INTERVAL_MINUTES = 5

const { mobile } = useDisplay()
const lastUpdatedTime = ref(0)
const lastUpdatedSeconds = ref(0)
const updateFailed = ref(false)
const rtf = new Intl.RelativeTimeFormat('en', {
  localeMatcher: 'best fit',
  numeric: 'always',
  style: 'long'
})

const packageCount = ref({
  total: 0,
  building: 0,
  built: 0,
  queued: 0
})

const packages = ref<{
  built: Array<Package>
  building: Array<Package>
  queued: Array<Package>
}>({
  built: [],
  building: [],
  queued: []
})

let timerInterval: NodeJS.Timeout // Declare timerInterval outside the function

const fetchPackages = async (offset: string, status?: string) => {
  let url = `${BASE_URL}?limit=0&offset=${offset}`
  if (status) {
    url += `&status=${status}`
  }

  try {
    const response = await fetch(url, { method: 'GET' })
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`)
    }
    const json: Packages = await response.json()

    lastUpdatedTime.value = Date.now()
    lastUpdatedSeconds.value = 0 // Reset seconds counter
    updateFailed.value = false

    return json
  } catch (error) {
    console.error('Error fetching packages:', error)
    updateFailed.value = true
    return null
  }
}

const getTotalPackages = async () => {
  const json = await fetchPackages('1')
  if (json) {
    packageCount.value.total = json.total
  }
}

const getBuiltPackages = async () => {
  const json = await fetchPackages('0', 'built')
  if (json) {
    packageCount.value.built = json.total
    packages.value.built = json.packages
  }
}

const getBuildingPackages = async () => {
  const json = await fetchPackages('0', 'building')
  if (json) {
    packageCount.value.building = json.total
    packages.value.building = json.packages
  }
}

const getQueuedPackages = async () => {
  const json = await fetchPackages('0', 'queued')
  if (json) {
    packageCount.value.queued = json.total
    packages.value.queued = json.packages
  }
}

// Function to start the timer
const startTimer = () => {
  stopTimer() // Clear any existing timer
  getTotalPackages()
  getBuiltPackages()
  getBuildingPackages()
  getQueuedPackages()
  timerInterval = setInterval(
    () => {
      getTotalPackages()
      getBuiltPackages()
      getBuildingPackages()
      getQueuedPackages()
    },
    UPDATE_INTERVAL_MINUTES * 60 * 1000
  )
}

// Function to stop the timer
const stopTimer = () => {
  clearInterval(timerInterval)
}

onMounted(() => {
  startTimer() // Start the timer when the component is mounted
})

// Update seconds counter every second
setInterval(() => {
  lastUpdatedSeconds.value++
}, 1000)
</script>

<style lang="scss">
.pulsating-circle-green {
  background-color: rgba(126, 206, 5, 0.94);
  border-radius: 50%;
  width: 12px;
  height: 12px;
}

.pulsating-circle-green:before {
  content: '';
  display: block;
  width: 200%;
  height: 200%;
  box-sizing: border-box;
  margin-left: -50%;
  margin-top: -50%;
  border-radius: 50%;
  background-color: rgba(126, 206, 5, 0.94);
  -webkit-animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
  animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}

.pulsating-circle-amber {
  background-color: #f39c12f0;
  border-radius: 50%;
  width: 12px;
  height: 12px;
}

.pulsating-circle-amber:before {
  content: '';
  display: block;
  width: 200%;
  height: 200%;
  box-sizing: border-box;
  margin-left: -50%;
  margin-top: -50%;
  border-radius: 50%;
  background-color: #f39c12;
  -webkit-animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
  animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}

.pulsating-circle-error {
  background-color: rgba(225, 64, 6, 0.94);
  border-radius: 50%;
  width: 12px;
  height: 12px;
}

.pulsating-circle-error:before {
  content: '';
  display: block;
  width: 200%;
  height: 200%;
  box-sizing: border-box;
  margin-left: -50%;
  margin-top: -50%;
  border-radius: 50%;
  background-color: rgba(225, 64, 6, 0.94);
  -webkit-animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
  animation: pulse-ring 1.25s cubic-bezier(0.215, 0.61, 0.355, 1) infinite;
}

.circle-offset {
  transform: translateY(10px); /* Preserves vertical shift as needed */
}

.flex-circle {
  flex-shrink: 0; /* Prevents shrinking */
  flex-grow: 0; /* Prevents growing */
  width: 12px; /* Ensures consistent dimensions */
  height: 12px;
  border-radius: 50%; /* Maintains circular appearance */
}

@-webkit-keyframes pulse-ring {
  0% {
    transform: scale(0.33);
  }

  80%,
  100% {
    opacity: 0;
  }
}

@keyframes pulse-ring {
  0% {
    transform: scale(0.33);
  }

  80%,
  100% {
    opacity: 0;
  }
}

@-webkit-keyframes pulse-dot {
  0% {
    transform: scale(0.8);
  }

  50% {
    transform: scale(1);
  }

  100% {
    transform: scale(0.8);
  }
}

@keyframes pulse-dot {
  0% {
    transform: scale(0.8);
  }

  50% {
    transform: scale(1);
  }

  100% {
    transform: scale(0.8);
  }
}
</style>
