/**
 * Processor for "cmsp-eligibility-history-remaining-check" jobs.
 * Saves eligibility PDF, service history PDF, and accumulator PDF
 * to the patient's ELIGIBILITY_STATUS document group.
 */
import fs from "fs/promises";
import path from "path";
import { storage } from "../../storage";
import { emptyFolderContainingFile } from "../../utils/emptyTempFolder";
import forwardToPatientDataExtractorService from "../../services/patientDataExtractorService";
import {
  callPythonSync,
  splitName,
  createOrUpdatePatientByInsuranceId,
} from "./_shared";

export interface CmspEligibilityHistoryRemainingProcessorInput {
  enrichedPayload: any;
  userId: number;
  insuranceId: string;
  formFirstName?: string;
  formLastName?: string;
  formDob?: string;
}

export interface CmspEligibilityHistoryRemainingProcessorResult {
  patientUpdateStatus?: string;
  pdfUploadStatus?: string;
  pdfFileId?: number | null;
  pdfFilename?: string | null;
  memberDetailsPdfFileId?: number | null;
  memberDetailsPdfFilename?: string | null;
  historyPdfFileId?: number | null;
  historyPdfFilename?: string | null;
  accumulatorPdfFileId?: number | null;
  accumulatorPdfFilename?: string | null;
}

export async function runCmspEligibilityHistoryRemainingProcessor(
  input: CmspEligibilityHistoryRemainingProcessorInput
): Promise<CmspEligibilityHistoryRemainingProcessorResult> {
  const { enrichedPayload, userId, insuranceId, formFirstName, formLastName, formDob } = input;

  const seleniumResult = await callPythonSync("/cmsp-eligibility-history-remaining-check", {
    data: enrichedPayload,
  });

  const outputResult: CmspEligibilityHistoryRemainingProcessorResult = {};

  // Extract patient name
  const seleniumFirst = seleniumResult.firstName?.trim() || null;
  const seleniumLast = seleniumResult.lastName?.trim() || null;
  const seleniumName = seleniumResult.name?.trim() || null;
  const seleniumInsurance = seleniumResult.insurance?.trim() || null;

  const extracted: { firstName?: string | null; lastName?: string | null } = {};

  if (seleniumFirst || seleniumLast) {
    extracted.firstName = seleniumFirst;
    extracted.lastName = seleniumLast;
  } else if (seleniumName) {
    const parts = splitName(seleniumName);
    extracted.firstName = parts.firstName || null;
    extracted.lastName = parts.lastName || null;
  }

  if (!extracted.firstName && !extracted.lastName && seleniumResult?.pdf_path?.endsWith(".pdf")) {
    try {
      const pdfBuffer = await fs.readFile(seleniumResult.pdf_path);
      const extraction = await forwardToPatientDataExtractorService({
        buffer: pdfBuffer,
        originalname: path.basename(seleniumResult.pdf_path),
        mimetype: "application/pdf",
      } as any);
      if (extraction.name) {
        const parts = splitName(extraction.name);
        extracted.firstName = parts.firstName || null;
        extracted.lastName = parts.lastName || null;
      }
    } catch (e) {
      console.error("[cmspProcessor] PDF name extraction failed:", e);
    }
  }

  const preferFirst = extracted.firstName || formFirstName || null;
  const preferLast = extracted.lastName || formLastName || null;

  let patient;
  try {
    patient = await createOrUpdatePatientByInsuranceId({
      insuranceId,
      firstName: preferFirst,
      lastName: preferLast,
      dob: formDob,
      userId,
    });
  } catch (e: any) {
    throw new Error(`Failed to create/update patient: ${e.message}`);
  }

  if (patient && patient.id !== undefined) {
    let newStatus = "UNKNOWN";
    if (seleniumResult.eligibility === "Y") newStatus = "ACTIVE";
    else if (seleniumResult.eligibility === "N") newStatus = "INACTIVE";

    const updates: any = { status: newStatus };
    if (seleniumInsurance) updates.insuranceProvider = seleniumInsurance;
    await storage.updatePatient(patient.id, updates);
    outputResult.patientUpdateStatus = `Patient status updated to ${newStatus}`;

    // Helper: save a single PDF to the patient's ELIGIBILITY_STATUS group
    const saveToGroup = async (pdfPath: string): Promise<number | null> => {
      try {
        const buffer = await fs.readFile(pdfPath);
        const groupTitleKey = "ELIGIBILITY_STATUS";
        const groupTitle = "Eligibility Status";
        let group = await storage.findPdfGroupByPatientTitleKey(patient!.id, groupTitleKey);
        if (!group) group = await storage.createPdfGroup(patient!.id, groupTitle, groupTitleKey);
        if (!group?.id) throw new Error("PDF group creation failed");
        const created = await storage.createPdfFile(group.id, path.basename(pdfPath), buffer);
        if (created && typeof created === "object" && "id" in created) {
          return Number(created.id);
        }
        return null;
      } catch (e: any) {
        console.error("[cmspProcessor] saveToGroup failed:", e.message);
        return null;
      }
    };

    // Save eligibility PDF
    if (seleniumResult.pdf_path?.endsWith(".pdf")) {
      outputResult.pdfFileId = await saveToGroup(seleniumResult.pdf_path);
      outputResult.pdfFilename = path.basename(seleniumResult.pdf_path);
      outputResult.pdfUploadStatus = outputResult.pdfFileId ? "Eligibility PDF saved" : "Eligibility PDF upload failed";
    } else {
      outputResult.pdfUploadStatus = "No eligibility PDF returned by Selenium";
    }

    // Save member details PDF
    if (seleniumResult.member_details_pdf_path?.endsWith(".pdf")) {
      outputResult.memberDetailsPdfFileId = await saveToGroup(seleniumResult.member_details_pdf_path);
      outputResult.memberDetailsPdfFilename = path.basename(seleniumResult.member_details_pdf_path);
    }

    // Save history PDF
    if (seleniumResult.history_pdf_path?.endsWith(".pdf")) {
      outputResult.historyPdfFileId = await saveToGroup(seleniumResult.history_pdf_path);
      outputResult.historyPdfFilename = path.basename(seleniumResult.history_pdf_path);
    }

    // Save accumulator PDF
    if (seleniumResult.accumulator_pdf_path?.endsWith(".pdf")) {
      outputResult.accumulatorPdfFileId = await saveToGroup(seleniumResult.accumulator_pdf_path);
      outputResult.accumulatorPdfFilename = path.basename(seleniumResult.accumulator_pdf_path);
    }
  } else {
    outputResult.patientUpdateStatus = "Patient not found or missing ID; no update performed";
  }

  // Cleanup temp files
  try {
    if (seleniumResult.pdf_path) await emptyFolderContainingFile(seleniumResult.pdf_path);
  } catch (e) {
    console.error("[cmspProcessor] cleanup failed:", e);
  }

  return outputResult;
}
