<template>
  <v-carousel
    eager
    :show-arrows="mediaItems && mediaItems.length > 1"
    v-if="!isConverting"
    :height="height || 400"
  >
    <template v-for="(item, idx) in mediaItems" :key="idx">
      <!-- IMAGE -->
      <v-carousel-item v-if="item.type === 'image'">
        <v-img
          :src="item.url"
          class="cursor-pointer"
          cover
          height="100%"
          @click.stop="openMediaDialog(item.url)"
        >
          <template #placeholder>
            <v-skeleton-loader height="100%" width="100%" />
          </template>
        </v-img>

        <div class="edit-btn mb-5" v-if="imgEditable">
          <v-btn
            color="primary"
            height="42px"
            width="100px"
            @click.stop="onMediaEdit(item.url, idx)"
          >
            Edit
          </v-btn>
        </div>

        <div class="delete-btn mb-3" v-if="imgDelete">
          <v-btn
            color="red"
            height="42px"
            width="100px"
            @click.stop="onMediaDelete(item.url)"
          >
            Delete
          </v-btn>
        </div>
      </v-carousel-item>

      <!-- VIDEO -->
      <v-carousel-item v-else-if="item.type === 'video'">
        <div
          class="media-fill cursor-pointer"
          @click.stop="openMediaDialog(item.url)"
        >
          <video class="media-video" muted playsinline preload="metadata">
            <source :src="item.url" />
          </video>
          <div class="play-overlay">
            <v-btn class="play-btn" icon size="55" color="primary">
              <v-icon icon="mdi-play" size="40" />
            </v-btn>
          </div>

          <div class="delete-btn pb-4" v-if="imgDelete">
            <v-btn
              color="red"
              height="42px"
              width="100px"
              @click.stop="onMediaDelete(item.url)"
            >
              Delete
            </v-btn>
          </div>
        </div>
      </v-carousel-item>

      <!-- DOCUMENT -->
      <v-carousel-item v-else>
        <div
          class="media-fill d-flex flex-column align-center justify-center cursor-pointer"
          @click.stop="
            downloadFile({ name: item.name, url: item.url, type: item.type })
          "
        >
          <v-icon
            :icon="getFileIcon(item.type)"
            size="150"
            :color="getFileIconColor(getFileIcon(item.type))"
          />
          <div class="text-h6 text-center text-wrap mt-2">{{ item.name }}</div>

          <div class="delete-btn pb-4" v-if="imgDelete">
            <v-btn
              color="red"
              height="42px"
              width="100px"
              @click.stop="onMediaDelete(item.url)"
            >
              Delete
            </v-btn>
          </div>
        </div>
      </v-carousel-item>
    </template>
  </v-carousel>

  <v-skeleton-loader height="400px" width="100%" v-else />

  <!-- Dialog for fullscreen view -->
  <v-dialog v-model="isDialogOpen" max-width="700">
    <v-card>
      <v-btn icon class="close-btn" @click="isDialogOpen = false">
        <v-icon icon="mdi-close" size="40" />
      </v-btn>

      <!-- Image preview -->
      <v-img
        v-if="selectedMediaType === 'image'"
        :src="selectedMediaUrl"
        contain
      />

      <!-- Video preview with playback controls -->
      <div
        v-else-if="selectedMediaType === 'video'"
        class="dialog-video-container"
      >
        <video autoplay controls class="full-size-video" @click.stop>
          <source :src="selectedMediaUrl" />
        </video>
      </div>
    </v-card>
  </v-dialog>

  <!-- Image editor component -->
  <DrawImage
    v-if="isShowImageEdit"
    :is-show-dialog="isShowImageEdit"
    :image-url="imageUrl"
    :image-idx="imageIdx"
    @on-submit="onImageSubmitEdit"
    @on-close-dialog="isShowImageEdit = false"
  />
  <Snackbar v-model="messageSnackbar" :text="message" :color="messageColor" />
</template>

<script setup lang="ts">
const { fileToBase64 } = useUtils();

const emit = defineEmits([
  "on-click-carousel",
  "on-file-edit",
  "on-file-delete",
]);

const props = defineProps<{
  height?: string | number;
  urls?: string[];
  clickable?: boolean;
  imgEditable?: boolean;
  dataFiles?: {
    name: string;
    data: File;
    progress: number;
    id?: string;
    url?: string;
    type?: string;
  }[];
  imgDelete?: boolean;
}>();

const isConverting = ref(false);
const isShowImageEdit = ref(false);
const imageUrl = ref();
const imageIdx = ref();
const videoRefs = ref([]);

// Media items with thumbnail property
const mediaItems = ref<
  {
    url: string;
    name: string;
    type: string;
    mimeType?: string;
    thumbnail?: string;
  }[]
>([]);

// Dialog state
const isDialogOpen = ref(false);
const selectedMediaUrl = ref("");
const selectedMediaType = ref<string>("");
const selectedMediaMimeType = ref("");

function getFileType(file: any) {
  return file.type.startsWith("video/")
    ? "video"
    : file.type.startsWith("image/")
    ? "image"
    : file.type;
}

function getMimeType(file: any) {
  return file.type || "application/octet-stream";
}

// Edit functions
const onMediaEdit = (url: string, idx: number) => {
  isShowImageEdit.value = true;
  imageUrl.value = url;
  imageIdx.value = idx;
};

const onMediaDelete = (url: string) => {
  mediaItems.value = mediaItems.value.filter((file) => file.url !== url);
  URL.revokeObjectURL(url);
  emit("on-file-delete", url);
};

const onImageSubmitEdit = (url: string, idx: number) => {
  if (mediaItems.value && mediaItems.value.length > 0) {
    mediaItems.value[idx].url = url;
  }
  isShowImageEdit.value = false;
  emit("on-file-edit", url, idx);
};

