"use client";

import Image from "next/image";
import { FaEnvelope, FaLinkedin } from "react-icons/fa6";
import { Card, CardBody, CardHeader, Chip, Divider } from "@nextui-org/react";
import React, { useCallback, useMemo, useRef, useState } from "react";
import DOMPurify from "isomorphic-dompurify";
import parse, { domToReact } from "html-react-parser";
import Link from "next/link";
import {
  FcCalendar,
  FcClock,
  FcCollaboration,
  FcGlobe,
  FcMoneyTransfer,
  FcReading,
} from "react-icons/fc";
import {
  useParams,
  usePathname,
  useRouter,
  useSearchParams,
} from "next/navigation";

import { Opportunity } from "@/types/opportunities/opportunity-types";
import Button from "@/components/common/button";
import { Options } from "@/types/options/options-data-types";
import { formatIncentives } from "@/utils/format-incentive";
import { FRIENDLY_TOPICS_ICONS } from "@/utils/opportunities/job-topic-icons";
import { formatDateRange } from "@/components/pages/participant/opportunities/other-utils";
import { INTERNAL_PAGES } from "@/constants/pages-mapping/internal-pages-mapping";
import useStickyCTA from "@/hooks/useStickyCTA";

type ParsedOpportunity = {
  currency: string | string[];
  typeOfStudy: string[];
  paymentMethods: string[];
  jobTopic: string;
  formatOfResearch: string[];
};

type CampaignInitialScreenProps = {
  opportunity: Opportunity;
  parsedOpportunity: ParsedOpportunity;
  currencyOptions: Options;
  jobId: number;
};

