import { IncomingMessage, ServerResponse } from 'http';
import { ClientRequest as ProxyRequest, IncomingMessage as ProxyResponse } from 'http';
import { Response } from 'express';
import zlib from 'zlib';
import fs from 'fs';
import path from 'path';
import { simpleRewriteLinks } from '../helpers/helpers';

export const proxyReqHandler = (req: IncomingMessage, proxyReq: ProxyRequest) => {
    // Forward necessary headers for requests to the target URL
    proxyReq.setHeader('User-Agent', req.headers['user-agent'] || '');
    proxyReq.setHeader('Accept-Language', req.headers['accept-language'] || '');
    proxyReq.setHeader('Cookie', req.headers['cookie'] || ''); // Ensure cookies are forwarded
};


export const proxyResHandler = (proxyRes: ProxyResponse, req: IncomingMessage, res: ServerResponse<IncomingMessage>, originalUrl: string) => {

    if (proxyRes.statusCode && proxyRes.statusCode >= 300 && proxyRes.statusCode < 400) {
        const location = proxyRes.headers['location'];
    
        if (location) {
          try {
            const targetUrl = new URL(location);
            // const proxyBase = `http://localhost:3005/proxy?url=`;
            const proxyBase = `http://localhost:3005/proxy/`;
            const proxiedRedirect = `${proxyBase}${encodeURIComponent(targetUrl.href)}`;
    
            console.log(`Redirect intercepted: ${location} -> ${proxiedRedirect}`);
    
            res.writeHead(proxyRes.statusCode, { Location: proxiedRedirect });
            res.end();
            return;
          } catch (err) {
            console.error('Failed to parse redirect URL:', location, err);
          }
        }
      }
    
      let body: Buffer[] = [];
      delete proxyRes.headers['content-length'];
    
      proxyRes.on('data', (chunk: Buffer) => {
        body.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
      });
    
      proxyRes.on('end', () => {
        let rawBody = Buffer.concat(body);
    
        // Handle decompression safely
        try {
          if (proxyRes.headers['content-encoding']) {
            if (proxyRes.headers['content-encoding'].includes('gzip')) {
              rawBody = zlib.gunzipSync(rawBody);
            } else if (proxyRes.headers['content-encoding'].includes('br')) {
              rawBody = zlib.brotliDecompressSync(rawBody);
            } else if (proxyRes.headers['content-encoding'].includes('deflate')) {
              rawBody = zlib.inflateSync(rawBody);
            }
    
            delete proxyRes.headers['content-encoding']; // Let the browser handle plain text
          }
        } catch (err) {
          console.error('Decompression failed:', err);
        }
    
        // Modify HTML only
        const contentType = proxyRes.headers['content-type'] || '';
        if (contentType.includes('text/html')) {
          let response = rawBody.toString('utf8');
          const filePath = path.join(__dirname, 'original_response.html');
          fs.writeFile(filePath, response, (err) => {
            if (err) {
                console.error('Error writing to file', err);
              }
            console.error('Successtully writing response to file', err);
        });
    
        // Debugging
        console.log("Received HTML Length:", response.length);
        console.log('checking if __NEXT_DATA__ exists in response:');
        if (!rawBody.toString().includes('__NEXT_DATA__')) {
          console.warn("🚨 __NEXT_DATA__ is missing from final response! 🚨");
        } else {
          console.log("✅ __NEXT_DATA__ exists in final response.");
        }
    
          // const oU = originalUrl || 'https://www.bosch-diy.com';
          // if (originalUrl) {
          //   const baseOriginalUrl = getBaseUrl(originalUrl);
          //   const rewrittenUrl = originalUrl ? `${baseUrl}${baseOriginalUrl}` : '';
          //   // Add a <base> tag to ensure relative URLs resolve correctly
          //   response = response.replace(/<head>/, `<head><base href="${rewrittenUrl}">`);
    
    
          //   // Rewrite only relative URLs to absolute URLs
          //   response = response.replace(/(href|src)="\/([^"]+)"/g, `$1="${rewrittenUrl}/$2"`);
          // }
    
          // const originalHost = new URL(originalUrl || '').host;
          // const baseProxyUrl = `http://localhost:3005/proxy?url=`;
          // // 🔹 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 to go through the proxy
          // console.log('Rewriting absolute <a href="..."> links');
          // response = response.replace(
          //   /<a\s+[^>]*?href=["'](https?:\/\/([^"']+))["']/gi,
          //   (match, fullUrl, domain) => {
          //     if (domain.includes(originalHost) && !staticFileExtensions.test(fullUrl)) {
          //       return match.replace(fullUrl, `${baseProxyUrl}${encodeURIComponent(fullUrl)}`);
          //     }
          //     return match;
          //   }
          // );
    
          // // 🔹 Rewrite relative <a href="..."> links (e.g., /page.html) to absolute via the proxy
          // console.log('Rewriting relative <a href="..."> links');
          // 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="..."> to go through the proxy
          // console.log('Rewriting forms <form action="..."> links');
          // response = response.replace(
          //   /<form\s+[^>]*?action=["'](https?:\/\/([^"']+))["']/gi,
          //   (match, fullUrl, domain) => {
          //     if (domain.includes(originalHost) && !staticFileExtensions.test(fullUrl)) {
          //       return match.replace(fullUrl, `${baseProxyUrl}${encodeURIComponent(fullUrl)}`);
          //     }
          //     return match;
          //   }
          // );
    
          // // 🔹 Rewrite relative <form action="..."> paths
          // response = response.replace(
          //   /<form\s+[^>]*?action=["'](\/[^"']*)["']/gi,
          //   (match, relativePath) => {
          //     return match.replace(relativePath, `${baseProxyUrl}${encodeURIComponent(originalUrl + relativePath)}`);
          //   }
          // );
    
        response = simpleRewriteLinks(response, originalUrl);
    
          fs.writeFile(filePath, response, (err) => {
            if (err) {
                console.error('Error writing to file', err);
              }
            console.error('Successtully writing response to file', err);
        });
    
          // force all internal navigation to go trough the proxy
          const overrideScript = `
            <script>
              (function() {
                const originalPushState = window.history.pushState;
                const originalReplaceState = window.history.replaceState;
    
                function sanitizeUrl(url) {
                  if (!url.startsWith('/') && !url.startsWith(window.location.origin)) {
                    console.warn('🔍 Blocking navigation to external URL:', url);
                    return window.location.pathname; // Stay on the same page
                  }
                  return url;
                }
    
                window.history.pushState = function(state, title, url) {
                  return originalPushState.call(this, state, title, sanitizeUrl(url));
                };
    
                window.history.replaceState = function(state, title, url) {
                  return originalReplaceState.call(this, state, title, sanitizeUrl(url));
                };
              })();
            </script>`;
    
          const overrideScriptToSolvePushState_orig = `
            <script>
              (function() {
                function sanitizeUrl(url) {
                  // If the URL is trying to go to another origin, block it
                  if (!url.startsWith(window.location.origin)) {
                    console.warn('🚫 Blocking cross-origin replaceState:', url);
                    return window.location.pathname; // Stay on the same page
                  }
                  return url;
                }
    
                function overrideHistoryMethod(method) {
                  const original = history[method];
    
                  Object.defineProperty(history, method, {
                    configurable: false,
                    enumerable: false,
                    writable: false,
                    value: function(state, title, url) {
                      const safeUrl = sanitizeUrl(url);
                      try {
                        return original.call(this, state, title, safeUrl);
                      } catch (e) {
                        console.error(\`❌ History. error prevented:\`, e);
                      }
                    }
                  });
                }
    
                overrideHistoryMethod('replaceState');
                overrideHistoryMethod('pushState');
    
                console.log('✅ History override (Object.defineProperty) injected');
              })();
            </script>`;
    
          const overrideScriptToSolvePushState = `
            <script>
      (function() {
        console.log('✅ Injecting domain and history overrides...');
    
        // Override history.replaceState to prevent cross-origin errors
        const originalReplaceState = window.history.replaceState;
        window.history.replaceState = function(state, title, url) {
          try {
            if (url && url.startsWith("https://www.bosch-diy.com")) {
              console.warn("🚨 Prevented replaceState to", url);
              return;
            }
            originalReplaceState.apply(this, arguments);
            console.log("✅ replaceState called with:", state, title, url);
          } catch (e) {
            console.error("❌ Error in replaceState override:", e);
          }
        };
    
        console.log("✅ history.replaceState overridden successfully");
      })();
            </script>`;
    
          const fixDomainScript = `
            <script>
              console.log('✅ Injecting document.domain fix...');
    
              try {
                document.domain = "localhost";
                console.log("✅ document.domain set to localhost");
              } catch (e) {
                console.warn("❌ Unable to set document.domain:", e);
              }
            </script>`;
    
          console.log("🔹 Adding override script to response");
          response = response.replace('</head>', `${overrideScriptToSolvePushState}${fixDomainScript}${overrideScript}</head>`);
    
    
          rawBody = Buffer.from(response, 'utf8');
    
          const encoding = proxyRes.headers['content-encoding'] || '';
          console.log("🔄 Encoding Type:", encoding);
    
          if (encoding.includes('gzip')) {
            rawBody = zlib.gunzipSync(rawBody);
          } else if (encoding.includes('br')) {
            rawBody = zlib.brotliDecompressSync(rawBody);
          } else if (encoding.includes('deflate')) {
            rawBody = zlib.inflateSync(rawBody);
          }
    
          delete proxyRes.headers['content-encoding']; // Remove encoding header
          if (proxyRes.headers['set-cookie']) {
            proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map((cookie: string) =>
              cookie.replace(/Domain=\.?bosch-diy\.com/gi, 'Domain=localhost').replace(/Secure;/gi, '') // Remove Secure for local dev
            );
          }
          if (proxyRes.headers['content-security-policy']) {
            delete proxyRes.headers['content-security-policy']; // Remove CSP
          }
          if (proxyRes.headers['content-security-policy-report-only']) {
            delete proxyRes.headers['content-security-policy-report-only']; // Remove CSP report-only mode
          }
        }
    
        // 🔹 Set CORS headers dynamically for all responses
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
        res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
        res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate, proxy-revalidate');
        res.setHeader('Pragma', 'no-cache');
        res.setHeader('Expires', '0');
    
        res.writeHead(proxyRes.statusCode || 200, proxyRes.headers);
        res.end(rawBody);
      });

}