import fs from 'fs';
import path from 'path';
import { getPublicHost } from './getPublicHost';
import { writeToLog } from './writeToLog';

// const baseProxyUrl = 'http://localhost:3005';
const baseProxyUrl = getPublicHost('basePath');
const pageLoadLogs = path.join(__dirname, '../pageload.log'); // Specify the path of the file



export const getBaseUrl = (urlString: string): string => {
  try {
    const url = new URL(urlString);
    const baseDomain = url.hostname; // Get the base domain
    const protocol = url.protocol; // Get the protocol (includes ':' at the end)

    // Format the output as needed
    const output = {
      protocol: protocol, // e.g., 'https:'
      baseDomain: baseDomain, // e.g., 'www.example.com'
    };

    return protocol + '//' + baseDomain;
  } catch (error) {
    return '';
  }
};

export const getUrlPath = (urlString: string): string => {
  try {
    const url = new URL(urlString);
    const path = url.pathname; // Get the path (e.g., '/path/to/resource')
    const queryString = url.search; // Get the query string (e.g., '?query=parameter')
    const hash = url.hash; // Get the hash (e.g., '#section')

    // Combine the path, query string, and hash into a single string
    const output = path + queryString + hash;

    return output;
  } catch (error) {
    return '';
  }
};

export const rewriteLinks = (response: string, originalUrl: string): string => {
  const originalHost = new URL(originalUrl || '').host;
  // const baseProxyUrl = `http://localhost:3005/proxy?url=`;
  const baseProxyUrl = getPublicHost();
  const hostnameParts = originalHost.split('.');
  const baseDomain = hostnameParts.slice(-2).join('.');

  // 🔹 Skip URLs pointing to static assets (JS, CSS, images, fonts)
  const staticFileExtensions = /\.(js|css|png|jpe?g|gif|svg|woff2?|ttf|eot|ico|mp4|webm|ogg|json|xml)(\?.*)?$/i;

  // 🔹 Rewrite `<a href="...">` links (absolute & relative) unless they are static assets
  response = response.replace(/<a\s+[^>]*?href=["'](https?:\/\/([^"']+))["']/gi, (match, fullUrl, domain) => {
    if (domain.includes(baseDomain) && !staticFileExtensions.test(fullUrl)) {
      console.log('match', match);
      return match.replace(fullUrl, `${baseProxyUrl}${encodeURIComponent(fullUrl)}`);
    }
    return match;
  });

  response = response.replace(/<a\s+[^>]*?href=["'](\/[^"']*)["']/gi, (match, relativePath) => {
    if (!staticFileExtensions.test(relativePath)) {
      return match.replace(relativePath, `${baseProxyUrl}${encodeURIComponent(originalUrl + relativePath)}`);
    }
    return match;
  });

  // 🔹 Rewrite `<form action="...">` links unless they are static assets
  response = response.replace(/<form\s+[^>]*?action=["'](https?:\/\/([^"']+))["']/gi, (match, fullUrl, domain) => {
    if (domain.includes(baseDomain) && !staticFileExtensions.test(fullUrl)) {
      return match.replace(fullUrl, `${baseProxyUrl}${encodeURIComponent(fullUrl)}`);
    }
    return match;
  });

  response = response.replace(/<form\s+[^>]*?action=["'](\/[^"']*)["']/gi, (match, relativePath) => {
    if (!staticFileExtensions.test(relativePath)) {
      return match.replace(relativePath, `${baseProxyUrl}${encodeURIComponent(originalUrl + relativePath)}`);
    }
    return match;
  });

  // 🔹 Rewrite `<iframe src="...">` unless it is a static asset
  response = response.replace(/<iframe\s+[^>]*?src=["'](https?:\/\/([^"']+))["']/gi, (match, fullUrl, domain) => {
    if (domain.includes(baseDomain) && !staticFileExtensions.test(fullUrl)) {
      return match.replace(fullUrl, `${baseProxyUrl}${encodeURIComponent(fullUrl)}`);
    }
    return match;
  });

  // 🔹 Rewrite AJAX / Fetch requests to go through the proxy
  response = response.replace(/fetch\(["'](https?:\/\/([^"']+))["']/gi, (match, fullUrl, domain) => {
    if (domain.includes(baseDomain) && !staticFileExtensions.test(fullUrl)) {
      return match.replace(fullUrl, `${baseProxyUrl}${encodeURIComponent(fullUrl)}`);
    }
    return match;
  });

  // 🔹 Rewrite links inside JSON-like structures: `"url": "https://..."`
  response = response.replace(/"url"\s*:\s*"([^"]+)"/gi, (match, fullUrl) => {
    try {
      const parsedUrl = new URL(fullUrl);
      if (parsedUrl.host.includes(baseDomain) && !staticFileExtensions.test(fullUrl)) {
        return match.replace(fullUrl, `${baseProxyUrl}${encodeURIComponent(fullUrl)}`);
      }
    } catch (e) {
      return match;
    }
    return match;
  });

  return response;
};

