const { RRClient } = require("./lib/index.cjs");
const { getRRConfigFromBodyshop } = require("./rr-config");

/**
 * Build an RR client + common opts from a bodyshop row
 */
const buildClientAndOpts = (bodyshop) => {
  const cfg = getRRConfigFromBodyshop(bodyshop);

  const client = new RRClient({
    baseUrl: cfg.baseUrl,
    username: cfg.username,
    password: cfg.password,
    timeoutMs: cfg.timeoutMs,
    retries: cfg.retries
  });

  // Common CallOptions for all ops; routing is CRITICAL for Destination block
  const opts = {
    routing: cfg.routing,
    envelope: {
      sender: {
        component: "Rome",
        task: "CVC",
        referenceId: "Query",
        creator: "RCI",
        senderName: "RCI"
      }
    }
  };

  return { client, opts };
};

/**
 * Normalize the combined-search arguments into the RR shape.
 * We infer `kind` if not provided, based on the first detectable field.
 */
const toCombinedSearchPayload = (args = {}) => {
  const q = { ...args };

  // Decide kind if not provided
  let kind = (q.kind || "").toString().trim();
  if (!kind) {
    if (q.phone) kind = "phone";
    else if (q.license) kind = "license";
    else if (q.vin) kind = "vin";
    else if (q.nameRecId || q.custId) kind = "nameRecId";
    else if (typeof q.name === "string" || (q.name && (q.name.fname || q.name.lname || q.name.mname || q.name.name))) {
      kind = "name";
    } else if (q.stkNo || q.stock) kind = "stkNo";
  }

  const payload = {
    // set both; the XML layer renders MaxRecs
    maxRecs: q.maxResults ?? q.maxRecs ?? 50,
    maxResults: q.maxResults ?? q.maxRecs ?? 50,
    kind
  };

  switch ((kind || "").toLowerCase()) {
    case "phone":
      payload.kind = "phone";
      payload.phone = String(q.phone ?? "").trim();
      break;

    case "license":
      payload.kind = "license";
      payload.license = String(q.license ?? "").trim();
      break;

    case "vin":
      payload.kind = "vin";
      payload.vin = String(q.vin ?? "").trim();
      break;

    case "namerecid":
      payload.kind = "nameRecId";
      payload.nameRecId = String(q.nameRecId ?? q.custId ?? "").trim();
      break;

    case "stkno":
    case "stkNo":
      payload.kind = "stkNo";
      payload.stkNo = String(q.stkNo ?? q.stock ?? "").trim();
      break;

    case "name": {
      payload.kind = "name";
      const n = q.name;
      if (typeof n === "string") {
        const last = n.trim();
        if (last) payload.name = { name: last }; // <LName Name="..."/>
        break;
      }
      const fname = n?.fname && String(n.fname).trim();
      const lname = n?.lname && String(n.lname).trim();
      const mname = n?.mname && String(n.mname).trim();
      const lastOnly = n?.name && String(n.name).trim();

      if (fname || lname || mname) {
        const full = {};
        if (fname) full.fname = fname;
        if (mname) full.mname = mname;
        if (lname) full.lname = lname;
        payload.name = full; // will render <FullName .../>
      } else if (lastOnly) {
        payload.name = { name: lastOnly }; // explicit last-only
      }
      break;
    }

    default:
      payload.kind = kind;
  }

  if (q.make || q.model || q.year) {
    payload.make = q.make || "ANY";
    payload.model = q.model || "ANY";
    payload.year = q.year || "ANY";
  }

  if (q.vin && payload.kind !== "vin") payload.vin = String(q.vin).trim();
  if (q.phone && payload.kind !== "phone") payload.phone = String(q.phone).trim();
  if (q.license && payload.kind !== "license") payload.license = String(q.license).trim();

  return payload;
};

/**
 * Combined customer/service/vehicle search
 * @param bodyshop - bodyshop row (must include rr_dealerid & rr_configuration with store/branch)
 * @param args - search inputs (phone | license | vin | nameRecId | name | stkNo)
 */
const rrCombinedSearch = async (bodyshop, args = {}) => {
  const { client, opts } = buildClientAndOpts(bodyshop);
  const payload = toCombinedSearchPayload(args);
  const res = await client.combinedSearch(payload, opts);
  return res;
};

/**
 * Advisors lookup
 * @param bodyshop
 * @param args - { department: 'B'|'S'|'P'|string, advisorNumber?: string }
 */
const rrGetAdvisors = async (bodyshop, args = {}) => {
  const { client, opts } = buildClientAndOpts(bodyshop);
  // Accept either department or departmentType from FE
  const dep = String(args.department ?? args.departmentType ?? "").toUpperCase();
  const department =
    dep === "BODY" || dep === "BODYSHOP" ? "B" : dep === "SERVICE" ? "S" : dep === "PARTS" ? "P" : dep || "B";

  const payload = {
    department,
    advisorNumber: args.advisorNumber ? String(args.advisorNumber) : undefined
  };

  return client.getAdvisors(payload, opts);
};

module.exports = {
  rrCombinedSearch,
  rrGetAdvisors,
  buildClientAndOpts
};
