<template>
  <div class="columns mx-0 mb-0 pb-0">
    <div class="column is-6">
      <div class="tags are-medium">
        <a v-for="v in hashtag" @click="refreshShow(v)">
          <span :class="`tag ${v.file__hashtag===current? 'is-primary' : ''}`">
            {{ v.file__hashtag }}
            {{ `(${v.count})` }}
          </span>
        </a>
      </div>
    </div>
    <div class="column is-6">
    <div class="is-flex is-align-items-center is-justify-content-flex-end">
      <div class="buttons has-addons are-small my-0">
        <button 
          v-for="layout in Object.values(layoutModes)"
          :key="layout"
          :class="[
            'button px-5', 
            { 'is-primary': layout === layoutMode },
          ]"
          @click="layoutMode = layout"
        >
          <SvgIcon v-bind="{
            name: `${layout}.svg`, 
            type: layout === layoutMode ? 'white' : 'primary',
            size: 20
          }" />
        </button>
      </div>
      <div v-if="!dealer && $getEditRights('edit', { code: 'product', category: 'topmenu' })" class="ml-6 is-flex is-align-items-center">
        <div class="mr-5">
          <label class="checkbox mr-2">
            <input type="checkbox" v-model="convertToWebp" />
            <span class="ml-2">Convert to WebP</span>
          </label>
            <input v-if="convertToWebp"
              class="input is-small"
              type="number"
              v-model.number="webpQuality"
              min="1"
              max="100"
              style="width: 60px"
              placeholder="80"
            />
        </div>
        <FileUpload
          position="right"
          type="image"
          :convert="convertToWebp"
          :quality="webpQuality"
          @files="onUploaded"
        />
      </div>
    </div>
    </div>
  </div>
  <component 
    :is="layoutMode === layoutModes.GRID ? 'div' : 'table'" 
    :class="layoutMode === layoutModes.GRID ? 'columns is-multiline px-2 mt-0' : 'table is-fullwidth is-bordered'"
  >
    <template v-if="layoutMode === layoutModes.LIST">
      <thead>
        <tr>
          <th>File</th>
          <th>Mô tả</th>
          <th>Hashtag</th>
          <th>Người tải lên</th>
          <th>
            <span class="icon-text">
            <span class="mr-5">Chức năng</span>
            <a class="mr-3" @click="excel()">
              <SvgIcon v-bind="{ name: 'excel.png', type: 'black', size: 20 }"></SvgIcon>
            </a>
            <a v-if="$getEditRights()" @click="importData()">
              <SvgIcon v-bind="{ name: 'upload.svg', type: 'black', size: 20 }"></SvgIcon>
            </a>
            </span>
          </th>
        </tr>
      </thead>
      <tbody>
        <ImageCard 
          v-for="(image, index) in imgInPage" 
          :key="image.id" 
          v-bind="{ image, index, layoutMode, loadImages, deleteImage, viewImage }"
        />
      </tbody>
    </template>
    <ImageCard 
      v-else
      v-for="(image, index) in imgInPage" 
      :key="image.id" 
      v-bind="{ image, index: index + perPage * (currentPage - 1), layoutMode, loadImages, deleteImage, viewImage }"
    />
  </component>
  <ImageLayoutPagination v-bind="{ imgshow, currentPage, perPage, onChangePage }" />
  <!-- Modal xem ảnh lớn -->
  <div v-if="typeof activeImageIndex === 'number'" class="modal is-active">
    <div class="modal-background" @click="closeViewImage"></div>
    <div 
      class="modal-content" 
      style="width: 90vw; height: 90vh; border-radius: 8px; overflow: hidden"
    >
      <div 
        class="is-flex h-full"
        style="transition: all 0.3s ease-out"
        :style="`transform: translateX(${-100 * activeImageIndex}%)`"
      >
        <div
          v-for="image in imgshow"
          :key="image.id"
          class="has-background-black is-flex is-justify-content-center is-align-items-center is-flex-grow-0 is-flex-shrink-0"
          style="flex-basis: 100%"
        >
          <nuxt-img
            loading="lazy"
            class="h-full"
            :src="`${$getpath()}static/files/${image.file__file}`"
            :alt="image.file__name"
            style="object-fit: contain"
          />
        </div>
      </div>
      <div class="gallery-arrows">
        <button 
          @click="showPrevImage()"
          class="button is-rounded"
          style="left: 24px"
        >
          <SvgIcon v-bind="{ name: 'left1.svg', type: 'black', size: 20 }" />
        </button>
        <button
          @click="showNextImage()"
          class="button is-rounded"
          style="right: 24px"
        >
          <SvgIcon v-bind="{ name: 'right.svg', type: 'black', size: 20 }" />
        </button>
      </div>
      <div class="gallery-count">
        {{ activeImageIndex + 1 }}
        /
        {{ imgshow.length }}
      </div>
    </div>
    <button
      class="modal-close is-large"
      aria-label="close"
      @click="closeViewImage"
    ></button>
  </div>
  <Modal @dataevent="dataevent" @close="showmodal=undefined" v-bind="showmodal" v-if="showmodal" />
