<script setup lang="ts">
import { useResourceStore } from "@/stores/resources";
import { computed, onMounted, reactive } from "vue";
import {
  type ResourceOut,
  type ResourceVersionOut,
  Status,
} from "@/client/resource";
import FontAwesomeIcon from "@/components/FontAwesomeIcon.vue";
import { Modal, Toast, Tooltip } from "bootstrap";
import ResourceVersionInfoModal from "@/components/resources/modals/ResourceVersionInfoModal.vue";
import { useNameStore } from "@/stores/names";
import BootstrapToast from "@/components/BootstrapToast.vue";
import ReasonModal from "@/components/modals/ReasonModal.vue";

const resourceRepository = useResourceStore();
const nameRepository = useNameStore();
let refreshTimeout: NodeJS.Timeout | undefined = undefined;
let rejectReasonModal: Modal | null = null;
let successToast: Toast | null = null;
let rejectToast: Toast | null = null;

const resourceState = reactive<{
  sendingRequest: boolean;
  loading: boolean;
  inspectResource?: ResourceOut;
  rejectResource?: ResourceVersionOut;
  inspectVersionIndex: number;
}>({
  sendingRequest: false,
  loading: true,
  inspectResource: undefined,
  rejectResource: undefined,
  inspectVersionIndex: 0,
});

const countItems = computed<number>(() =>
  resourceRepository.reviewableResources.reduce(
    (previousValue, currentValue) =>
      previousValue + currentValue.versions.length,
    0,
  ),
);

function fetchResources() {
  resourceRepository.fetchReviewableResources(() => {
    resourceState.loading = false;
  });
}

function clickRefreshResources() {
  clearTimeout(refreshTimeout);
  refreshTimeout = setTimeout(() => {
    fetchResources();
  }, 500);
}

function acceptReview(resourceVersion: ResourceVersionOut) {
  resourceState.sendingRequest = true;
  resourceRepository
    .reviewResource(resourceVersion, { deny: false })
    .then(() => {
      successToast?.show();
    })
    .finally(() => {
      resourceState.sendingRequest = false;
    });
}

function rejectReview(reason: string, resourceVersion?: ResourceVersionOut) {
  if (resourceVersion) {
    resourceState.sendingRequest = true;
    resourceRepository
      .reviewResource(resourceVersion, { deny: true, reason: reason })
      .then(() => {
        rejectReasonModal?.hide();
        rejectToast?.show();
      })
      .finally(() => {
        resourceState.sendingRequest = false;
      });
  }
}

onMounted(() => {
  fetchResources();
  new Tooltip("#refreshReviewableResourcesButton");
  rejectReasonModal = new Modal("#review-reject-modal");
  successToast = new Toast("#accept-resource-review-toast");
  rejectToast = new Toast("#reject-resource-review-toast");
});
</script>

<template>
  <bootstrap-toast
    toast-id="accept-resource-review-toast"
    color-class="success"
  >
    Accepted resource review
  </bootstrap-toast>
  <bootstrap-toast toast-id="reject-resource-review-toast" color-class="danger">
    Rejected resource review
  </bootstrap-toast>
  <resource-version-info-modal
    modal-id="review-resource-version-info-modal"
    :resource-version-index="resourceState.inspectVersionIndex"
    :resource="resourceState.inspectResource"
  />
  <reason-modal
    modal-id="review-reject-modal"
    modal-label="Resource Review Reject Modal"
    :loading="resourceState.sendingRequest"
    purpose="rejection"
    @save="(reason) => rejectReview(reason, resourceState.rejectResource)"
  >
    <template #header>
      Reject Resource Review <b>{{ resourceState.rejectResource?.release }}</b>
    </template>
  </reason-modal>
  <div
    class="row border-bottom mb-4 justify-content-between align-items-center"
  >
    <h2 class="w-fit">Resource requests</h2>
    <span
      class="w-fit"
      tabindex="0"
      data-bs-title="Refresh Reviewable Resources"
      data-bs-toggle="tooltip"
      id="refreshReviewableResourcesButton"
    >
      <button
        type="button"
        class="btn btn-primary btn-light me-2 shadow-sm border w-fit"
        :disabled="resourceState.loading"
        @click="clickRefreshResources"
      >
        <font-awesome-icon icon="fa-solid fa-arrow-rotate-right" />
        <span class="visually-hidden">Refresh Reviewable Resources</span>
      </button>
    </span>
  </div>
  <div v-if="resourceState.loading" class="text-center mt-5">
    <div class="spinner-border" style="width: 3rem; height: 3rem" role="status">
      <span class="visually-hidden">Loading...</span>
    </div>
  </div>
  <table
    class="table caption-top table-striped table-hover align-middle"
    v-else-if="resourceRepository.reviewableResources.length > 0"
  >
    <caption>
      Display
      {{
        countItems
      }}
      resource versions
    </caption>
    <thead>
      <tr>
        <th scope="col">Resource</th>
        <th scope="col">Release</th>
        <th scope="col">Status</th>
        <th scope="col">Maintainer</th>
        <th scope="col"></th>
        <th scope="col" class="text-end">Action</th>
      </tr>
    </thead>
    <tbody>
      <template
        v-for="resource in resourceRepository.reviewableResources"
        :key="resource.resource_id"
      >
        <tr
          v-for="(version, index) in resource.versions"
          :key="version.resource_version_id"
        >
          <th>{{ resource.name }}</th>
          <th>{{ version.release }}</th>
          <th>{{ version.status }}</th>
          <th>{{ nameRepository.getName(resource.maintainer_id) }}</th>
          <th>
            <button
              type="button"
              class="btn btn-secondary"
              data-bs-toggle="modal"
              data-bs-target="#review-resource-version-info-modal"
              @click="
                resourceState.inspectResource = resource;
                resourceState.inspectVersionIndex = index;
              "
            >
              Inspect
            </button>
          </th>
          <th class="text-end">
            <div
              v-if="version.status === Status.WAIT_FOR_REVIEW"
              class="btn-group"
            >
              <button
                type="button"
                class="btn btn-success btn-sm"
                :disabled="resourceState.sendingRequest"
                @click="acceptReview(version)"
              >
                Accept
              </button>
              <button
                type="button"
                class="btn btn-danger btn-sm"
                @click="resourceState.rejectResource = version"
                data-bs-toggle="modal"
                data-bs-target="#review-reject-modal"
                :disabled="resourceState.sendingRequest"
              >
                Reject
              </button>
            </div>
            <div
              v-else-if="version.status === Status.SYNCHRONIZING"
              class="progress"
              role="progressbar"
              aria-label="Animated striped example"
              aria-valuenow="100"
              aria-valuemin="0"
              aria-valuemax="100"
            >
              <div
                class="progress-bar progress-bar-striped progress-bar-animated"
                style="width: 100%"
              ></div>
            </div>
          </th>
        </tr>
      </template>
    </tbody>
  </table>
  <div v-else class="text-center mt-5 fs-4">
    There are currently no resources to review
  </div>
</template>

<style scoped></style>