export const runtime = "nodejs";

type RunEsignOfferLetterRequest = {
  firstName: string;
  lastName: string;
  emailId: string;
};

function getFoxitEsignAccessToken() {
  return process.env.FOXIT_ESIGN_API_ACCESS_TOKEN ?? "";
}

function pickEmbeddedSessionUrl(value: unknown): string | null {
  if (!value || typeof value !== "object") {
    return null;
  }

  const record = value as Record<string, unknown>;
  const directCandidates = [
    record.embeddedSessionURL,
    record.embeddedSessionUrl,
    record.embeddedSigningSessionURL,
    record.embeddedSigningSessionUrl,
  ];

  for (const candidate of directCandidates) {
    if (typeof candidate === "string" && candidate.length > 0) {
      return candidate;
    }
  }

  const nestedCandidates = [record.data, record.result, record.response, record.payload];
  for (const nested of nestedCandidates) {
    const nestedUrl = pickEmbeddedSessionUrl(nested);
    if (nestedUrl) {
      return nestedUrl;
    }
  }

  return null;
}

function pickFolderId(value: unknown): string | number | null {
  if (!value || typeof value !== "object") {
    return null;
  }

  const record = value as Record<string, unknown>;
  const folder = record.folder as Record<string, unknown> | undefined;
  const directCandidate = folder?.folderId ?? record.folderId;
  if (typeof directCandidate === "string" || typeof directCandidate === "number") {
    return directCandidate;
  }

  const nestedCandidates = [record.data, record.result, record.response, record.payload, folder];
  for (const nested of nestedCandidates) {
    const nestedFolderId = pickFolderId(nested);
    if (nestedFolderId !== null) {
      return nestedFolderId;
    }
  }

  return null;
}

function pickFolderAccessURLForAuthor(value: unknown): string | null {
  if (!value || typeof value !== "object") {
    return null;
  }

  const record = value as Record<string, unknown>;
  const folder = record.folder as Record<string, unknown> | undefined;
  const directCandidates = [
    folder?.folderAccessURLForAuthor,
    folder?.folderAccessUrlForAuthor,
    record.folderAccessURLForAuthor,
    record.folderAccessUrlForAuthor,
  ];

  for (const candidate of directCandidates) {
    if (typeof candidate === "string" && candidate.length > 0) {
      return candidate;
    }
  }

  const nestedCandidates = [record.data, record.result, record.response, record.payload, folder];
  for (const nested of nestedCandidates) {
    const nestedUrl = pickFolderAccessURLForAuthor(nested);
    if (nestedUrl) {
      return nestedUrl;
    }
  }

  return null;
}

function pickEsignStatus(value: unknown): string | null {
  if (!value || typeof value !== "object") {
    return null;
  }

  const record = value as Record<string, unknown>;
  const folder = record.folder as Record<string, unknown> | undefined;
  const documentsList = Array.isArray(folder?.documentsList)
    ? (folder?.documentsList as Array<Record<string, unknown>>)
    : [];
  const firstDocument = documentsList[0];
  const directCandidates = [
    folder?.folderStatus,
    folder?.status,
    folder?.envelopeStatus,
    firstDocument?.contractStatus,
    record.status,
    record.folderStatus,
    record.signingStatus,
    record.overallStatus,
  ];

  for (const candidate of directCandidates) {
    if (typeof candidate === "string" && candidate.length > 0) {
      return candidate;
    }
  }

  const nestedCandidates = [record.data, record.result, record.response, record.payload, folder];
  for (const nested of nestedCandidates) {
    const nestedStatus = pickEsignStatus(nested);
    if (nestedStatus) {
      return nestedStatus;
    }
  }

  return null;
}

function normalizeEsignStatus(status: string | null): string | null {
  if (!status) {
    return null;
  }
  const normalized = status.trim().toUpperCase().replace(/_/g, " ");
  const knownStatuses = new Set([
    "EXECUTED",
    "SHARED",
    "DRAFT",
    "PARTIALLY SIGNED",
    "CANCELLED",
    "EXPIRED",
    "DELETED",
  ]);
  return knownStatuses.has(normalized) ? normalized : status.trim();
}

export async function POST(request: Request) {
  try {
    const body = (await request.json()) as RunEsignOfferLetterRequest;
    if (!body?.firstName || !body?.lastName || !body?.emailId) {
      return Response.json(
        { error: "Missing firstName, lastName, or emailId in request body." },
        { status: 400 }
      );
    }

    const accessToken = getFoxitEsignAccessToken();
    if (!accessToken) {
      return Response.json(
        { error: "FOXIT_ESIGN_API_ACCESS_TOKEN is not configured on the server." },
        { status: 500 }
      );
    }

    const foxitPayload = {
      folderName: "Sample ATS System Offer Letter",
      templateIds: [421369],
      allowAdvancedEmailValidation: false,
      parties: [
        {
          firstName: body.firstName,
          lastName: body.lastName,
          emailId: body.emailId,
          permission: "FILL_FIELDS_AND_SIGN",
          workflowSequence: 1,
          sequence: 1,
          allowNameChange: "true",
          signerAuthLevel: "NO",
        },
      ],
      signInSequence: false,
      inPersonEnable: false,
      sendNow: false,
      signSuccessUrlAllParties: false,
      createEmbeddedSendingSession: true,
      fixRecipientParties: true,
      fixDocuments: true,
      hideSignerSelectOption: false,
      hideMoreActions: true,
      hideSenderName: true,
      hideSaveButton: true,
      hideFolderName: false,
      hideDocumentsName: true,
      hideAddMeButton: false,
      hideAddNewButton: true,
      hideAddGroupButton: false,
      createEmbeddedSigningSessionForAllParties: false,
      hideNextRequiredFieldBtn: false,
      hideDeclineToSign: false,
      hideMoreAction: false,
      hideAddPartiesOption: false,
      sessionExpire: false,
      expiry: 300000,
      allowSendNowAndEmbeddedSigningSession: false,
      enableStepByStep: false,
    };

    const foxitResponse = await fetch("https://na1.foxitesign.foxit.com/api/templates/createFolder", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${accessToken}`,
      },
      body: JSON.stringify(foxitPayload),
    });

    const rawText = await foxitResponse.text();
    let foxitJson: Record<string, unknown> = {};
    try {
      foxitJson = rawText ? (JSON.parse(rawText) as Record<string, unknown>) : {};
    } catch {
      return Response.json(
        {
          error: "Foxit eSign response was not valid JSON.",
          status: foxitResponse.status,
          rawText,
        },
        { status: 502 }
      );
    }

    if (!foxitResponse.ok) {
      return Response.json(
        {
          error: "Foxit eSign API call failed.",
          status: foxitResponse.status,
          details: foxitJson,
        },
        { status: 502 }
      );
    }

    const embeddedSessionURL = pickEmbeddedSessionUrl(foxitJson);
    const folderAccessURLForAuthor = pickFolderAccessURLForAuthor(foxitJson);
    const folderId = pickFolderId(foxitJson);
    const esignStatus = normalizeEsignStatus(pickEsignStatus(foxitJson));
    return Response.json({
      foxitResponse: foxitJson,
      embeddedSessionURL,
      folderAccessURLForAuthor,
      folderId,
      esignStatus,
    });
  } catch (error) {
    const message = error instanceof Error ? error.message : "Unknown server error";
    return Response.json({ error: message }, { status: 500 });
  }
}
