import { config } from '../config';
import { rewriteGoogleMapsApiKeys } from '../googleMaps/key';
import { rewriteZowieUrls } from '../intercept/zowieProxy';

/** Content-types we rewrite (buffer + replace). Everything else is streamed. */
const REWRITABLE = [
  'text/html',
  'application/json',
  'application/javascript',
  'text/javascript',
  'text/css',
  'application/x-javascript',
];

export function isRewritable(contentType: string | undefined): boolean {
  if (!contentType) return false;
  const ct = contentType.toLowerCase();
  return REWRITABLE.some((t) => ct.includes(t));
}

/**
 * Rewrite all Sinsay/LPP URLs in a response buffer to point to our domain.
 * Handles plain, JSON-escaped, and unicode-escaped variants.
 */
interface RewriteOptions {
  origin?: string;
  domain?: string;
}

export function rewriteBody(body: Buffer, options?: RewriteOptions): Buffer {
  let text = body.toString('utf8');
  text = applyRewrites(text, options);
  return Buffer.from(text, 'utf8');
}

export function applyRewrites(text: string, options?: RewriteOptions): string {
  const origin = options?.origin ?? config.origin;
  const mirrorDomain = options?.domain ?? config.domain;
  const cdnOrigin = `${origin}${config.cdnPrefix}`;
  const staticOrigin = `${origin}${config.staticCdnPrefix}`;

  // ─── 1. media.sinsay.com ────────────────────────────────────────────────
  // plain https
  text = text.replaceAll('https://media.sinsay.com/', `${cdnOrigin}/`);
  text = text.replaceAll('https://media.sinsay.com', cdnOrigin);
  // plain http
  text = text.replaceAll('http://media.sinsay.com/', `${cdnOrigin}/`);
  text = text.replaceAll('http://media.sinsay.com', cdnOrigin);
  // JSON-escaped https / http
  text = text.replaceAll('https:\\/\\/media.sinsay.com\\/', escapeForJson(`${cdnOrigin}/`));
  text = text.replaceAll('https:\\/\\/media.sinsay.com', escapeForJson(cdnOrigin));
  text = text.replaceAll('http:\\/\\/media.sinsay.com\\/', escapeForJson(`${cdnOrigin}/`));
  text = text.replaceAll('http:\\/\\/media.sinsay.com', escapeForJson(cdnOrigin));
  // unicode-escaped (\u003A = ':', \\\/\\\/  = '//')
  text = text.replaceAll('https\\u003A\\/\\/media.sinsay.com\\/', escapeForJson(`${cdnOrigin}/`));
  text = text.replaceAll('https\\u003A\\/\\/media.sinsay.com', escapeForJson(cdnOrigin));
  text = text.replaceAll('https\\u003A\\\\\\/\\\\\\/media.sinsay.com\\/', escapeForJson(`${cdnOrigin}/`));
  text = text.replaceAll('https\\u003A\\\\\\/\\\\\\/media.sinsay.com', escapeForJson(cdnOrigin));
  text = text.replaceAll('http\\u003A\\/\\/media.sinsay.com\\/', escapeForJson(`${cdnOrigin}/`));
  text = text.replaceAll('http\\u003A\\/\\/media.sinsay.com', escapeForJson(cdnOrigin));
  text = text.replaceAll('http\\u003A\\\\\\/\\\\\\/media.sinsay.com\\/', escapeForJson(`${cdnOrigin}/`));
  text = text.replaceAll('http\\u003A\\\\\\/\\\\\\/media.sinsay.com', escapeForJson(cdnOrigin));

  // ─── 2. static.sinsay.com ───────────────────────────────────────────────
  text = text.replaceAll('https://static.sinsay.com/', `${staticOrigin}/`);
  text = text.replaceAll('https://static.sinsay.com', staticOrigin);
  text = text.replaceAll('http://static.sinsay.com/', `${staticOrigin}/`);
  text = text.replaceAll('http://static.sinsay.com', staticOrigin);
  text = text.replaceAll('https:\\/\\/static.sinsay.com\\/', escapeForJson(`${staticOrigin}/`));
  text = text.replaceAll('https:\\/\\/static.sinsay.com', escapeForJson(staticOrigin));
  text = text.replaceAll('http:\\/\\/static.sinsay.com\\/', escapeForJson(`${staticOrigin}/`));
  text = text.replaceAll('http:\\/\\/static.sinsay.com', escapeForJson(staticOrigin));
  text = text.replaceAll('https\\u003A\\/\\/static.sinsay.com\\/', escapeForJson(`${staticOrigin}/`));
  text = text.replaceAll('https\\u003A\\/\\/static.sinsay.com', escapeForJson(staticOrigin));
  text = text.replaceAll('https\\u003A\\\\\\/\\\\\\/static.sinsay.com\\/', escapeForJson(`${staticOrigin}/`));
  text = text.replaceAll('https\\u003A\\\\\\/\\\\\\/static.sinsay.com', escapeForJson(staticOrigin));
  text = text.replaceAll('http\\u003A\\/\\/static.sinsay.com\\/', escapeForJson(`${staticOrigin}/`));
  text = text.replaceAll('http\\u003A\\/\\/static.sinsay.com', escapeForJson(staticOrigin));
  text = text.replaceAll('http\\u003A\\\\\\/\\\\\\/static.sinsay.com\\/', escapeForJson(`${staticOrigin}/`));
  text = text.replaceAll('http\\u003A\\\\\\/\\\\\\/static.sinsay.com', escapeForJson(staticOrigin));

  // ─── 3. fastend.sinsay.com ──────────────────────────────────────────────
  text = text.replaceAll('https://fastend.sinsay.com/', `${origin}/`);
  text = text.replaceAll('https://fastend.sinsay.com', origin);
  text = text.replaceAll('http://fastend.sinsay.com/', `${origin}/`);
  text = text.replaceAll('http://fastend.sinsay.com', origin);
  text = text.replaceAll('https:\\/\\/fastend.sinsay.com\\/', escapeForJson(`${origin}/`));
  text = text.replaceAll('https:\\/\\/fastend.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('http:\\/\\/fastend.sinsay.com\\/', escapeForJson(`${origin}/`));
  text = text.replaceAll('http:\\/\\/fastend.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('https\\u003A\\/\\/fastend.sinsay.com\\/', escapeForJson(`${origin}/`));
  text = text.replaceAll('https\\u003A\\/\\/fastend.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('https\\u003A\\\\\\/\\\\\\/fastend.sinsay.com\\/', escapeForJson(`${origin}/`));
  text = text.replaceAll('https\\u003A\\\\\\/\\\\\\/fastend.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('http\\u003A\\/\\/fastend.sinsay.com\\/', escapeForJson(`${origin}/`));
  text = text.replaceAll('http\\u003A\\/\\/fastend.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('http\\u003A\\\\\\/\\\\\\/fastend.sinsay.com\\/', escapeForJson(`${origin}/`));
  text = text.replaceAll('http\\u003A\\\\\\/\\\\\\/fastend.sinsay.com', escapeForJson(origin));

  // ─── 4. www.sinsay.com (must come last to avoid double-rewriting CDN hosts) ──
  // plain https / http
  text = text.replaceAll('https://www.sinsay.com', origin);
  text = text.replaceAll('http://www.sinsay.com', origin);
  // JSON-escaped
  text = text.replaceAll('https:\\/\\/www.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('http:\\/\\/www.sinsay.com', escapeForJson(origin));
  // unicode-escaped  https\u003A\/\/www.sinsay.com  and  https\u003A\\\/\\\/www.sinsay.com
  text = text.replaceAll('https\\u003A\\/\\/www.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('https\\u003A\\\\\\/\\\\\\/www.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('http\\u003A\\/\\/www.sinsay.com', escapeForJson(origin));
  text = text.replaceAll('http\\u003A\\\\\\/\\\\\\/www.sinsay.com', escapeForJson(origin));

  // ─── 5. arch.sinsay.com (before bare //arch — else https://arch → https://localhost/…)
  const archOrigin = `${origin.replace(/\/$/, '')}${config.intercept.archProxyPrefix}`;
  text = text.replaceAll('https://arch.sinsay.com/', `${archOrigin}/`);
  text = text.replaceAll(
    'https:\\/\\/arch.sinsay.com\\/',
    escapeForJson(`${archOrigin}/`),
  );
  text = text.replaceAll('//arch.sinsay.com', archOrigin);

  // ─── 6. Bare protocol-relative hostnames ────────────────────────────────
  text = text.replaceAll('//www.sinsay.com', `//${mirrorDomain}`);
  text = text.replaceAll('//fastend.sinsay.com', `//${mirrorDomain}`);

  // ─── 7. Luigi/Luma AI search integration ────────────────────────────────
  text = text.replaceAll(
    'https://scripts.luigisbox.tech/',
    `${origin}${config.intercept.luigisboxProxyPrefix}/`,
  );
  text = text.replaceAll(
    'https:\\/\\/scripts.luigisbox.tech\\/',
    escapeForJson(`${origin}${config.intercept.luigisboxProxyPrefix}/`),
  );

  // Fix https://localhost arch URLs left from older rewrites (dev is HTTP-only).
  if (mirrorDomain.startsWith('localhost') || mirrorDomain.startsWith('127.')) {
    const archBase = `${archOrigin}/`;
    text = text.replaceAll(`https://${mirrorDomain}${config.intercept.archProxyPrefix}/`, archBase);
    text = text.replaceAll(
      `https:\\/\\/${mirrorDomain.replace(/\./g, '\\.')}${config.intercept.archProxyPrefix.replace(/\//g, '\\/')}\\/`,
      escapeForJson(archBase),
    );
  }

  // ─── 8. Google Maps (API key is referer-locked to www.sinsay.com) ───────
  const googleMapsPrefix = `${origin.replace(/\/$/, '')}${config.intercept.googleMapsProxyPrefix}`;
  const googleHosts = [
    'maps.googleapis.com',
    'maps.gstatic.com',
    'khms.googleapis.com',
    'khms0.googleapis.com',
    'khms1.googleapis.com',
    'khms2.googleapis.com',
    'khms3.googleapis.com',
    'geo0.googleapis.com',
    'geo1.googleapis.com',
  ];
  for (const host of googleHosts) {
    const proxied = `${googleMapsPrefix}/${host}`;
    text = text.replaceAll(`https://${host}`, proxied);
    text = text.replaceAll(`http://${host}`, proxied);
    text = text.replaceAll(`//${host}`, proxied);
    text = text.replaceAll(`https:\\/\\/${host}`, escapeForJson(proxied));
    text = text.replaceAll(`http:\\/\\/${host}`, escapeForJson(proxied));
    text = text.replaceAll(`\\/\\/${host}`, escapeForJson(proxied));
  }

  // ─── 9. Wishlist API ─────────────────────────────────────────────────────
  text = text.replaceAll(
    'https://wishlist-api.sinsay.com/',
    `${origin}${config.intercept.wishlistApiProxyPrefix}/`,
  );
  text = text.replaceAll(
    'https:\\/\\/wishlist-api.sinsay.com\\/',
    escapeForJson(`${origin}${config.intercept.wishlistApiProxyPrefix}/`),
  );

  // Use Magento checkoutcart (AJAX) everywhere — fastend gRPC cart stays empty when add goes to Magento.
  text = text.replaceAll('"fastendcart":1', '"fastendcart":0');
  text = text.replaceAll('\\"fastendcart\\":1', '\\"fastendcart\\":0');

  text = rewriteContactDetails(text);
  text = rewriteZowieUrls(text);
  text = stripInlineZowieLoader(text);
  text = rewriteBase64SinsayReferers(text, origin);
  text = rewriteGoogleMapsApiKeys(text);

  return text;
}

/** Login AJAX URLs embed referer/uenc as base64(https://www.sinsay.com/...). */
function rewriteBase64SinsayReferers(text: string, mirrorOrigin: string): string {
  const mirrorRoot = `${mirrorOrigin.replace(/\/$/, '')}/pl/pl/`;
  const pairs: Array<[string, string]> = [
    ['https://www.sinsay.com/pl/pl/', mirrorRoot],
    ['https://www.sinsay.com/pl/pl/checkout/order/', `${mirrorRoot}checkout/order/`],
    ['http://www.sinsay.com/pl/pl/', mirrorRoot],
  ];
  for (const [upstream, mirror] of pairs) {
    text = text.replaceAll(base64UrlToken(upstream), base64UrlToken(mirror));
    text = text.replaceAll(base64UrlToken(`${upstream},`), base64UrlToken(`${mirror},`));
  }
  return text;
}

/** Base64 as embedded in Sinsay paths (padding often omitted before ","). */
function base64UrlToken(value: string): string {
  return Buffer.from(value).toString('base64').replace(/=+$/, '');
}

/** Remove CMS-embedded Zowie loader; global inject.ts provides one instance. */
function stripInlineZowieLoader(text: string): string {
  if (!config.support.enabled || !text.includes('startZowie')) {
    return text;
  }
  return text.replace(
    /<script type="text\/javascript">\s*function startZowie\(\)[\s\S]*?startZowie\(\);\s*<\/script>/gi,
    '',
  );
}

/** Mirror support phone above WhatsApp and fix empty tel: links on contacts. */
function rewriteContactDetails(text: string): string {
  const { phoneDisplay, phoneTel, whatsappDigits } = config.contact;
  const whatsappUrl = `https://wa.me/${whatsappDigits}`;

  text = text.replaceAll('https://wa.me/48583536565', whatsappUrl);
  text = text.replaceAll(
    'https:\\/\\/wa.me\\/48583536565',
    escapeForJson(whatsappUrl),
  );

  text = text.replaceAll(
    /<a\s+href="tel:\s*">\s*<\/a>/gi,
    `<a href="tel:${phoneTel}">${phoneDisplay}</a>`,
  );

  const phoneBlock =
    `<p style="text-align: center;"><a href="tel:${phoneTel}" ` +
    `style="color:#000000;font-weight:600;text-decoration:none;">${phoneDisplay}</a></p>`;
  const whatsappMarker = '<p style="text-align: center;"><a aria-label="Chat on WhatsApp"';

  if (text.includes(whatsappMarker) && !text.includes(phoneBlock)) {
    text = text.replaceAll(whatsappMarker, phoneBlock + whatsappMarker);
  }

  return text;
}

/** Escape a URL the same way JSON.stringify would (forward slashes → \/) */
function escapeForJson(url: string): string {
  return url.replace(/\//g, '\\/');
}
