import { redirect, notFound } from "next/navigation";

import {
  getCampaignUserSession,
  getLinkedInCallbackData,
} from "@/lib/campaigns-session";
import { INTERNAL_PAGES } from "@/constants/pages-mapping/internal-pages-mapping";
import { retrieveUserSession } from "@/lib/user-session";
import { getOpportunitiesNotLoggedIn } from "@/services/opportunities";
import { CORE_ENDPOINTS } from "@/constants/api-mappings/external-api-mapping";
import { getOptions } from "@/services/general-actions";
import ExpiredOppCampaignScreen from "@/components/pages/participant/campaigns/expired-opp-initial-screen";
import CampaignNotFound from "@/components/pages/participant/campaigns/campaign-not-found";
import CampaignInitialScreen from "@/components/pages/participant/campaigns/initial-screen";
import { getOpportunityByMarketingSlug } from "@/services/participant/campaigns/marketing";
import { parseOpportunity } from "@/utils/opportunities/parse-opportunity";
import OpportunityDetail from "@/components/pages/participant/opportunities/opportunity-detail";
import { PROFESSIONAL_JOB_TOPIC_IDS } from "@/constants/professional-job-topics";

/**
 * Important notes for this flow:
 * The cookies we're going to be using here:
 * COOKIE_CAMPAIGN_AUTH_SESSION: the campaign auth session. Retrieved from the backend (user token)
 * COOKIE_CAMPAIGN_USER_SESSION: the campaign user session. Only stores userId, email and isLoggedIn as false.
 * COOKIE_LINKEDIN_USER_DATA: the LinkedIn user data. Only stores firstName, lastName, email retrieve from the callback.
 * COOKIE_CAMPAIGN_USER_SIGNUP_DATA: Stores the data that user entered in the signup campaign form, in case he needs to refresh the page.
 */

type Params = {
  slug: string;
};

export async function generateMetadata({ params }: { params: Params }) {
  const { slug } = params;
  const opportunityDetails = await getOpportunityByMarketingSlug(slug);

  if (!opportunityDetails) {
    return {
      title: "Opportunity not found",
      description: "This opportunity could not be found.",
    };
  }

  const pageTitle =
    opportunityDetails.title.length > 50
      ? `${opportunityDetails.title.substring(0, 50)}...`
      : opportunityDetails.title;

  const description =
    opportunityDetails.description.length > 150
      ? `${opportunityDetails.description.substring(0, 150)}...`
      : opportunityDetails.description;

  return {
    title: `${pageTitle} | Opportunity details`,
    description,
    openGraph: {
      title: `${pageTitle} | Opportunity details`,
      description,
      type: "website",
    },
    twitter: {
      card: "summary_large_image",
      title: `${pageTitle} | Opportunity details`,
      description,
    },
  };
}

export const dynamic = "force-dynamic";
export const revalidate = 0;

