import db from "../models/index.js";
import { sendEmail, renderTemplate } from "../utils/emailService.js";
import { logAudit } from "../utils/auditLogger.js";

/**
 * Maps a Didit decision payload onto our internal KybApplication status, persists
 * the change, and notifies the merchant. Shared between the Didit webhook handler
 * and the KYB polling cron job so the status-mapping logic can't drift out of sync
 * between the two call sites.
 *
 * @param {object} application - A KybApplication instance, with `merchant` included.
 * @param {object} decision - The response from DiditService.getSessionDecision().
 * @param {"webhook"|"cron"} source - Where this update came from, for the KybHistory comment.
 * @param {object} [req] - Optional Express request, for audit log IP attribution.
 * @returns {Promise<{ changed: boolean, previousStatus: string, newStatus: string }>}
 */
export const applyDiditKybDecision = async (application, decision, source = "webhook", req = null) => {
  const previousStatus = application.status;
  let newStatus = application.status;

  // Didit's documented session-level statuses ("Not Started", "In Progress", "Awaiting User",
  // "In Review", "Approved", "Declined", "Resubmitted", "Expired", "Kyc Expired", "Abandoned")
  // are Title Case with spaces. Normalized here since Didit's own docs are inconsistent about casing.
  const normalizedStatus = String(decision.status || "").trim().toLowerCase();

  switch (normalizedStatus) {
    case "approved":
      // Didit identity checks passed -> Move to Under Review for SuperAdmin final approval
      newStatus = "Under Review";
      break;
    case "declined":
      newStatus = "Rejected";
      break;
    case "in review":
    case "resubmitted":
      newStatus = "Under Review";
      break;
    case "expired":
    case "kyc expired":
    case "abandoned":
      newStatus = "Additional Documents Required";
      break;
    case "not started":
    case "in progress":
    case "awaiting user":
      // Expected in-flight states while the merchant is still completing the hosted flow — no transition yet.
      break;
    default:
      console.warn(`⚠️ [Didit Decision] Unrecognized decision.status "${decision.status}" for session ${application.diditSessionId} — no status change applied`);
  }

  if (previousStatus === newStatus && application.verificationOutcome) {
    return { changed: false, previousStatus, newStatus };
  }

  application.status = newStatus;
  application.verificationOutcome = decision;
  await application.save();

  // Update linked Merchant kybStatus if in review or rejected
  if (application.merchantId) {
    const merchantKybState = newStatus === "Under Review" ? "in_review" : (newStatus === "Rejected" ? "rejected" : "pending");
    await db.Merchant.update({ kybStatus: merchantKybState }, { where: { id: application.merchantId } });
  }

  await db.KybHistory.create({
    applicationId: application.id,
    action: `Didit Status Update: ${decision.status}`,
    previousStatus,
    newStatus,
    comment: source === "cron"
      ? "Status automatically updated via scheduled Didit sync."
      : "Status automatically updated via Didit webhook.",
  });

  logAudit({
    userId: application.merchantId,
    userType: "system",
    action: source === "cron" ? "KYB_STATUS_UPDATED_VIA_CRON" : "KYB_STATUS_UPDATED_VIA_WEBHOOK",
    details: { applicationId: application.id, previousStatus, newStatus, diditSessionId: application.diditSessionId },
    req,
  });

  // Notify the merchant — same templates/pattern used by the manual admin review path
  let slug = "";
  if (newStatus === "Under Review") slug = "kyb_under_review";
  else if (newStatus === "Approved") slug = "kyb_approved";
  else if (newStatus === "Rejected") slug = "kyb_rejected";
  else if (newStatus === "Additional Documents Required") slug = "kyb_additional_docs";

  if (slug && application.merchant) {
    const emailParams = await renderTemplate(slug, {
      merchantName: application.merchant.businessName,
      reason: newStatus === "Rejected" || newStatus === "Additional Documents Required"
        ? "Please check your KYB verification details in the dashboard for more information."
        : "",
    });

    if (emailParams) {
      sendEmail(application.merchant.email, emailParams.subject, emailParams.html).catch(() => {});
    }
  } else if (slug && !application.merchant) {
    console.warn(`⚠️ [Didit Decision] KybApplication ${application.id} has no linked merchant — skipped notification email`);
  }

  return { changed: true, previousStatus, newStatus };
};
