import iconv from "iconv-lite";

const SEARCH_RESULTS_BASE_URL = "https://s.1688.com/selloffer/offer_search.htm";

function isUnescapedQueryByte(byte) {
  return (
    (byte >= 0x30 && byte <= 0x39) ||
    (byte >= 0x41 && byte <= 0x5a) ||
    (byte >= 0x61 && byte <= 0x7a) ||
    byte === 0x2d ||
    byte === 0x5f ||
    byte === 0x2e ||
    byte === 0x21 ||
    byte === 0x7e ||
    byte === 0x2a ||
    byte === 0x27 ||
    byte === 0x28 ||
    byte === 0x29
  );
}

export function encode1688KeywordForUrl(keyword) {
  const normalizedKeyword = String(keyword ?? "");
  const encodedBytes = iconv.encode(normalizedKeyword, "gbk");
  let encodedKeyword = "";

  for (const byte of encodedBytes) {
    if (isUnescapedQueryByte(byte)) {
      encodedKeyword += String.fromCharCode(byte);
      continue;
    }

    encodedKeyword += `%${byte.toString(16).toUpperCase().padStart(2, "0")}`;
  }

  return encodedKeyword;
}

export function build1688OfferSearchUrl(keyword) {
  return `${SEARCH_RESULTS_BASE_URL}?keywords=${encode1688KeywordForUrl(keyword)}`;
}

function splitHash(url) {
  const hashIndex = url.indexOf("#");
  if (hashIndex === -1) {
    return { withoutHash: url, hash: "" };
  }

  return {
    withoutHash: url.slice(0, hashIndex),
    hash: url.slice(hashIndex),
  };
}

function splitQuery(url) {
  const queryIndex = url.indexOf("?");
  if (queryIndex === -1) {
    return { base: url, query: "" };
  }

  return {
    base: url.slice(0, queryIndex),
    query: url.slice(queryIndex + 1),
  };
}

export function replaceRawQueryParam(url, paramName, rawValue) {
  const normalizedUrl = String(url ?? "");
  const normalizedName = String(paramName ?? "").trim();

  if (!normalizedUrl || !normalizedName) {
    return normalizedUrl;
  }

  const { withoutHash, hash } = splitHash(normalizedUrl);
  const { base, query } = splitQuery(withoutHash);
  const params = query
    ? query.split("&").filter((part) => part && part.split("=", 1)[0] !== normalizedName)
    : [];

  if (rawValue != null && rawValue !== "") {
    params.push(`${normalizedName}=${String(rawValue)}`);
  }

  return `${base}${params.length > 0 ? `?${params.join("&")}` : ""}${hash}`;
}