<template>
  <li>
    <h2>{{ props.item.title }}</h2>
    <time class="createdBy" datetime="{{item.startDate.datetime}}">{{
      props.item?.startDate
        ? localizeDateTimeFormat(props.item?.startDate, "text")
        : ""
    }}</time>
    <div class="content" v-if="shouldTruncate(item.content)">
      <div v-html="prepareContent(item.content)"></div>
      <div class="float-end">
        <button
          class="btn btn-sm btn-show read-more"
          @click="() => openModal(item)"
        >
          {{ $t("widget.news.readMore") }}
        </button>
      </div>
    </div>
    <div class="content" v-else>
      <div v-html="convertMarkdownToHtml(item.content)"></div>
    </div>

    <modal v-if="showModal" @close="closeModal">
      <template #header>
        <p class="news-title">{{ item.title }}</p>
      </template>
      <template #body>
        <p class="news-date">
          <time class="createdBy" datetime="{{item.startDate.datetime}}">{{
            props.item?.startDate
              ? localizeDateTimeFormat(props.item?.startDate, "text")
              : ""
          }}</time>
        </p>
        <div v-html="convertMarkdownToHtml(item.content)"></div>
      </template>
    </modal>
  </li>
</template>

<script setup lang="ts">
import Modal from "ChillMainAssets/vuejs/_components/Modal.vue";
import { marked } from "marked";
import DOMPurify from "dompurify";
import { NewsItemType } from "../../../types";
import type { PropType } from "vue";
import { ref } from "vue";
import { localizeDateTimeFormat } from "ChillMainAssets/lib/localizationHelper/localizationHelper";

const props = defineProps({
  item: {
    type: Object as PropType<NewsItemType>,
    required: true,
  },
  maxLength: {
    type: Number,
    required: false,
    default: 350,
  },
  maxLines: {
    type: Number,
    required: false,
    default: 3,
  },
});

const selectedArticle = ref<NewsItemType | null>(null);
const showModal = ref(false);

const openModal = (item: NewsItemType) => {
  selectedArticle.value = item;
  showModal.value = true;
};

const closeModal = () => {
  selectedArticle.value = null;
  showModal.value = false;
};

const shouldTruncate = (content: string): boolean => {
  const lines = content.split("\n");

  // Check if any line exceeds the maximum length
  const tooManyLines = lines.length > props.maxLines;

  return content.length > props.maxLength || tooManyLines;
};

const truncateContent = (content: string): string => {
  let truncatedContent = content.slice(0, props.maxLength);
  let linkDepth = 0;
  let linkStartIndex = -1;
  const lines = content.split("\n");

  // Truncate if amount of lines are too many
  if (lines.length > props.maxLines && content.length < props.maxLength) {
    const truncatedContent = lines.slice(0, props.maxLines).join("\n").trim();
    return truncatedContent + "...";
  }

  for (let i = 0; i < truncatedContent.length; i++) {
    const char = truncatedContent[i];

    if (char === "[") {
      linkDepth++;
      if (linkDepth === 1) {
        linkStartIndex = i;
      }
    } else if (char === "]") {
      linkDepth = Math.max(0, linkDepth - 1);
    } else if (char === "(" && linkDepth === 0) {
      truncatedContent = truncatedContent.slice(0, i);
      break;
    }
  }

  while (linkDepth > 0) {
    truncatedContent += "]";
    linkDepth--;
  }

  // If a link was found, append the URL inside the parentheses
  if (linkStartIndex !== -1) {
    const linkEndIndex = content.indexOf(")", linkStartIndex);
    const url = content.slice(linkStartIndex + 1, linkEndIndex);
    truncatedContent = truncatedContent.slice(0, linkStartIndex) + `(${url})`;
  }

  truncatedContent += "...";

  return truncatedContent;
};

const preprocess = (markdown: string): string => {
  return markdown;
};

const postprocess = (html: string): string => {
  DOMPurify.addHook("afterSanitizeAttributes", (node: Element) => {
    if ("target" in node) {
      node.setAttribute("target", "_blank");
      node.setAttribute("rel", "noopener noreferrer");
    }
    if (
      !node.hasAttribute("target") &&
      (node.hasAttribute("xlink:href") || node.hasAttribute("href"))
    ) {
      node.setAttribute("xlink:show", "new");
    }
  });

  return DOMPurify.sanitize(html);
};

const convertMarkdownToHtml = (markdown: string): string => {
  marked.use({ hooks: { postprocess, preprocess }, async: false });
  const rawHtml = marked(markdown) as string;
  return rawHtml;
};

const prepareContent = (content: string): string => {
  const htmlContent = convertMarkdownToHtml(content);
  return truncateContent(htmlContent);
};
</script>

<style scoped>
li {
  margin-bottom: 20px;
  overflow: hidden;
  padding: 0.8rem;
  background-color: #fbfbfb;
  border-radius: 4px;
}

h2 {
  font-size: 1rem !important;
  text-transform: uppercase;
}

.content {
  overflow: hidden;
  font-size: 0.9rem;
  position: relative;
}

.news-title {
  font-weight: bold;
}
</style>
