<script lang="ts" setup>
/**
 * @todo require keyfile to be set before allowing user to check for OS updates
 * @todo require keyfile to update
 * @todo require valid guid / server state to update
 */
import { Switch, SwitchGroup, SwitchLabel } from '@headlessui/vue';
import {
  ArchiveBoxArrowDownIcon,
  ArrowPathIcon,
  ArrowTopRightOnSquareIcon,
  BellAlertIcon,
  EyeIcon,
} from '@heroicons/vue/24/solid';
import dayjs from 'dayjs';
import { storeToRefs } from 'pinia';
import { ref, watchEffect } from 'vue';
import type { ComposerTranslation } from 'vue-i18n';

import 'tailwindcss/tailwind.css';
import '~/assets/main.css';

import useDateTimeHelper from '~/composables/dateTime';
import { useServerStore } from '~/store/server';
import { useUpdateOsStore } from '~/store/updateOs';
import { useUpdateOsActionsStore } from '~/store/updateOsActions';
import type { UserProfileLink } from '~/types/userProfile';

const props = defineProps<{
  t: ComposerTranslation;
}>();

const serverStore = useServerStore();
const { dateTimeFormat, updateOsResponse } = storeToRefs(serverStore);

const updateOsStore = useUpdateOsStore();
const updateOsActionsStore = useUpdateOsActionsStore();

const { connectPluginInstalled, flashBackupActivated } = storeToRefs(useServerStore());
const { available } = storeToRefs(updateOsStore);

const {
  outputDateTimeFormatted: formattedReleaseDate,
} = useDateTimeHelper(dateTimeFormat.value, props.t, true, dayjs(updateOsResponse.value?.date ?? '', 'YYYY-MM-DD').valueOf());

const updateButton = ref<UserProfileLink | undefined>();

const heading = computed(() => {
  if (available.value && updateButton?.value?.text && updateButton?.value?.textParams) {
    return props.t(updateButton?.value.text, updateButton?.value.textParams);
  }
  return props.t('Check for OS Updates');
});

const headingIcon = computed(() => {
  if (available.value) {
    return BellAlertIcon;
  }
  return ArrowPathIcon;
});

const flashBackupCopy = computed(() => {
  const base = props.t('We recommend backing up your USB Flash Boot Device before starting the update.');
  if (connectPluginInstalled.value && flashBackupActivated.value) {
    return `${base}
      ${props.t('You have already activated the Flash Backup feature via the Unraid Connect plugin.')}
      ${props.t('Go to Tools > Management Access to ensure your backup is up-to-date.')}
      ${props.t('You can also manually create a new backup by clicking the Create Flash Backup button.')}
    `;
  }
  if (connectPluginInstalled.value && !flashBackupActivated.value) {
    return `${base}
      ${props.t('You have not activated the Flash Backup feature via the Unraid Connect plugin.')}
      ${props.t('Go to Tools > Management Access to activate the Flash Backup feature and ensure your backup is up-to-date.')}
      ${props.t('You can also manually create a new backup by clicking the Create Flash Backup button.')}
    `;
  }
  return `${base} ${props.t('You can manually create a backup by clicking the Create Flash Backup button.')}`;
});

const acknowledgeBackup = ref<boolean>(false);
const flashBackupBasicStatus = ref<'complete' | 'ready' | 'started'>('ready');
const flashBackupText = computed(() => props.t('Create Flash Backup'));
const startFlashBackup = () => {
  console.debug('[startFlashBackup]', Date.now());
  // @ts-expect-error – global function provided by the webgui on the update page
  if (typeof flashBackup === 'function') {
    flashBackupBasicStatus.value = 'started';
    // @ts-expect-error – global function provided by the webgui on the update page
    flashBackup();
    checkFlashBackupStatus();
  } else {
    alert(props.t('Flash Backup is not available. Navigate to {0}/Main/Settings/Flash to try again then come back to this page.', [window.location.origin]));
  }
};
/**
 * Checking for element on the page to determine if the flash backup has started
 */
const checkFlashBackupStatus = () => {
  const loadingElement: HTMLCollectionOf<Element> = document.getElementsByClassName('spinner');
  setTimeout(() => {
    if (loadingElement.length > 0 && loadingElement[0]) {
      const el = loadingElement[0] as HTMLDivElement;
      const loaderHidden = el.style.display === 'none';
      if (loaderHidden) {
        flashBackupBasicStatus.value = 'complete';
        console.debug('[checkFlashBackupStatus] complete', Date.now());
      } else {
        checkFlashBackupStatus(); // check again
      }
    } else {
      flashBackupBasicStatus.value = 'complete';
    }
  }, 500);
};

const disableCallbackButton = computed(() => !acknowledgeBackup.value || flashBackupBasicStatus.value === 'started');