// Open dialog for fullscreen view
const openMediaDialog = (url: string) => {
  const mediaItem = mediaItems.value.find((item) => item.url === url);
  if (mediaItem) {
    selectedMediaUrl.value = url;
    selectedMediaType.value = mediaItem.type;
    selectedMediaMimeType.value = mediaItem.mimeType || "";
    isDialogOpen.value = true;
  }
};

async function getMimeFromHead(url: string) {
  const res = await fetch(url);
  if (!res.ok) throw new Error(`HEAD failed: ${res.status}`);
  return res.headers.get("content-type");
}

watchEffect(async (onCleanup) => {
  let isCancelled = false;

  onCleanup(() => {
    isCancelled = true;
  });

  // Local temporary storage
  const newMediaItems: any = [];

  if (props.dataFiles && props.dataFiles.length > 0) {
    isConverting.value = true;

    for (const file of props.dataFiles) {
      try {
        let fileType;
        let mimeType;
        let finalUrl;

        // 1. Process the file data
        if ("type" in file && "size" in file) {
          mimeType = getMimeType(file);
          fileType = getFileType(file);

          if (fileType === "video") {
            finalUrl = URL.createObjectURL(file);
          } else {
            // Awaiting async conversion
            finalUrl = await fileToBase64(file);
          }
        } else {
          finalUrl = file.url;
          fileType = getFileType(file);
          mimeType = getMimeType(file);
        }

        // 2. Check if the watcher was reset during the 'await'
        if (isCancelled) return;

        // 3. Push to LOCAL array, not the reactive .value
        newMediaItems.push({
          url: finalUrl,
          name: file?.name,
          type: fileType,
          mimeType: mimeType,
          thumbnail: undefined,
        });
      } catch (error) {
        console.error("Error processing file:", error);
      }
    }
  } else if (props.urls && props.urls.length > 0) {
    isConverting.value = true;

    for (const url of props.urls) {
      try {
        const mimeType = await getMimeFromHead(url);
        if (isCancelled) return;

        newMediaItems.push({
          url,
          name: "",
          type: mimeType
            ? mimeType.startsWith("image/")
              ? "image"
              : mimeType.startsWith("video/")
              ? "video"
              : mimeType
            : mimeType,
        });
      } catch (error) {
        console.error("Error fetching MIME type:", error);
      }
    }
  }

  // 4. Finalizing state
  if (!isCancelled) {
    isConverting.value = false;
    // Replace the entire array at once to avoid "doubling" or partial updates
    mediaItems.value = newMediaItems;
    console.log("watchEffect mediaItems updated:", mediaItems.value);
  }
});

const getFileIcon = (type: string) => {
  const iconMap: any = {
    "application/pdf": "mdi-file-pdf-box",
    "application/msword": "mdi-file-word-box",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
      "mdi-file-word-box",
    "application/vnd.ms-excel": "mdi-file-excel-box",
    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
      "mdi-file-excel-box",
    "application/vnd.ms-powerpoint": "mdi-file-powerpoint-box",
    "application/vnd.openxmlformats-officedocument.presentationml.presentation":
      "mdi-file-powerpoint-box",
    "text/plain": "mdi-file-document-outline",
    "text/csv": "mdi-file-delimited-outline",
    "application/zip": "mdi-zip-box-outline",
    "application/x-rar-compressed": "mdi-zip-box-outline",
    // Add more mappings as needed
  };

  return iconMap[type] || "mdi-file-outline";
};

function getFileIconColor(icon?: string) {
  if (icon === "mdi-file-pdf-box") return "#F44336"; // Red
  if (icon === "mdi-file-word-box") return "#2196F3"; // Blue
  if (icon === "mdi-file-excel-box" || icon === "mdi-file-delimited-outline")
    return "#4CAF50"; // Green
  if (icon === "mdi-file-powerpoint-box") return "#FF9800"; // Orange
  if (icon === "mdi-zip-box-outline") return "#9C27B0"; // Purple
  return "grey";
}

const message = ref("");
const messageColor = ref("");
const messageSnackbar = ref(false);

function showMessage(msg: string, color: string) {
  message.value = msg;
  messageColor.value = color;
  messageSnackbar.value = true;
}

async function downloadFile({
  name,
  url,
  type,
}: {
  name: string;
  url: string;
  type: string;
}) {
  try {
    const link = document.createElement("a");
    link.href = url;
    if (type == "application/pdf") {
      link.target = "_blank";
    }
    link.rel = "noopener noreferrer";
    link.download = name;

    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);

    URL.revokeObjectURL(url);
  } catch (err) {
    showMessage(err as string, "error");
  }
}

// // Clean up object URLs when component is unmounted
// onBeforeUnmount(() => {
//   // Revoke any object URLs to prevent memory leaks
//   mediaItems.value.forEach((item) => {
//     if (item.type === "video" && item.url && item.url.startsWith("blob:")) {
//       URL.revokeObjectURL(item.url);
//     }
//   });
// });
</script>

<style scoped>
.edit-btn {
  position: absolute;
  bottom: 24%;
  right: 5%;
  z-index: 5;
}

.delete-btn {
  position: absolute;
  bottom: 13%;
  right: 5%;
}

.close-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  background-color: rgba(0, 0, 0, 0.5);
  color: white;
  z-index: 10;
}

.play-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.play-overlay .v-btn {
  pointer-events: auto;
}

.play-btn {
  border-radius: 9999px;
}

.dialog-video-container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  padding: 20px;
}

.full-size-video {
  max-width: 100%;
  max-height: 80vh;
}

.media-fill {
  position: relative;
  width: 100%;
  height: 100%;
}

.media-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
</style>
