import { notFound } from "next/navigation";

import { parseOpportunity } from "@/utils/opportunities/parse-opportunity";
import { CORE_ENDPOINTS } from "@/constants/api-mappings/external-api-mapping";
import {
  checkIfOpportunityHasExpired,
  getOpportunitiesNotLoggedIn,
  getOpportunityById,
  verifyIfUserAppliedToJob,
} from "@/services/opportunities";
import { getOptions, getProfileData } from "@/services/general-actions";
import { FinancialEmploymentProfileSchema } from "@/types/profile/profile-update-schema";
import OpportunityDetail from "@/components/pages/participant/opportunities/opportunity-detail";
import OpportunityExpired from "@/components/pages/participant/opportunities/opportunity-expired";
import { retrieveUserSession, retrieveUserToken } from "@/lib/user-session";

type Params = Promise<{ id: number }>;

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

  if (!opportunityDetails) {
    return { title: "Opportunity not 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 default async function OpportunityDetails({
  params,
  searchParams,
}: {
  params: Params;
  searchParams: Record<string, string>;
}) {
  const { id: jobId } = await params;

  const [opportunityDetails, isExpired] = await Promise.all([
    getOpportunityById(jobId),
    checkIfOpportunityHasExpired(jobId),
  ]);

  if (!opportunityDetails) {
    notFound();
  }

  if (isExpired) {
    const { title } = opportunityDetails || {};

    const sort: { colId: string; sort: "desc" | "asc" } = {
      colId: "publishDate",
      sort: "desc",
    };
    const filterModel = {};
    const itemsPerPage = 5;
    const maxPage = 3;
    const randomPage = Math.floor(Math.random() * maxPage) + 1;

    const listOfOpportunities = await getOpportunitiesNotLoggedIn(
      itemsPerPage,
      randomPage,
      sort,
      filterModel,
    );

    const opportunityList = (listOfOpportunities.data || [])
      .filter((opp) => opp.jobId !== Number(jobId))
      .slice(0, 4);

    return (
      <OpportunityExpired
        relatedOpportunities={opportunityList}
        title={title}
      />
    );
  }

  const { userId, isLoggedIn, clientId } = (await retrieveUserSession()) || {};
  const userToken = await retrieveUserToken();
  const { utm_source, utm_medium, utm_content } = searchParams;

  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)),
  );

  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 participantData = userToken ? await getProfileData(userToken) : null;

  let userDetails: FinancialEmploymentProfileSchema = {
    financialProductsIds: [],
    seniorityLevelIds: [],
    benefitsIds: [],
    industryId: 0,
    employmentStatusIds: [],
    individualIncomeId: 0,
    occupation: null,
  };

  if (participantData) {
    const { businessInformation, personalInformation } = participantData;

    const {
      financialProductsIds,
      seniorityLevelIds,
      industryId,
      employmentStatusIds,
      incomeBracketId,
      occupation,
    } = businessInformation;

    const { benefitsIds: benefitsIds } = personalInformation;

    userDetails = {
      ...userDetails,
      financialProductsIds,
      seniorityLevelIds,
      benefitsIds: benefitsIds,
      industryId: industryId,
      employmentStatusIds: employmentStatusIds,
      individualIncomeId: incomeBracketId,
      occupation: occupation,
    };
  }

  let hasParticipantApplied = false;

  if (userToken) {
    hasParticipantApplied = await verifyIfUserAppliedToJob(jobId);
  }

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

  // these parameters are required to be stored so they can appear
  // correctly associated with an enrolment on the call list.
  const utmParams = {
    utm_source,
    utm_medium,
    utm_content,
  };

  return (
    <OpportunityDetail
      currencyOptions={currencyOptions}
      employmentOptions={employmentStatusOptions}
      hasApplied={hasParticipantApplied}
      industryOptions={industryOptions}
      isExclusiveToClient={!!clientId}
      isExperianJob={isExperianJob}
      isLoggedIn={isLoggedIn}
      jobId={jobId}
      opportunity={opportunityDetails}
      parsedOpportunity={parsedOpportunity}
      seniorityOptions={seniorityLevelOptions}
      userDetails={userDetails}
      userId={userId}
      utmParams={utmParams}
    />
  );
}