function CampaignInitialScreen({
  opportunity,
  parsedOpportunity,
  currencyOptions,
  jobId,
}: CampaignInitialScreenProps) {
  const ctaRef = useRef<HTMLDivElement | null>(null);
  const router = useRouter();
  const pathname = usePathname();
  const { slug } = useParams();
  const searchParams = useSearchParams();
  const queryString = searchParams.toString();
  const BASE_URL = process.env.NEXT_PUBLIC_PFR_WEBSITE_BASE_URL_CAMPAIGNS_ONLY;
  const [loadingButton, setLoadingButton] = useState<string | null>(null);
  const { isModerated } = opportunity.jobInformation;
  const isUnmoderated = !isModerated;

  const {
    title,
    durationText,
    location,
    startDate,
    description,
    incentives,
    thumbnail,
    hideLocation,
    startingTime,
    endingTime,
    altTextThumbnail,
  } = opportunity;

  const { endDate } = opportunity.jobInformation;
  const dateRange = formatDateRange("long", startDate, endDate, true);
  const formattedStart =
    typeof dateRange === "string" ? dateRange : dateRange.formattedStart;
  const formattedEnd =
    typeof dateRange === "string" ? dateRange : dateRange.formattedEnd;

  const { typeOfStudy, jobTopic, formatOfResearch, paymentMethods } =
    parsedOpportunity;

  const formatTime = useCallback((timeString: string) => {
    const [hour, minute] = timeString.split(":");
    return `${hour}:${minute}`;
  }, []);

  const cities =
    (location !== null &&
      location.split(/,|&/).map((location) => location.trim())) ||
    [];

  const displayCity =
    !location || hideLocation
      ? "To be confirmed"
      : cities.length > 2
        ? `${cities.slice(0, -1).join(", ")} and ${cities[cities.length - 1]}`
        : cities.length === 2
          ? `${cities[0]} and ${cities[1]}`
          : cities[0];

  const GRID_ITEMS = useMemo(
    () => [
      {
        icon: FcGlobe,
        title: "Location",
        value:
          displayCity === "To be confirmed"
            ? "To be confirmed."
            : `${displayCity}.`,
      },
      {
        icon: FcCalendar,
        title: "Date & time",
        value: isUnmoderated
          ? formattedStart === formattedEnd
            ? `${formattedStart}.`
            : `${formattedStart} to ${formattedEnd}.`
          : formattedStart === formattedEnd
            ? `${formattedStart}${
                startingTime && endingTime
                  ? `, between ${formatTime(startingTime)} and ${formatTime(
                      endingTime,
                    )}`
                  : ""
              }.`
            : `${formattedStart} to ${formattedEnd}${
                startingTime && endingTime
                  ? `, between ${formatTime(startingTime)} and ${formatTime(
                      endingTime,
                    )}`
                  : ""
              }.`,
      },
      {
        icon: FcClock,
        title: "Duration of the study",
        value:
          durationText && durationText.endsWith(".")
            ? durationText
            : `${durationText}.`,
      },
      {
        icon: FcMoneyTransfer,
        title: "Incentive",
        value:
          incentives.length > 0
            ? `${formatIncentives(
                incentives,
                currencyOptions,
                true,
              )} ${paymentMethods
                .map((paymentMethod) => paymentMethod)
                .join(", ")
                .toLowerCase()}.`
            : "To be confirmed.",
      },
      {
        icon: FcReading,
        title: "Study format",
        value:
          typeOfStudy && typeOfStudy.length > 0
            ? `${
                typeOfStudy.length === 1
                  ? typeOfStudy[0].charAt(0).toUpperCase() +
                    typeOfStudy[0].slice(1).toLowerCase()
                  : typeOfStudy[0].charAt(0).toUpperCase() +
                    typeOfStudy[0].slice(1).toLowerCase() +
                    (typeOfStudy.length > 1
                      ? ", " +
                        typeOfStudy
                          .slice(1, -1)
                          .map((format) => format.toLowerCase())
                          .join(", ") +
                        (typeOfStudy.length > 2 ? ", " : " ") +
                        "and " +
                        typeOfStudy[typeOfStudy.length - 1].toLowerCase()
                      : "")
              }.`
            : "Not available.",
      },
      {
        icon: FcCollaboration,
        title: "Format of research",
        value:
          formatOfResearch && formatOfResearch.length > 0
            ? `${
                formatOfResearch.length === 1
                  ? formatOfResearch[0].charAt(0).toUpperCase() +
                    formatOfResearch[0].slice(1).toLowerCase()
                  : formatOfResearch[0].charAt(0).toUpperCase() +
                    formatOfResearch[0].slice(1).toLowerCase() +
                    (formatOfResearch.length > 1
                      ? ", " +
                        formatOfResearch
                          .slice(1, -1)
                          .map((format) => format.toLowerCase())
                          .join(", ") +
                        (formatOfResearch.length > 2 ? ", " : " ") +
                        "and " +
                        formatOfResearch[
                          formatOfResearch.length - 1
                        ].toLowerCase()
                      : "")
              }.`
            : "Not available.",
      },
    ],
    [
      displayCity,
      isUnmoderated,
      formattedStart,
      formattedEnd,
      startingTime,
      endingTime,
      formatTime,
      durationText,
      incentives,
      currencyOptions,
      paymentMethods,
      typeOfStudy,
      formatOfResearch,
    ],
  );

  const sanitizedDescription = DOMPurify.sanitize(description, {
    ADD_TAGS: ["a", "ol", "li", "ul", "span", "h2", "h3"],
  });

  const liContent = (domNode: any, options: any) => {
    const children = domNode.children || [];

    if (children.length === 1 && children[0].name === "p") {
      return domToReact(children[0].children, options);
    }
    return domToReact(children, options);
  };

  const renderOrderedList = (domNode: any, options: any) => {
    return (
      <ol className="list-decimal list-inside ms-6">
        {domToReact(domNode.children, options)}
      </ol>
    );
  };

  const renderUnorderedList = (domNode: any, options: any) => {
    return (
      <ul className="list-disc list-inside ms-6">
        {domToReact(domNode.children, options)}
      </ul>
    );
  };

  const renderListItem = (domNode: any, options: any) => {
    return <li className="mb-0">{liContent(domNode, options)}</li>;
  };

  const renderAnchor = (domNode: any, options: any) => {
    const url = new URL(domNode.attribs.href);
    url.searchParams.delete("ref");

    return (
      <Link
        className="font-semibold underline decoration-dotted"
        href={url.toString()}
        rel="noopener noreferrer"
        target="_blank"
      >
        {domToReact(domNode.children, options)}
      </Link>
    );
  };

  const options = {
    replace: (domNode: any) => {
      if (!domNode.name) return;

      switch (domNode.name) {
        case "hr":
          return (
            <Divider className="my-4 border-gray-300 dark:border-gray-500" />
          );
        case "a":
          return renderAnchor(domNode, options);
        case "ol":
          return renderOrderedList(domNode, options);
        case "ul":
          return renderUnorderedList(domNode, options);
        case "li":
          return renderListItem(domNode, options);
        case "h2":
          return (
            <h2 className="text-xl font-bold mt-4 mb-1 font-inter">
              {domToReact(domNode.children, options)}
            </h2>
          );
        case "h3":
          return (
            <h3 className="text-lg font-semibold mt-3 mb-1 font-inter">
              {domToReact(domNode.children, options)}
            </h3>
          );
        case "p":
          if (!domNode.children || domNode.children.length === 0) return null;

          return (
            <p className="my-2">{domToReact(domNode.children, options)}</p>
          );
        case "span":
          if (domNode.attribs?.["data-type"] === "emoji") {
            return <span>{domNode.children?.[0]?.data}</span>;
          }
          break;
      }
    },
  };

  const hrefCoookies = `${BASE_URL}${INTERNAL_PAGES.participant.howItWorks.policies}/cookies-policy`;
  const hrefTerms = `${BASE_URL}${INTERNAL_PAGES.participant.howItWorks.policies}/general-terms-and-contact-details`;

  const handleContinue = (selection: string) => {
    setLoadingButton(selection);
    if (selection === "linkedin") {
      handleLinkedInAuth();
    } else {
      const params = new URLSearchParams(queryString);
      params.set("jobIdRef", jobId.toString());

      router.push(
        `${INTERNAL_PAGES.participant.campaign}/${slug}/signup?${params.toString()}`,
      );
    }
  };

  const handleLinkedInAuth = () => {
    const params = new URLSearchParams(queryString);
    params.set("jobIdRef", jobId.toString());

    const state = encodeURIComponent(
      JSON.stringify({
        returnTo: `${pathname}?${params.toString()}`,
      }),
    );

    const linkedinAuthUrl = `https://www.linkedin.com/oauth/v2/authorization?${new URLSearchParams(
      {
        response_type: "code",
        client_id: process.env.NEXT_PUBLIC_LINKEDIN_CLIENT_ID!,
        redirect_uri: `${BASE_URL}${INTERNAL_PAGES.participant.linkedInCallback}`,
        scope: "openid profile email",
        state,
      },
    )}`;
    window.location.href = linkedinAuthUrl;
  };

  const showStickyCTA = useStickyCTA(ctaRef);

  // Note: This can be removed in a near future!
  // It's aimed to help the transition of opps with no markup yet
  const prepareDescription = (text: string) => {
    const trimmedText = text.trim();
    const singleParagraphMatch = /^<p>([\s\S]*)<\/p>$/i.test(trimmedText);

    if (singleParagraphMatch) {
      const unwrapped = trimmedText.replace(/^<p>|<\/p>$/gi, "").trim();
      const hasOtherBlockTags =
        /<\/?(?:p|div|section|article|h[1-6]|ul|ol|li|blockquote)[\s\S]*?>/i.test(
          unwrapped,
        );

      if (!hasOtherBlockTags) {
        const sentences = unwrapped.split(/\.\s+(?=[A-Z])/);

        const paragraphs: string[] = [];
        let currentParagraph = "";

        sentences.forEach((sentence, index) => {
          const sentenceWithPeriod =
            sentence.endsWith(".") ||
            sentence.endsWith(".)") ||
            sentence.endsWith(".</a>")
              ? sentence
              : sentence + ".";

          currentParagraph +=
            (currentParagraph ? " " : "") + sentenceWithPeriod;

          const sentenceCount = currentParagraph.split(/\.\s+/).length;
          if (
            sentenceCount >= 3 ||
            currentParagraph.length > 250 ||
            index === sentences.length - 1
          ) {
            paragraphs.push(currentParagraph.trim());
            currentParagraph = "";
          }
        });

        return paragraphs
          .filter((p) => p.length > 0)
          .map((p) => `<p>${p}</p>`)
          .join("");
      }
    }

    const hasBlockTags =
      /<\/?(?:p|div|section|article|h[1-6]|ul|ol|li|blockquote)[\s\S]*?>/i.test(
        trimmedText,
      );

    if (hasBlockTags) {
      return trimmedText;
    }

    return trimmedText
      .split(/\n\s*\n|\r?\n/)
      .filter((p) => p.trim().length > 0)
      .map((p) => `<p>${p.trim()}</p>`)
      .join("");
  };

  const preparedDescription = prepareDescription(sanitizedDescription);

  return (
    <div className="flex items-center justify-center p-0 sm:p-10 m-auto relative">
      <div className="relative z-10 container mx-auto sm:px-4 sm:py-8 flex flex-col items-center justify-center min-h-screen mt-0">
        <div className="relative w-full max-w-4xl">
          <Card className="shadow border-0 p-0 rounded-none sm:rounded-3xl text-gray-900 dark:text-gray-100 overflow-hidden">
            <CardHeader className="relative w-full h-64">
              <Image
                fill
                priority
                alt={altTextThumbnail || ""}
                className="object-cover"
                src={`data:image/png;base64,${thumbnail}`}
              />
              <div className="absolute inset-0 bg-gradient-to-b from-black/40 via-black/50 to-black/70" />
              <div className="absolute inset-0 flex flex-col items-center justify-center text-center px-4 sm:px-6 md:px-8">
                <span className="text-xs sm:text-sm text-white/90 font-semibold mb-2 sm:mb-3">
                  You&apos;re invited to participate in
                </span>
                <h1 className="text-3xl sm:text-4xl lg:text-5xl font-black leading-tight text-white max-w-3xl">
                  {title}
                </h1>

                <div className="flex flex-wrap justify-center gap-2 mt-4">
                  <Chip
                    classNames={{
                      content: "font-semibold py-1",
                      base: "bg-white/20 backdrop-blur-sm text-white font-inter font-extrabold text-xs border border-white/30",
                    }}
                    startContent={
                      FRIENDLY_TOPICS_ICONS[
                        jobTopic as keyof typeof FRIENDLY_TOPICS_ICONS
                      ] &&
                      React.createElement(
                        FRIENDLY_TOPICS_ICONS[
                          jobTopic as keyof typeof FRIENDLY_TOPICS_ICONS
                        ],
                        { className: "mx-1" },
                      )
                    }
                  >
                    {jobTopic}
                  </Chip>
                </div>
              </div>
            </CardHeader>

            <div className="p-4 sm:p-6 md:p-8">
              <CardBody className="space-y-4 p-4">
                <article className="font-noto leading-6">
                  {parse(preparedDescription, options)}
                </article>

                <div className="grid grid-cols-2 lg:grid-cols-3 gap-1 mb-8">
                  {GRID_ITEMS.map((item, index) => {
                    const Icon = item.icon;
                    return (
                      <Card
                        key={index}
                        className="shadow-none p-4 rounded light bg-gray-400/10 dark:bg-white/5 space-y-1"
                      >
                        <Icon className="text-3xl text-black" />
                        <h2 className="text-sm font-bold text-gray-800 dark:text-gray-100">
                          {item.title}
                        </h2>
                        <p className="text-xs text-gray-600 dark:text-gray-300">
                          {item.value}
                        </p>
                      </Card>
                    );
                  })}
                </div>
              </CardBody>

              <div
                ref={ctaRef}
                className="flex flex-col justify-center text-black dark:text-white overflow-visible p-3"
              >
                <Button
                  customVariant="linkedin"
                  isDisabled={loadingButton !== null}
                  isLoading={loadingButton === "linkedin"}
                  size="lg"
                  startContent={
                    loadingButton !== "linkedin" && (
                      <FaLinkedin className="w-4 h-4 sm:w-5 sm:h-5" />
                    )
                  }
                  onClick={() => handleContinue("linkedin")}
                >
                  <span className="text-sm sm:text-base">
                    {loadingButton === "linkedin"
                      ? "Redirecting..."
                      : "Continue with LinkedIn"}
                  </span>
                </Button>

                <div className="relative my-4">
                  <div className="absolute inset-0 flex items-center">
                    <div className="w-full border-t border-gray-300 dark:border-gray-700"></div>
                  </div>
                  <div className="relative flex justify-center text-sm">
                    <span className="bg-white dark:bg-zinc-900 px-3 text-gray-500 dark:text-gray-400">
                      or
                    </span>
                  </div>
                </div>

                <Button
                  customVariant="primary"
                  isDisabled={loadingButton !== null}
                  isLoading={loadingButton === "email"}
                  size="lg"
                  startContent={
                    loadingButton !== "email" && (
                      <FaEnvelope className="w-4 h-4 sm:w-5 sm:h-5" />
                    )
                  }
                  onClick={() => handleContinue("email")}
                >
                  <span className="text-sm sm:text-base">
                    {loadingButton === "email"
                      ? "Redirecting..."
                      : "Continue with email"}
                  </span>
                </Button>

                <p className="text-xs text-gray-600 dark:text-gray-400 text-center leading-relaxed mt-8">
                  By signing up, you agree to People for Research&apos;s{" "}
                  <Link
                    className="text-black dark:text-blue-400 underline underline-offset-2 decoration-dotted cursor-pointer font-semibold"
                    href={hrefCoookies}
                    rel="noopener noreferrer"
                    target="_blank"
                  >
                    Cookies Policy
                  </Link>{" "}
                  and{" "}
                  <Link
                    className="text-black dark:text-blue-400 underline underline-offset-2 decoration-dotted cursor-pointer font-semibold"
                    href={hrefTerms}
                    rel="noopener noreferrer"
                    target="_blank"
                  >
                    General Terms and Conditions
                  </Link>{" "}
                  .
                </p>
              </div>
            </div>
          </Card>

          {showStickyCTA && (
            <div className="sticky bottom-0 left-0 right-0 pb-1 sm:pb-4 px-4 z-30 backdrop-blur">
              <Button
                className="w-full mb-3"
                customVariant="linkedin"
                isDisabled={loadingButton !== null}
                size="lg"
                startContent={
                  loadingButton !== "linkedin" && (
                    <FaLinkedin className="w-4 h-4 sm:w-5 sm:h-5" />
                  )
                }
                onClick={() => handleContinue("linkedin")}
              >
                <span className="text-sm sm:text-base">
                  {loadingButton === "linkedin"
                    ? "Redirecting..."
                    : "Continue with LinkedIn"}
                </span>
              </Button>

              <Button
                className="w-full"
                customVariant="primary"
                isDisabled={loadingButton !== null}
                isLoading={loadingButton === "email"}
                size="lg"
                startContent={
                  loadingButton !== "email" && (
                    <FaEnvelope className="w-4 h-4 sm:w-5 sm:h-5" />
                  )
                }
                onClick={() => handleContinue("email")}
              >
                <span className="text-sm sm:text-base">
                  {loadingButton === "email"
                    ? "Redirecting..."
                    : "Continue with email"}
                </span>
              </Button>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

export default CampaignInitialScreen;