</template>
<script setup>
import { ref } from "vue";
import { debounce } from 'es-toolkit';
import { useNuxtApp } from "#app";
import FileUpload from "@/components/media/FileUpload.vue";
import ImageCard from '@/components/media/ImageCard.vue';
import ImageLayoutPagination from '@/components/media/ImageLayoutPagination.vue';

// pass only projectId for project images, pass both for product images
const props = defineProps({
  productId: String,
  projectId: String,
})

const { dealer } = useStore();
const {
  $snackbar,
  $getdata,
  $insertapi,
  $deleteapi,
  $findapi,
  $getapi,
  $dayjs,
  $unique
} = useNuxtApp();

const layoutModes = { GRID: 'grid', LIST: 'list' };
const layoutMode = ref(layoutModes.GRID);

const convertToWebp = ref(false);
const webpQuality = ref(80);

const project = await $getdata('project', { id: props.projectId }, undefined, true);
const images = ref([]);
const isForProduct = computed(() => props.productId !== undefined);
const product = isForProduct.value ? await $getdata("product", { id: props.productId }, undefined, true) : undefined;
const showmodal = ref()
const imgshow = ref([])
const hashtag = ref()
const current = ref()

const perPage = 24;
const currentPage = ref(1);
watch(imgshow, () => currentPage.value = 1);
const imgInPage = computed(() => {
  const start = (currentPage.value - 1) * perPage;
  return imgshow.value.slice(start, start + perPage);
});

function onChangePage(page) {
  currentPage.value = page;
}

async function loadImages() {
  const values = "id,file__hashtag,file__code,file,create_time,file__code,file__type,file__doc_type,file__name,file__file,file__size,file__caption,file__user__fullname,";
  
  const projectImages = await $getdata("projectfile", undefined, {
    filter: { project: project.id, file__type: 2 },
    values: values + 'project',
    sort: "-create_time"
  });
  
  if (isForProduct.value) {
    const productImages = await $getdata("productfile", undefined, {
      filter: { product: props.productId, file__type: 2 },
      values: values + 'product',
      sort: "-create_time"
    });

    const sameTemplateImages = projectImages.filter(img => img.file__name.startsWith(product.template_name));
    images.value = [...productImages, ...sameTemplateImages];
  }
  else {
    images.value = projectImages;
  }
  imgshow.value = [...images.value]
  hashtag.value = $unique(images.value.filter(v=>v.file__hashtag), ["file__hashtag"])
  hashtag.value.map(v=>v.count = images.value.filter(x=>x.file__hashtag===v.file__hashtag).length)
}

const handleKeyDown = debounce((e) => {
  if (e.key === 'Escape') closeViewImage();
  if (e.key === 'ArrowLeft') showPrevImage();
  if (e.key === 'ArrowRight') showNextImage();
}, 100);

onMounted(() => {
  loadImages();
  window.addEventListener('keydown', handleKeyDown);
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown);
})

