import React, { useEffect, useState } from "react";
import "./frontend-style.scss";
import { UrlData } from "@app/models/api";
import CTACard from "@app/components/CTACard/CTACard";
import {
  convertToEasternArabic,
  mapTaxonomyToName,
  renderType,
} from "@app/services/utilities";

import ResultCard from "@app/components/result-card/ResultCard";
import {
  CTACardProps,
  CustomizableCardProps,
  ResultCardProps,
} from "@app/models/components";

import CustomizableCard from "@app/components/customizableCard/CustomizableCard";
import { getFilter, checkUrlDataType } from "@app/services/api";
import InfiniteScroll from "@app/components/InfiniteScroll/InfiniteScroll";
import SkeletonCard from "@app/components/skeleton-card/SkeletonCard";

let frontendData: any;

if (topPostsFrontendData) {
  frontendData = topPostsFrontendData;
} else {
  frontendData = topPostsFrontendWidgetData;
}

function App() {
  const [filteredPosts, setFilteredPosts] = useState<Array<UrlData>>([]);
  const [posts, setPosts] = useState<Array<UrlData>>([]);
  const [isFetching, setIsFetching] = useState(false);
  const skeletonItems = Array.from({ length: 6 }, (_, index) => index + 1);

  const applyFilterLogic = (posts: any[]) => {
    const filterByLanguage = frontendData?.filter?.language ?? "";
    let filterByScope = frontendData?.filter?.scope ?? "";
    return posts.filter((post) => {
      // Check language independently
      const isLanguageValid =
        filterByLanguage === "" || post.language === filterByLanguage;

      // Check scope independently
      const isScopeValid =
        filterByScope.length === 0 ||
        (filterByScope.length === 1 && filterByScope[0] === "") ||
        filterByScope.some((s: any) => s === post.type);
      // Return true only if both conditions are satisfied
      return isLanguageValid && isScopeValid;
    });
  };

  const fetchFilter = async () => {
    const currentFilterID = frontendData?.filter?.filter_id;
    if (!currentFilterID) {
      return;
    }
    let checkUrlDataTypeResp;
    checkUrlDataTypeResp = frontendData?.filter?.filterPosts || [];
    if (!!checkUrlDataTypeResp.length) {
      if (
        frontendData?.filter?.language ||
        frontendData?.filter?.scope?.filter(Boolean).length > 0
      ) {
        const dataResponse = applyFilterLogic(checkUrlDataTypeResp);

        setFilteredPosts(dataResponse);
        setPosts(dataResponse);
      } else {
        setFilteredPosts(checkUrlDataTypeResp);
        setPosts(checkUrlDataTypeResp);
      }
    } else {
      setIsFetching(true);
    }

    const getFilterResp = await getFilter(
      frontendData?.apiKey || "",
      frontendData?.filterID,
      frontendData?.filter?.lastModified || ""
    );

    if (getFilterResp?.error) {
      setIsFetching(false);
      return;
    }

    if (getFilterResp?.status === 304) {
      checkUrlDataTypeResp = frontendData?.filter?.filterPosts || [];
    } else {
      checkUrlDataTypeResp = await checkUrlDataType(
        getFilterResp.data,
        "" //scope
      );
    }

    if (
      frontendData?.filter?.language ||
      frontendData?.filter?.scope?.filter(Boolean).length > 0
    ) {
      const dataResponse = applyFilterLogic(checkUrlDataTypeResp);

      setFilteredPosts(dataResponse);
      setPosts(dataResponse);
    } else {
      setFilteredPosts(checkUrlDataTypeResp);
      setPosts(checkUrlDataTypeResp);
    }

    setIsFetching(false);
  };

  useEffect(() => {
    fetchFilter();
  }, []);

  useEffect(() => {
    let updatedPosts = [...posts];

    updatedPosts = updatedPosts.map((post) => ({
      ...post,
      excluded: frontendData.filter.excluded?.includes(post?.id) ?? false,
      pinned: frontendData.filter.pinned?.includes(post.id) ?? false,
    }));

    setFilteredPosts(updatedPosts);
  }, [frontendData.filter, posts]);

  const shouldDisplay = (prop: string) => {
    return frontendData.display_options.includes(prop);
  };

  const renderCard = (post: UrlData, index: number) => {
    const pinnedPostsArray = frontendData?.filter?.pinned;
    const pinned = pinnedPostsArray?.includes(post?.id) || false;

    const isPostOrCPT =
      post?.type !== "category" &&
      post?.type !== "post_tag" &&
      post?.type !== "page";

    const isPostOrPage = isPostOrCPT || post?.type === "page";

    const hasDate = isPostOrPage && post?.date;
    const date =
      hasDate && post?.language === "ar"
        ? convertToEasternArabic(
            new Date(post.date).toLocaleDateString("ar", {
              day: "2-digit",
              month: "short",
              year: "numeric",
            })
          )
        : hasDate
        ? new Date(post.date).toLocaleDateString("en-GB", {
            day: "2-digit",
            month: "short",
            year: "numeric",
          })
        : "";

    const tags =
      isPostOrCPT && post?.tags
        ? post?.tags.map((tag) => ({
            label: tag.name,
            href: tag.link,
          })) ?? []
        : [];

    const title = (isPostOrCPT ? post?.title : post?.name) ?? "";

    const body = (isPostOrCPT ? post?.excerpt : post?.description) ?? "";

    const category = isPostOrCPT
      ? post?.category[0]
      : mapTaxonomyToName(post?.type);

    let props: CTACardProps | ResultCardProps | null = null;
    const style = frontendData?.results_style || "search_results_card";

    const getVariant = () => {
      if (isPostOrPage && !pinned) {
        return "PRIMARY";
      } else if (isPostOrPage && pinned) {
        return "PRIMARY_VERTICAL";
      } else if (!isPostOrPage && !pinned) {
        return "SECONDARY";
      } else if (!isPostOrPage && pinned) {
        return "TERTIARY";
      }
    };

    if (style === "fancy_card") {
      props = {
        variant: getVariant(),
        imageSrc: shouldDisplay("image") ? post?.image : "",
        title,
        tag: shouldDisplay("category") ? category : "",
        meta: shouldDisplay("date") ? date : "",
        description: shouldDisplay("excerpt") ? body : "",
        rtl: post.language == "ar" ? true : false,
        onClick: () => post?.url && window.open(post?.url, "_self"),
        type: shouldDisplay("type") ? renderType(post) : "",
        lazyLoad: index > 2,
        showImage: shouldDisplay("image"),
      } satisfies CTACardProps;
    } else if (style === "search_results_card") {
      props = {
        image: shouldDisplay("image") ? post?.image : "",
        href: post?.url,
        tags: shouldDisplay("tag") ? tags : [],
        body: shouldDisplay("excerpt") ? body : "",
        title,
        category: shouldDisplay("category") ? category : "",
        date: shouldDisplay("date") ? date : "",
        rtl: post.language == "ar" ? true : false,
        type: shouldDisplay("type") ? renderType(post) : "",
        lazyLoad: index > 2,
      } satisfies ResultCardProps;
    } else if (style === "customizable_card") {
      props = {
        image: shouldDisplay("image") ? post?.image : "",
        href: post?.url,
        tags: shouldDisplay("tag") ? tags : [],
        body: shouldDisplay("excerpt") ? body : "",
        title,
        category: shouldDisplay("category") ? category : "",
        date: shouldDisplay("date") ? date : "",
        rtl: post.language == "ar" ? true : false,
        type: shouldDisplay("type") ? renderType(post) : "",
        lazyLoad: index > 2,
      } satisfies CustomizableCardProps;
    }
    return (
      <div key={`${post.id}-${index}`} className="topPostsFrontend-gridItem">
        {style === "fancy_card" ? (
          <CTACard {...(props as CTACardProps)} />
        ) : style === "search_results_card" ? (
          <ResultCard {...(props as ResultCardProps)} />
        ) : style === "customizable_card" ? (
          <CustomizableCard
            {...(props as CustomizableCardProps)}
            styling={frontendData?.custom_styles}
          />
        ) : null}
      </div>
    );
  };

  const excludedPostsArray = frontendData?.filter?.excluded;

  const seenIds = new Set();
  let finalFilteredPosts = filteredPosts
    .filter((item) => {
      const isDuplicate = seenIds.has(item.id);
      seenIds.add(item.id);
      return !isDuplicate;
    })
    .filter(
      (post: any) => !post.excluded && !excludedPostsArray?.includes(post.id)
    )
    .sort((a: any, b: any) => {
      const pinnedPostsArray = frontendData?.filter?.pinned;
      if (
        pinnedPostsArray?.includes(a.id) &&
        !pinnedPostsArray?.includes(b.id)
      ) {
        return -1; // a should come before b
      } else if (
        !pinnedPostsArray?.includes(a.id) &&
        pinnedPostsArray?.includes(b.id)
      ) {
        return 1; // b should come before a
      } else {
        return 0; // maintain existing order
      }
    });

  if (parseInt(frontendData.limit) != 0) {
    finalFilteredPosts = finalFilteredPosts.slice(0, frontendData.limit);
  } else {
    finalFilteredPosts = finalFilteredPosts.slice(
      0,
      frontendData?.filter?.limit
    );
  }

  let gridTemplateColumn = "";
  for (let i = 0; i < frontendData.columns_number; i++) {
    gridTemplateColumn += "1fr ";
  }

  return (
    <div className="topPostsFrontend">
      <div
        className="topPostsFrontend-postsGrid--inner"
        style={
          gridTemplateColumn
            ? {
                gridTemplateColumns: `${gridTemplateColumn}`,
                maxWidth: "none",
              }
            : {}
        }
      >
        {isFetching &&
          skeletonItems.map((item) => (
            <div key={item}>
              <SkeletonCard variant={frontendData?.results_style} />
            </div>
          ))}

        {!!finalFilteredPosts.length && (
          <InfiniteScroll
            items={finalFilteredPosts}
            itemsToShow={20}
            renderItem={renderCard}
          />
        )}
      </div>
    </div>
  );
}

export default App;
