<template>
  <button
    :class="['input-group-text', 'btn', 'btn-primary', pelotonBtnClass]"
    type="button"
    @click="handleClick"
    :disabled="!storedObjects?.length"
  >
    <i class="fa fa-sitemap"></i>
  </button>
  <Modal
    v-if="showPelotonsModal"
    :show="showPelotonsModal"
    modal-dialog-class="modal-xl"
    @close="closeModal"
  >
    <template #header>
      <div class="dropdown-container">
        <select
          v-model="selectedStoredObject"
          class="form-select"
          @change="fetchDocument"
          style="max-width: 400px"
        >
          <option
            v-for="storedObject in storedObjects"
            :key="storedObject.id"
            :value="storedObject"
          >
            {{ storedObject.title }}
          </option>
        </select>
      </div>
    </template>
    <template #body>
      <div v-if="selectedStoredObject && documentUrl" class="document-viewer">
        <div v-if="documentType === 'image'" class="image-container">
          <img
            :src="documentUrl"
            class="img-fluid"
            style="max-width: 100%; height: auto"
          />
        </div>

        <div v-else-if="documentType === 'pdf'" class="pdf-container">
          <iframe
            :src="documentUrl"
            width="100%"
            height="100%"
            style="border: 1px solid #ccc"
          ></iframe>
          <noscript>
            <p>
              {{ trans(CHILL_TICKET_PELOTON_IFRAME_NOT_SUPPORTED) }}
              <a :href="documentUrl" target="_blank">
                {{ trans(CHILL_TICKET_PELOTON_CLICK_TO_OPEN_PDF) }}
              </a>
            </p>
          </noscript>
        </div>

        <div v-else class="unsupported-document">
          <p>{{ trans(CHILL_TICKET_PELOTON_UNSUPPORTED_TYPE) }}</p>
          <a :href="documentUrl" target="_blank" class="btn btn-primary">
            {{ trans(CHILL_TICKET_PELOTON_OPEN_NEW_TAB) }}
          </a>
        </div>
      </div>

      <div v-if="isLoading" class="loading-indicator">
        <div class="spinner-border" role="status">
          <span class="visually-hidden">{{
            trans(CHILL_TICKET_PELOTON_LOADING)
          }}</span>
        </div>
        <p>{{ trans(CHILL_TICKET_PELOTON_LOADING_DOCUMENT) }}</p>
      </div>

      <div v-if="error" class="alert alert-danger">
        {{ error }}
      </div>
    </template>
  </Modal>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

// Component
import Modal from "../../../../../../../ChillMainBundle/Resources/public/vuejs/_components/Modal.vue";

// Translations
import {
  CHILL_TICKET_PELOTON_LOADING_DOCUMENT,
  CHILL_TICKET_PELOTON_LOADING,
  CHILL_TICKET_PELOTON_ERROR_LOADING,
  CHILL_TICKET_PELOTON_UNSUPPORTED_TYPE,
  CHILL_TICKET_PELOTON_OPEN_NEW_TAB,
  CHILL_TICKET_PELOTON_IFRAME_NOT_SUPPORTED,
  CHILL_TICKET_PELOTON_CLICK_TO_OPEN_PDF,
  trans,
} from "translator";
// Type
import { StoredObject, StoredObjectVersion } from "ChillDocStoreAssets/types";

// Utils
import {
  download_info_link,
  is_object_ready,
} from "ChillDocStoreAssets/vuejs/StoredObjectButton/helpers";

const props = withDefaults(
  defineProps<{
    storedObjects: StoredObject[] | null;
    pelotonBtnClass?: string;
  }>(),
  {
    pelotonBtnClass: "",
  },
);

const selectedStoredObject = ref<StoredObject | null>(null);
const documentUrl = ref<string>("");
const documentType = ref<string>("");
const isLoading = ref<boolean>(false);
const error = ref<string>("");
const showPelotonsModal = ref<boolean>(false);

async function fetchDocument() {
  if (!selectedStoredObject.value) {
    cleanupPrevious();
    documentType.value = "";
    error.value = "";
    return;
  }

  isLoading.value = true;
  error.value = "";
  cleanupPrevious();

  try {
    const document = await is_object_ready(selectedStoredObject.value);

    const algo = "AES-CBC";
    const atVersionToDownload = selectedStoredObject.value
      .currentVersion as StoredObjectVersion;
    const downloadInfo = await download_info_link(
      selectedStoredObject.value,
      selectedStoredObject.value.currentVersion,
    );
    const rawResponse = await window.fetch(downloadInfo.url);

    if (!rawResponse.ok) {
      throw new Error(
        "error while downloading raw file " +
          rawResponse.status +
          " " +
          rawResponse.statusText,
      );
    }

    let blob: Blob;
    if (atVersionToDownload.iv.length === 0) {
      blob = await rawResponse.blob();
    } else {
      const rawBuffer = await rawResponse.arrayBuffer();
      try {
        const key = await window.crypto.subtle.importKey(
          "jwk",
          atVersionToDownload.keyInfos,
          { name: algo },
          false,
          ["decrypt"],
        );
        const iv = Uint8Array.from(atVersionToDownload.iv);
        const decrypted = await window.crypto.subtle.decrypt(
          { name: algo, iv: iv },
          key,
          rawBuffer,
        );

        blob = new Blob([decrypted], { type: document.type });

        documentUrl.value = URL.createObjectURL(blob);
      } catch (e) {
        console.error("encounter error while keys and decrypt operations");
        console.error(e);
        throw e;
      }
    }

    documentUrl.value = URL.createObjectURL(blob);

    const mimeType = blob.type;
    if (mimeType.startsWith("image/")) {
      documentType.value = "image";
    } else if (mimeType === "application/pdf") {
      documentType.value = "pdf";
    } else {
      documentType.value = "other";
    }
  } catch (err) {
    console.error(trans(CHILL_TICKET_PELOTON_ERROR_LOADING), err);
    error.value = trans(CHILL_TICKET_PELOTON_ERROR_LOADING);
  } finally {
    isLoading.value = false;
  }
}
// Nettoyer les URLs blob précédentes
function cleanupPrevious() {
  if (documentUrl.value) {
    URL.revokeObjectURL(documentUrl.value);
    documentUrl.value = "";
  }
}
function handleClick() {
  fetchDocument();
  showPelotonsModal.value = true;
}

function closeModal() {
  showPelotonsModal.value = false;
}

watch(
  () => props.storedObjects,
  (newStoredObjects) => {
    selectedStoredObject.value = newStoredObjects ? newStoredObjects[0] : null;
  },
  { immediate: true },
);
</script>

<style lang="scss" scoped>
.dropdown-container {
  .form-label {
    font-weight: 500;
    margin-bottom: 0.5rem;
  }
}

.document-viewer {
  height: 80vh;

  .image-container {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;

    img {
      box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
      border-radius: 0.25rem;
    }
  }

  .pdf-container {
    height: 100%;

    iframe {
      border-radius: 0.25rem;
      height: 100% !important;
    }
  }

  .unsupported-document {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;

    p {
      margin-bottom: 1rem;
      color: #6c757d;
    }
  }
}

.loading-indicator {
  text-align: center;
  padding: 2rem;

  .spinner-border {
    margin-bottom: 1rem;
  }

  p {
    color: #6c757d;
    margin: 0;
  }
}
</style>