async function attachFiles(files) {
  if (!project) return 0;
  
  const payload = files.map((file) => ({
    file: file.id,
    project: isForProduct.value ? undefined : project.id,
    product: isForProduct.value ? product.id : undefined
  }));

  const result = await $insertapi(isForProduct.value ? "productfile" : "projectfile", payload);
  if (result === "error") {
    throw new Error("Không thể liên kết tệp");
  }
  return payload.length;
}

async function onUploaded(uploadedFiles) {
  if (!Array.isArray(uploadedFiles) || uploadedFiles.length === 0) return;

  try {
    const attachedCount = await attachFiles(uploadedFiles);

    if (attachedCount > 0) {
      loadImages();
      $snackbar(`Đã thêm ${attachedCount} ảnh thành công`, "Thành công", "Success");
    }
  } catch (error) {
    console.error("Error attaching images:", error);
    $snackbar("Không thể thêm ảnh, vui lòng thử lại", "Lỗi", "Error");
  }
}

async function deleteImage(image) {
  try {
    await $deleteapi(isForProduct.value ? "productfile" : "projectfile", image.id);
    await $deleteapi("file", image.file);
    loadImages();
    $snackbar("Đã xóa ảnh thành công", "Thành công", "Success");
  } catch (error) {
    console.error("Error deleting image:", error);
    $snackbar("Xóa ảnh không thành công", "Lỗi", "Error");
  }
}

async function excel() {
  const found = $findapi('exportcsv')
  found.params =  {}
  let fields = [{name: 'code', label: 'code'}, {name: 'name', label: 'name'}, {name: 'caption', label: 'caption'}, {name: 'hashtag', label: 'hashtag'}]
  found.params.fields = JSON.stringify(fields)
  found.url = 'exportcsv/File/'
  found.params.filter = {code__in: images.value.map(v=>v.file__code)}
  const rs = await $getapi([found])
  if(rs === 'error') return $snackbar('Đã xảy ra lỗi. Vui lòng thử lại.')
  const url = window.URL.createObjectURL(new Blob([rs[0].data]))
  const link = document.createElement('a')
  const fileName = `${$dayjs(new Date()).format('YYYYMMDDhhmmss')}-data.csv`
  link.href = url
  link.setAttribute('download', fileName)
  document.body.appendChild(link)
  link.click()
  link.remove()
}

function importData() {
  showmodal.value = {"title":"Nhập bút toán theo lô","vbind":{"code":"file-import"},
    "width":"90%","height":"500px","component":"parameter/ImportData"}
}

function refreshShow(tag) {
  if(current.value===tag.file__hashtag) {
    imgshow.value = [...images.value]
    current.value = null
    return
  }
  imgshow.value = images.value.filter(v=>v.file__hashtag===tag.file__hashtag)
  current.value = tag.file__hashtag
}

// State cho xem ảnh lớn
const activeImageIndex = ref(null);

function viewImage(index) {
  activeImageIndex.value = index;
}

function showNextImage() {
  activeImageIndex.value = (activeImageIndex.value + 1) % imgshow.value.length;
}

function showPrevImage() {
  activeImageIndex.value = (activeImageIndex.value - 1 + imgshow.value.length) % imgshow.value.length;
}

function closeViewImage() {
  activeImageIndex.value = null;
}

watch(activeImageIndex, (val) => {
  if (typeof val === 'number') 
    document.documentElement.classList.add('is-clipped');
  else 
    document.documentElement.classList.remove('is-clipped');
})
</script>
<style scoped>
.gallery-arrows {
  > * {
    position: absolute;
    top: 50%;
    background-color: rgba(255, 255, 255, 0.6);
    padding: 0.5rem;
    border: none;
    box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.2);

    &:hover {
      background-color: rgba(255, 255, 255, 0.9);
    }
  }
}

.gallery-count {
  position: absolute;
  bottom: 24px;
  left: 0; 
  right: 0; 
  width: fit-content;
  margin-inline: auto;

  padding: 4px 12px;
  border-radius: 9999px;
  color: white;
  background-color: rgba(0, 0, 0, 0.5);
  font-size: 0.85rem;
}
</style>