const { admin } = require("../firebase/firebase-handler");
const { default: CdkJobExport, CdkSelectedCustomer } = require("../cdk/cdk-job-export");
const CdkGetMakes = require("../cdk/cdk-get-makes").default;
const CdkCalculateAllocations = require("../cdk/cdk-calculate-allocations").default;
const logger = require("../utils/logger");
const { default: PbsExportJob, PbsSelectedCustomer } = require("../accounting/pbs/pbs-job-export");

const { PbsCalculateAllocationsAp, PbsExportAp } = require("../accounting/pbs/pbs-ap-allocations");
const { createLogEvent } = require("./createLogEvent");

function SetLegacyWebsocketHandlers(io) {
  io.use(function (socket, next) {
    try {
      if (socket.handshake.auth.token) {
        admin
          .auth()
          .verifyIdToken(socket.handshake.auth.token)
          .then((user) => {
            socket.user = user;
            next();
          })
          .catch((error) => {
            next(new Error("Authentication error", JSON.stringify(error)));
          });
      } else {
        next(new Error("Authentication error - no authorization token."));
      }
    } catch (error) {
      //console.log("Uncaught connection error:::", error);
      logger.log("websocket-connection-error", "error", null, null, {
        token: socket.handshake.auth.token,
        ...error
      });
      next(new Error(`Authentication error ${error}`));
    }
  });

  io.on("connection", (socket) => {
    socket.log_level = "DEBUG";
    createLogEvent(socket, "DEBUG", `Connected and Authenticated.`);

    socket.on("set-log-level", (level) => {
      socket.log_level = level;
      socket.emit("log-event", {
        timestamp: new Date(),
        level: "INFO",
        message: `Updated log level to ${level}`
      });
    });

    ///CDK
    socket.on("cdk-export-job", (jobid) => {
      CdkJobExport(socket, jobid);
    });

    socket.on("cdk-selected-customer", (selectedCustomerId) => {
      createLogEvent(socket, "DEBUG", `User selected customer ID  ${selectedCustomerId}`);
      socket.selectedCustomerId = selectedCustomerId;
      CdkSelectedCustomer(socket, selectedCustomerId);
    });

    socket.on("cdk-get-makes", async (cdk_dealerid, callback) => {
      try {
        const makes = await CdkGetMakes(socket, cdk_dealerid);
        callback(makes);
      } catch (error) {
        createLogEvent(socket, "ERROR", `Error in cdk-get-makes WS call. ${JSON.stringify(error, null, 2)}`);
      }
    });

    socket.on("cdk-calculate-allocations", async (jobid, callback) => {
      console.log("cdk-calculate-allocations called", typeof CdkCalculateAllocations);
      const allocations = await CdkCalculateAllocations(socket, jobid);
      createLogEvent(socket, "DEBUG", `Allocations calculated.`);
      createLogEvent(socket, "SILLY", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`);

      callback(allocations);
    });
    //END CDK

    //PBS AR
    socket.on("pbs-calculate-allocations", async (jobid, callback) => {
      const allocations = await CdkCalculateAllocations(socket, jobid);
      createLogEvent(socket, "DEBUG", `Allocations calculated.`);
      createLogEvent(socket, "SILLY", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`);

      callback(allocations);
    });
    socket.on("pbs-export-job", (jobid) => {
      PbsExportJob(socket, jobid);
    });
    socket.on("pbs-selected-customer", (selectedCustomerId) => {
      createLogEvent(socket, "DEBUG", `User selected customer ID  ${selectedCustomerId}`);
      socket.selectedCustomerId = selectedCustomerId;
      PbsSelectedCustomer(socket, selectedCustomerId);
    });
    //End PBS AR

    //PBS AP
    socket.on("pbs-calculate-allocations-ap", async (billids, callback) => {
      const allocations = await PbsCalculateAllocationsAp(socket, billids);
      createLogEvent(socket, "DEBUG", `AP Allocations calculated.`);
      createLogEvent(socket, "DEBUG", `Allocations calculated. ${JSON.stringify(allocations, null, 2)}`);
      socket.apAllocations = allocations;
      callback(allocations);
    });

    socket.on("pbs-export-ap", ({ billids, txEnvelope }) => {
      socket.txEnvelope = txEnvelope;
      PbsExportAp(socket, { billids, txEnvelope });
    });

    //END PBS AP

    socket.on("disconnect", () => {
      createLogEvent(socket, "DEBUG", `User disconnected.`);
    });

    // DMS reset for legacy WS (CDK / PBS)
    socket.on("dms-reset-context", ({ jobId, mode } = {}, ack) => {
      try {
        // Clear any per-socket DMS state that can leak across jobs
        socket.selectedCustomerId = null; // CDK / PBS AR
        socket.txEnvelope = null; // PBS AP export
        socket.apAllocations = null; // PBS AP allocations

        createLogEvent(
          socket,
          "DEBUG",
          `DMS reset-context (legacy WS): cleared per-socket state` +
            (jobId ? ` (jobId=${jobId})` : "") +
            (mode ? ` (mode=${mode})` : "")
        );

        if (typeof ack === "function") {
          ack({ ok: true });
        }
      } catch (error) {
        createLogEvent(socket, "ERROR", `DMS reset-context (legacy WS) failed: ${error.message}`);
        if (typeof ack === "function") {
          ack({ ok: false, error: error.message });
        }
      }
    });
  });
}

exports.SetLegacyWebsocketHandlers = SetLegacyWebsocketHandlers;