export const simpleRewriteLinks = (response: string, originalUrl: string): string => {
  const originalHost = new URL(originalUrl || '').host;
  // const baseProxyUrl = `http://localhost:3005/proxy?url=`;
  // const baseProxyUrl = `http://localhost:3005/proxy/`;
  const hostnameParts = originalHost.split('.');
  const baseDomain = hostnameParts.slice(-2).join('.');
  console.log('baseDomain', baseDomain, 'originalUrl', originalUrl);

  // Regular expression to match URLs (absolute, relative, and JSON-like strings)
  // const urlRegex = /(https?:\/\/[^\s"']+|(?<!http:|https:)\/\/[^\s"']+|(?<!")\/[^\s"']*|:"\/[^\s"']*)/g;
  const urlRegex = /(https?:\/\/[^\s"']+|(?<!http:|https:)\/\/[^\s"']+|\\s*=\s*['"]|:\s*"\/[^\s"']*)/g;

  // Replace URLs with the base domain
  return response.replace(urlRegex, (match) => {
    // console.log('match', match);
    // If the URL is already absolute, leave it as is
    if (match.startsWith('http://') || match.startsWith('https://')) {
      return match;
    }
    // If the URL is protocol-relative (starts with //), prepend https:
    if (match.startsWith('=')) {
      return `="${baseDomain}${match.slice(2)}"`;
    }
    // If the URL is in a JSON-like string (starts with :"/"), remove the `:"` prefix
    if (match.startsWith(':"/')) {
        console.log('match', match, 'rewrite to', `:"${baseDomain}${match.slice(2)}"`);
      return `:"${baseDomain}${match.slice(2)}"`;
    }
    // If the URL is relative, prepend the base domain
    return `${baseDomain}${match}`;
  });
};

function replaceUrlInString(inputString: string): string {
    const oldUrl = 'https://accommodations.booking.com/autocomplete.json';
    const newUrl = `${baseProxyUrl}/proxyUrl?endpoint=` + encodeURIComponent(oldUrl);
    
    // Create a regular expression to match all occurrences of oldUrl
    const regex = new RegExp(oldUrl, 'g');
    
    // Replace all occurrences with the newUrl
    const updatedString = inputString.replace(regex, newUrl);
    
    return updatedString;
}

function removeOriginalDomain(inputString: string): string {
    const oldUrl = ['https://www.booking.com/', 'https://booking.com/'];
    // const newUrl = 'http://localhost:3005/';
    const newUrl = getPublicHost('basePath');
    let updatedString = inputString;
    
    oldUrl.forEach((url) => {
        const regex = new RegExp(url, 'g');
        updatedString = updatedString.replace(regex, newUrl);
        console.log('updatedString', updatedString);
    }
    );
    
    return updatedString;
}

export const directSimpleRewriteLinks = (response: string, originalUrl: string): string => {
    const originalHost = new URL(originalUrl || '').host;
    // const baseProxyUrl = `http://localhost:3005/browse/`;
    const hostnameParts = originalHost.split('.');
    const baseDomain = hostnameParts.slice(-2).join('.');

    writeToLog('doing directSimpleRewriteLinks');

    // replace https://accommodations.booking.com/autocomplete.json with http://localhost:3005/proxyUrl?endpoint=https://accommodations.booking.com/autocomplete.json
    response = replaceUrlInString(response);
    response = removeOriginalDomain(response);

    // Regular expression to match URLs (absolute, relative, and JSON-like strings)
    // const urlRegex = /(https?:\/\/[^\s"']+|(?<!http:|https:)\/\/[^\s"']+|(?<!")\/[^\s"']*|:"\/[^\s"']*)/g;
    // const urlRegex = /(https?:\/\/[^\s"']+|(?<!http:|https:)\/\/[^\s"']+|\\s*=\s*['"]|:\s*"\/[^\s"']*)/g;
    // const urlRegex = /(https?:\/\/[^\s"']+|\="(?<!http:|https:)\/\/[^\s"']+|\\s*=\s*['"]|\="\/[^\/].*|=\s*'\/[^']*'|:\s*"\/[^\s"']*)/g;
    // const urlRegex = /(https?:\/\/[^\s"']+|\="(?<!http:|https:)\/\/[^\s"']+|\\s*=\s*['"]|\="\/[^\/].*|=\s*'\/[^']*'|:\s*"\/[^\s"']*)/g;
    // https:&#47;&#47;
    const urlRegex = /(https?:\/\/[^\s"']+|https?:&#47;&#47;[^\s"']+|\="(?<!http:|https:)\/\/[^\s"']+|\\s*=\s*['"]|\="\/[^\/].*|=\s*'\/[^']*'|:\s*"\/[^\s"']*)/g;
    // <anysubdomain>.baseDomain.com
    // const subdomain = new RegExp(`(https?://)?([a-zA-Z0-9-]+\\.)?${baseDomain}`, 'g');
    const subdomain = new RegExp(`(https?:\/\/)?([a-zA-Z0-9-]+\\.)?booking.com`, 'g');

    // Replace URLs with the base domain
    return response.replace(urlRegex, (match) => {
        // 🔹 Skip URLs pointing to static assets (JS, CSS, images, fonts)
        const staticFileExtensions = /\.(js|css|png|jpe?g|jpg|jpeg|gif|svg|woff2?|ttf|eot|ico|mp4|webm|ogg|json|xml|webp|pdf|js_tracking)(\?.*)?$/i;
        const nonStaticFileIgnores = /(\/svg|js_tracking|cf.bstatic.com)(\?.*)?$/i;
        if (match.includes('_etnht')) {
          
          writeToLog(`MATCH FOUND: ${match}`);
          // return match.replace('.ngrok-free.app_', '.ngrok-free.app/browse/https://www.booking.com/_');
          return match.replace('.ngrok-free.app_', 'https://www.booking.com/_');
        } 
        if (staticFileExtensions.test(match) || nonStaticFileIgnores.test(match)) {
          // const dataToAppend = `${new Date().toISOString()} - staticFileExtension MATCHED: ${match}`;
          // fs.appendFile(pageLoadLogs, dataToAppend + '\n', (err) => {    });
          return match;
        }

        if (match.includes('_etnht')) {
          
          writeToLog(`resulting in match: ${match}`);
        } 

        const removeLogo = /\/(logo)(\?.*?)?(?=\s*")/i;
        if (removeLogo.test(match)) {
          const removed = match.replace(removeLogo, '');
          const dataToAppend = `${new Date().toISOString()} - LOGO MATCHED: ${match} rewritten to ${removed}`;
          fs.appendFile(pageLoadLogs, dataToAppend + '\n', (err) => {    });
          return removed;
        }

        if (match.includes('uri=')) {
          writeToLog(`replacing uri= in match: ${match}`);
          match = match.replace('uri=', `uri=${encodeURIComponent(getPublicHost('basePath'))}`);
          writeToLog(`resulting in match: ${match}`);
        }

        // console.log('match', match);

        // if subdomain of baseDomain
        // not working correctly
        // if (subdomain.test(match)) {
        //     console.log('subdomain matched', match)
        //     return match.replace(subdomain, 'http://localhost:3005');
        // }

        if (match.includes('https://ch.booking.com')) {
          // writeToLog(`replacing ch.booking.com, match: ${match}`);
          return match.replace('https://ch.booking.com', getPublicHost('basePath'));
        }
        
        // If the URL is already absolute, leave it as is
        // if ((match.startsWith('http://') || match.startsWith('https://') ) && !match.includes('localhost')) {
        if ((match.startsWith('http://') || match.startsWith('https://') ) && !match.startsWith(getPublicHost('basePath'))) {
            // if(match.includes('account')) {
            //   writeToLog(`http(s):// MATCHED: ${match} rewrite to: ${baseProxyUrl}/browse/${match}`);
            // }
            return `${baseProxyUrl}/browse/${match}`;
            return match;
        }

        // https:&#47;&#47;
        // if ((match.startsWith('http:&#47;&#47;') || match.startsWith('https:&#47;&#47;') ) && !match.includes('localhost')) {
        if ((match.startsWith('http:&#47;&#47;') || match.startsWith('https:&#47;&#47;') ) && !match.startsWith(encodeURI(getPublicHost('basePath')))) {
          if(match.includes('account')) {
            writeToLog(`http(s):https:&#47;&#47; MATCHED: ${match} rewrite to: ${baseProxyUrl}/browse/${match}`);
          }
          return `${baseProxyUrl}/browse/${match}`;
          return match;
      }

        // If the URL is protocol-relative (starts with //), prepend https:
        if (match.startsWith('=')) {
            // console.log('match', match, 'rewrite to', `:"${baseDomain}${match.slice(2)}"`);
            // writeToLog(`EQUAL SIGN FOUND rewriting to: "${baseDomain}${match.slice(2)}"`);
            writeToLog(`EQUAL SIGN FOUND leaving as is: ${match}`);
            // return `="${baseDomain}${match.slice(2)}"`;
            return match;
        }

         // If the URL is relative (starts with /), prepend proxyBaseUrl:
        if (/^\/[^\/].*/.test(match)) {
          console.log('Replacing relative url match', match, 'rewrite to', `:"${baseDomain}${match.slice(2)}"`);
          return `="${baseDomain}${match.slice(2)}"`;
        }

        // If the URL is in a JSON-like string (starts with :"/"), remove the `:"` prefix
        // if (match.startsWith(':"/')) {
        if (/:\s*"\/[^\s"']/.test(match)) {
            // writeToLog(`JSON MATCHED: ${match} rewrite to: ${baseProxyUrl}/browse/${match}`);
            // console.log('match', match, 'rewrite to', `:"https://www.${baseDomain}${match.slice(3)}`);
            return `:"https://www.${baseDomain}${match.slice(3)}`;
        }

        // If the URL is in a JSON-like string prepend the proxyBaseUrl
        if (/:\s*"(https?:\/\/[^"\s]*)"/.test(match)) {
            writeToLog(`JSON MATCHED: ${match} rewrite to: ${match.replace(/:\s*"(https?:\/\/[^"\s]*)"/, `:"${baseProxyUrl}/browse/${match}`)}`);
            return match.replace(/:\s*"(https?:\/\/[^"\s]*)"/, `:"${baseProxyUrl}/browse/${match}`);
        }

        // writeToLog(`last point reached, REPLACING URL: ${match} rewrite to: ${baseProxyUrl}${match}`);
        return match;
        // If the URL is relative, prepend the base domain
        return `${baseDomain}${match}`;
    });
};