export default async function CampaignHome({
  params,
  searchParams,
}: {
  params: { slug: string };
  searchParams: Record<string, string>;
}) {
  const { slug } = params;
  const { expired, notFound: notFoundParam, full_journey } = searchParams;
  const isFullJourney = full_journey === "true";
  const { utm_source, utm_medium, utm_campaign, utm_content, utm_term } =
    searchParams;

  // this the regular user session - meaning user has logged in normally and receives
  // a campaign link.
  const { isLoggedIn } = (await retrieveUserSession()) || {};

  // Logged-in users are existing community members - they don't need the campaign
  // signup/onboarding flow. Redirect them straight to the opportunity survey,
  // preserving UTM params for attribution tracking.
  if (isLoggedIn) {
    const opportunityDetails = await getOpportunityByMarketingSlug(slug);
    const { jobId } = opportunityDetails || {};

    if (!opportunityDetails) {
      notFound();
    }

    const query = new URLSearchParams(searchParams).toString();
    redirect(
      `${INTERNAL_PAGES.participant.opportunities.main}/${jobId}${query ? `?${query}` : ""}`,
    );
  }

  // note: in this case, it means the LinkedIn auth callback was already called
  // and we have a user in the session.
  const linkedinUser = await getLinkedInCallbackData();

  // if we already have a userId, redirect to the survey, it means the user already signed up successfully and already has a userId.
  const { userId } = (await getCampaignUserSession()) || {};

  if (linkedinUser && !userId) {
    const query = new URLSearchParams(searchParams).toString();
    const target = `${INTERNAL_PAGES.participant.campaign}/${slug}/signup${
      query ? `?${query}` : ""
    }`;
    redirect(target);
  }

  if (userId) {
    const query = new URLSearchParams(searchParams).toString();
    const target = `${INTERNAL_PAGES.participant.campaign}/${slug}/survey${
      query ? `?${query}` : ""
    }`;
    redirect(target);
  }

  const isExpired = expired === "true";
  const isNotFound = notFoundParam === "true";

  const sort: { colId: string; sort: "desc" | "asc" } = {
    colId: "publishDate",
    sort: "desc",
  };

  const filterModel = {
    researchTopic: PROFESSIONAL_JOB_TOPIC_IDS,
  };

  const itemsPerPage = 4;
  const currentPage = 1;

  const opportunities = await getOpportunitiesNotLoggedIn(
    itemsPerPage,
    currentPage,
    sort,
    filterModel,
  );

  const opportunityList = opportunities.data || [];

  const optionEndpoints = [
    CORE_ENDPOINTS.options.currency,
    CORE_ENDPOINTS.options.typeOfStudy,
    CORE_ENDPOINTS.options.paymentMethod,
    CORE_ENDPOINTS.options.jobTopic,
    CORE_ENDPOINTS.options.formatOfResearch,
    CORE_ENDPOINTS.options.employment,
    CORE_ENDPOINTS.options.industry,
    CORE_ENDPOINTS.options.seniority,
  ];

  const [
    currencyOptions,
    typeOfStudyOptions,
    paymentMethodsOptions,
    jobTopicOptions,
    formatOfResearchOptions,
    employmentStatusOptions,
    industryOptions,
    seniorityLevelOptions,
  ] = await Promise.all(
    optionEndpoints.map((endpoint) => getOptions(endpoint)),
  );

  if (isExpired) {
    return (
      <ExpiredOppCampaignScreen
        currencyOptions={currencyOptions}
        listOfOpps={opportunityList}
      />
    );
  }

  if (isNotFound) {
    return (
      <CampaignNotFound
        currencyOptions={currencyOptions}
        listOfOpps={opportunityList}
      />
    );
  }

  const opportunityDetails = await getOpportunityByMarketingSlug(slug);

  if (!opportunityDetails) {
    redirect(`${INTERNAL_PAGES.participant.opportunities.main}`);
  }

  const options = {
    currencyOptions,
    typeOfStudyOptions,
    paymentMethodsOptions,
    jobTopicOptions,
    formatOfResearchOptions,
  };

  const buildParsedOpportunity = parseOpportunity(
    opportunityDetails,
    options.currencyOptions,
    options.typeOfStudyOptions,
    options.paymentMethodsOptions,
    options.jobTopicOptions,
    options.formatOfResearchOptions,
  );

  const { currency, typeOfStudy, paymentMethods, jobTopic, formatOfResearch } =
    buildParsedOpportunity;

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

  const { jobId } = opportunityDetails;

  // this is a temp. fix! Only for the experian job
  const experianJobId = Number(process.env.EXPERIAN_JOB_ID);
  const isExperianJob = Number(jobId) === experianJobId;

  const utmParams = {
    utm_source,
    utm_medium,
    utm_campaign,
    ...(utm_term && { utm_term }), // term is optional.
    ...(utm_content && { utm_content }), // content is optional.
    full_journey: isFullJourney.toString(),
  };

  // Regular full journey for campaign users.
  // These users will see the opportunity details and then go to the regular, longer, signup/survey.
  if (isFullJourney) {
    return (
      <OpportunityDetail
        currencyOptions={currencyOptions}
        employmentOptions={employmentStatusOptions}
        industryOptions={industryOptions}
        isExperianJob={isExperianJob}
        isFullJourney={isFullJourney}
        isLoggedIn={isLoggedIn}
        jobId={jobId}
        opportunity={opportunityDetails}
        parsedOpportunity={parsedOpportunity}
        seniorityOptions={seniorityLevelOptions}
        userId={userId}
        utmParams={utmParams}
      />
    );
  }

  // Fast-lane initial screen for campaign users, like LinkedIn, or others.
  // These users will only see the initial screen and then go to signup/survey.
  // The signup is way simplified for them.
  return (
    <CampaignInitialScreen
      currencyOptions={currencyOptions}
      jobId={jobId}
      opportunity={opportunityDetails}
      parsedOpportunity={parsedOpportunity}
    />
  );
}