watchEffect(() => {
  if (available.value) {
    updateButton.value = updateOsActionsStore.updateCallbackButton();
  } else {
    updateButton.value = updateOsActionsStore.updateCallbackButton();
  }
  if (flashBackupBasicStatus.value === 'complete') {
    acknowledgeBackup.value = true; // auto check the box
  }
});
</script>

<template>
  <UiCardWrapper :increased-padding="true">
    <div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-20px sm:gap-24px">
      <div class="grid gap-y-16px">
        <h3
          class="font-semibold leading-normal flex flex-row items-start justify-start gap-8px"
        >
          <component :is="headingIcon" class="w-20px shrink-0" />
          <span class="leading-none inline-flex flex-wrap justify-start items-baseline gap-8px">
            <span class="text-20px">
              {{ heading }}
            </span>
            <span
              v-if="updateOsResponse && formattedReleaseDate"
              class="text-16px opacity-75 shrink"
            >
              {{ formattedReleaseDate }}
            </span>
          </span>
        </h3>

        <div class="prose opacity-75 text-16px leading-relaxed whitespace-normal">
          <p>{{ t('Receive the latest and greatest for Unraid OS. Whether it new features, security patches, or bug fixes – keeping your server up-to-date ensures the best experience that Unraid has to offer.') }}</p>
          <p v-if="available">
            {{ flashBackupCopy }}
          </p>
        </div>
      </div>

      <div class="flex flex-col sm:flex-shrink-0 items-center gap-16px">
        <template v-if="available && updateButton">
          <BrandButton
            btn-style="outline"
            :disabled="flashBackupBasicStatus === 'started'"
            :icon="ArchiveBoxArrowDownIcon"
            :name="'flashBackup'"
            :text="flashBackupText"
            class="flex-none"
            @click="startFlashBackup"
          />

          <p v-if="flashBackupBasicStatus === 'started'" class="text-12px italic opacity-75 shrink">
            {{ t('Backing up...this may take a few minutes') }}
          </p>

          <SwitchGroup as="div">
            <div class="flex flex-shrink-0 items-center gap-16px">
              <Switch
                v-model="acknowledgeBackup"
                :disabled="flashBackupBasicStatus === 'started'"
                :class="[
                  acknowledgeBackup ? 'bg-green-500' : 'bg-gray-200',
                  'relative inline-flex h-24px w-[44px] flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-indigo-600 focus:ring-offset-2',
                ]"
              >
                <span
                  :class="[
                    acknowledgeBackup ? 'translate-x-20px' : 'translate-x-0',
                    'pointer-events-none relative inline-block h-20px w-20px transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out',
                  ]"
                >
                  <span
                    :class="[
                      acknowledgeBackup ? 'opacity-0 duration-100 ease-out' : 'opacity-100 duration-200 ease-in',
                      'absolute inset-0 flex h-full w-full items-center justify-center transition-opacity',
                    ]"
                    aria-hidden="true"
                  >
                    <svg class="h-12px w-12px text-gray-400" fill="none" viewBox="0 0 12 12">
                      <path d="M4 8l2-2m0 0l2-2M6 6L4 4m2 2l2 2" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
                    </svg>
                  </span>
                  <span
                    :class="[
                      acknowledgeBackup ? 'opacity-100 duration-200 ease-in' : 'opacity-0 duration-100 ease-out',
                      'absolute inset-0 flex h-full w-full items-center justify-center transition-opacity',
                    ]"
                    aria-hidden="true"
                  >
                    <svg class="h-12px w-12px text-green-500" fill="currentColor" viewBox="0 0 12 12">
                      <path d="M3.707 5.293a1 1 0 00-1.414 1.414l1.414-1.414zM5 8l-.707.707a1 1 0 001.414 0L5 8zm4.707-3.293a1 1 0 00-1.414-1.414l1.414 1.414zm-7.414 2l2 2 1.414-1.414-2-2-1.414 1.414zm3.414 2l4-4-1.414-1.414-4 4 1.414 1.414z" />
                    </svg>
                  </span>
                </span>
              </Switch>
              <SwitchLabel class="text-14px">
                {{ t('I have made a Flash Backup') }}
              </SwitchLabel>
            </div>
          </SwitchGroup>
        </template>

        <BrandButton
          btn-style="fill"
          :disabled="disableCallbackButton"
          :external="updateButton?.external"
          :icon="EyeIcon"
          :icon-right="ArrowTopRightOnSquareIcon"
          :name="updateButton?.name"
          :text="t('View Available Updates')"
          :title="!acknowledgeBackup ? t('Acklowledge that you have made a Flash Backup to enable this action') : ''"
          class="flex-none"
          @click="updateButton?.click"
        />
      </div>
    </div>
  </UiCardWrapper>
</template>

<style lang="postcss">
@tailwind base;
@tailwind components;
@tailwind utilities;
</style>
