import { rewriteToPublicOrigin } from "@/lib/url/rewritePublicOrigin";

export const hashOnlyOfficeKey = (input: string) => {
  let hash = 0;
  for (let i = 0; i < input.length; i += 1) {
    hash = (hash << 5) - hash + input.charCodeAt(i);
    hash |= 0;
  }
  return Math.abs(hash).toString();
};

export const base64UrlEncodeUtf8 = (input: string) => {
  const bytes = new TextEncoder().encode(input);
  let binary = "";
  for (let i = 0; i < bytes.length; i += 1) {
    binary += String.fromCharCode(bytes[i] as number);
  }
  return btoa(binary).replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
};

export const docTypeFromExt = (ext: string) => {
  const word = ["doc", "docx", "odt", "rtf"];
  const slide = ["ppt", "pptx", "odp"];
  const sheet = ["xls", "xlsx", "ods", "csv"];
  const pdf = ["pdf"];
  if (word.includes(ext)) return "word";
  if (slide.includes(ext)) return "slide";
  if (sheet.includes(ext)) return "cell";
  if (pdf.includes(ext)) return "pdf";
  return "word";
};

export function resolveOnlyOfficeDocumentUrl(input: {
  effectiveFileUrl: string;
  proxyOrigin: string;
  storageHostOverride: string;
  runtimeSupabaseUrl: string;
  useConvex: boolean;
}): string {
  const { effectiveFileUrl, proxyOrigin, storageHostOverride, runtimeSupabaseUrl, useConvex } = input;
  if (!effectiveFileUrl) return "";

  const isConvexStorageUrl = (() => {
    try {
      const u = new URL(effectiveFileUrl);
      return u.pathname.startsWith("/api/storage/");
    } catch {
      return false;
    }
  })();

  let base =
    storageHostOverride || useConvex || isConvexStorageUrl
      ? effectiveFileUrl
      : rewriteToPublicOrigin(effectiveFileUrl, runtimeSupabaseUrl);
  try {
    const raw = new URL(base);
    let alreadyProxy = raw.pathname.includes("/api/onlyoffice/proxy");
    const isLocalHost =
      raw.hostname === "127.0.0.1" || raw.hostname === "localhost" || raw.hostname === "host.docker.internal";

    if (alreadyProxy && proxyOrigin) {
      const po = new URL(proxyOrigin);
      raw.protocol = po.protocol;
      raw.host = po.host;
      base = raw.toString();
    }

    if (!alreadyProxy && proxyOrigin && isLocalHost) {
      const proxy = new URL("/api/onlyoffice/proxy", proxyOrigin || window.location.origin);
      proxy.searchParams.set("u", base64UrlEncodeUtf8(base));
      base = proxy.toString();
      alreadyProxy = true;
    }
    if (!alreadyProxy && raw.searchParams.has("token")) {
      const proxy = new URL("/api/onlyoffice/proxy", proxyOrigin || window.location.origin);
      proxy.searchParams.set("u", base64UrlEncodeUtf8(base));
      base = proxy.toString();
      alreadyProxy = true;
    }

    const u = new URL(base);
    if (!storageHostOverride || alreadyProxy) return u.toString();

    if (/^https?:\/\//i.test(storageHostOverride)) {
      const ov = new URL(storageHostOverride);
      u.protocol = ov.protocol;
      u.host = ov.host;
      return u.toString();
    }

    u.hostname = storageHostOverride;
    return u.toString();
  } catch {
    return base;
  }
}

export function buildOnlyOfficeCallbackUrl(input: {
  callbackOrigin: string;
  proxyOrigin: string;
  windowOrigin: string;
  assetId: string;
  userId: string;
}): string {
  const base = input.callbackOrigin || input.proxyOrigin || input.windowOrigin;
  const callback = new URL("/api/onlyoffice/callback", base);
  if (input.assetId) callback.searchParams.set("assetId", input.assetId);
  if (input.userId) callback.searchParams.set("userId", input.userId);
  return callback.toString();
}

export function buildOnlyOfficeForcesaveUrl(input: {
  windowOrigin: string;
  assetId: string;
  key: string;
}): string {
  const url = new URL("/api/onlyoffice/forcesave", input.windowOrigin);
  url.searchParams.set("assetId", input.assetId);
  url.searchParams.set("key", input.key);
  return url.toString();
}

export function buildOnlyOfficeOpenFileId(input: {
  assetId: string;
  docKey: string;
  resolvedFileUrl: string;
  fileName: string;
}): string {
  return input.assetId || `onlyoffice_${input.docKey || hashOnlyOfficeKey(`${input.resolvedFileUrl}-${input.fileName}`)}`;
}
