import path from "node:path";
import react from "@vitejs/plugin-react";
import { createLogger, defineConfig } from "vite";
import inlineEditPlugin from "./plugins/visual-editor/vite-plugin-react-inline-editor.js";
import editModeDevPlugin from "./plugins/visual-editor/vite-plugin-edit-mode.js";
import iframeRouteRestorationPlugin from "./plugins/vite-plugin-iframe-route-restoration.js";
import selectionModePlugin from "./plugins/selection-mode/vite-plugin-selection-mode.js";

const isDev = process.env.NODE_ENV !== "production";

// Configuration des origines autorisées pour postMessage
// En production, définir via variable d'environnement
const ALLOWED_PARENT_ORIGINS = isDev
  ? [
      "http://localhost:3000",
      "http://localhost:5173",
      "https://prod.dataven.fr",
    ]
  : (
      process.env.VITE_ALLOWED_PARENT_ORIGINS || "https://prod.dataven.fr"
    ).split(",");

// Utilitaire pour postMessage sécurisé avec handshake
const configSecurePostMessage = `
(function() {
  const ALLOWED_ORIGINS = ${JSON.stringify(ALLOWED_PARENT_ORIGINS)};
  let verifiedParentOrigin = null;
  let isEmbedded = false;

  // Détecter si on est dans une iframe
  try {
    isEmbedded = window.self !== window.top;
  } catch (e) {
    isEmbedded = true; // Erreur de cross-origin = on est dans une iframe
  }

  // Écouter le handshake du parent
  window.addEventListener('message', (event) => {
    if (!ALLOWED_ORIGINS.includes(event.origin)) {
      return; // Ignorer les origines non autorisées
    }

    if (event.data?.type === 'HORIZONS_HANDSHAKE') {
      verifiedParentOrigin = event.origin;
      // Confirmer le handshake
      window.parent.postMessage({ type: 'HORIZONS_HANDSHAKE_ACK' }, event.origin);
    }
  });

  // Fonction sécurisée pour envoyer des messages au parent
  window.__securePostMessage = function(payload) {
    if (!isEmbedded) return;
    
    if (!verifiedParentOrigin) {
      // En attente de handshake, stocker temporairement (optionnel)
      console.debug('[SecurePostMessage] No verified parent origin yet');
      return;
    }

    // Sanitiser le payload avant envoi
    const sanitizedPayload = sanitizePayload(payload);
    window.parent.postMessage(sanitizedPayload, verifiedParentOrigin);
  };

  // Sanitisation du payload
  function sanitizePayload(payload) {
    const sanitized = { ...payload };
    
    ${
      isDev
        ? `
    // En DEV: conserver les détails pour le debugging
    return sanitized;
    `
        : `
    // En PROD: supprimer les infos sensibles
    if (sanitized.error) {
      // Remplacer la stack trace par un ID de corrélation
      sanitized.errorId = generateCorrelationId();
      sanitized.error = sanitized.error.split('\\n')[0]; // Garder uniquement la première ligne
      delete sanitized.stack;
    }
    
    // Ne pas exposer les URLs internes ou les détails de réponse
    if (sanitized.url) {
      sanitized.url = '[REDACTED]';
    }
    
    return sanitized;
    `
    }
  }

  function generateCorrelationId() {
    return 'err_' + Date.now().toString(36) + Math.random().toString(36).substr(2, 9);
  }

  // Exposer pour vérification
  window.__isSecureMessagingReady = () => !!verifiedParentOrigin;
})();
`;

// Handler d'erreurs Vite sécurisé
const configHorizonsViteErrorHandler = `
const observer = new MutationObserver((mutations) => {
  for (const mutation of mutations) {
    for (const addedNode of mutation.addedNodes) {
      if (
        addedNode.nodeType === Node.ELEMENT_NODE &&
        (addedNode.tagName?.toLowerCase() === 'vite-error-overlay' ||
         addedNode.classList?.contains('backdrop'))
      ) {
        handleViteOverlay(addedNode);
      }
    }
  }
});

observer.observe(document.documentElement, { childList: true, subtree: true });

function handleViteOverlay(node) {
  if (!node.shadowRoot) return;

  const backdrop = node.shadowRoot.querySelector('.backdrop');
  if (!backdrop) return;

  const messageBodyElement = backdrop.querySelector('.message-body');
  const messageText = messageBodyElement ? messageBodyElement.textContent.trim() : '';
  
  // Utiliser la fonction sécurisée
  window.__securePostMessage?.({
    type: 'horizons-vite-error',
    error: messageText,
    timestamp: Date.now()
  });
}
`;

// Handler d'erreurs runtime sécurisé
const configHorizonsRuntimeErrorHandler = `
window.onerror = (message, source, lineno, colno, errorObj) => {
  ${
    isDev
      ? `
  // DEV: Détails complets pour debugging
  const errorDetails = errorObj ? {
    name: errorObj.name,
    message: errorObj.message,
    stack: errorObj.stack,
    source,
    lineno,
    colno,
  } : null;
  `
      : `
  // PROD: Informations minimales
  const errorDetails = errorObj ? {
    name: errorObj.name,
    message: errorObj.message?.substring(0, 100), // Tronquer
  } : null;
  `
  }

  window.__securePostMessage?.({
    type: 'horizons-runtime-error',
    message: typeof message === 'string' ? message.substring(0, 200) : 'Unknown error',
    error: errorDetails,
    timestamp: Date.now()
  });
};
`;

// Handler console.error sécurisé
const configHorizonsConsoleErrorHandler = `
const originalConsoleError = console.error;
console.error = function(...args) {
  originalConsoleError.apply(console, args);

  ${
    isDev
      ? `
  // DEV: Logger les détails
  let errorString = '';
  for (const arg of args) {
    if (arg instanceof Error) {
      errorString = arg.stack || \`\${arg.name}: \${arg.message}\`;
      break;
    }
  }
  if (!errorString) {
    errorString = args.map(arg => 
      typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
    ).join(' ');
  }
  `
      : `
  // PROD: Message générique uniquement
  let errorString = 'An error occurred';
  for (const arg of args) {
    if (arg instanceof Error) {
      errorString = arg.name + ': ' + (arg.message || '').substring(0, 50);
      break;
    }
  }
  `
  }

  window.__securePostMessage?.({
    type: 'horizons-console-error',
    error: errorString,
    timestamp: Date.now()
  });
};
`;

// Monkey patch fetch sécurisé
const configWindowFetchMonkeyPatch = `
const originalFetch = window.fetch;

window.fetch = function(...args) {
  const url = args[0] instanceof Request ? args[0].url : args[0];

  // Skip WebSocket URLs
  if (url.startsWith('ws:') || url.startsWith('wss:')) {
    return originalFetch.apply(this, args);
  }

  return originalFetch.apply(this, args)
    .then(async response => {
      const contentType = response.headers.get('Content-Type') || '';
      const isDocumentResponse =
        contentType.includes('text/html') ||
        contentType.includes('application/xhtml+xml');

      if (!response.ok && !isDocumentResponse) {
        ${
          isDev
            ? `
        // DEV: Logger le contenu de l'erreur
        const responseClone = response.clone();
        const errorFromRes = await responseClone.text();
        console.error(\`Fetch error from \${response.url}: \${errorFromRes}\`);
        `
            : `
        // PROD: Ne pas exposer le contenu de la réponse
        console.error(\`Fetch error: \${response.status}\`);
        `
        }
      }
      return response;
    })
    .catch(error => {
      if (!url.match(/\\.html?$/i)) {
        ${
          isDev
            ? `
        console.error(error);
        `
            : `
        // PROD: Ne pas exposer l'URL ou les détails
        console.error('Network request failed');
        `
        }
      }
      throw error;
    });
};
`;

// Handler de navigation sécurisé
const configNavigationHandler = `
if (window.navigation && window.self !== window.top) {
  window.navigation.addEventListener('navigate', (event) => {
    const url = event.destination.url;

    try {
      const destinationUrl = new URL(url);
      const currentOrigin = window.location.origin;

      if (destinationUrl.origin === currentOrigin) {
        return;
      }
    } catch (error) {
      return;
    }

    window.__securePostMessage?.({
      type: 'horizons-navigation-error',
      ${isDev ? `url,` : `url: '[external]',`}
      timestamp: Date.now()
    });
  });
}
`;

const addTransformIndexHtml = {
  name: "add-transform-index-html",
  transformIndexHtml(html) {
    const tags = [
      // Le script de postMessage sécurisé doit être chargé EN PREMIER
      {
        tag: "script",
        attrs: { type: "module" },
        children: configSecurePostMessage,
        injectTo: "head-prepend", // Avant tous les autres scripts
      },
      {
        tag: "script",
        attrs: { type: "module" },
        children: configHorizonsRuntimeErrorHandler,
        injectTo: "head",
      },
      {
        tag: "script",
        attrs: { type: "module" },
        children: configHorizonsViteErrorHandler,
        injectTo: "head",
      },
      {
        tag: "script",
        attrs: { type: "module" },
        children: configHorizonsConsoleErrorHandler,
        injectTo: "head",
      },
      {
        tag: "script",
        attrs: { type: "module" },
        children: configWindowFetchMonkeyPatch,
        injectTo: "head",
      },
      {
        tag: "script",
        attrs: { type: "module" },
        children: configNavigationHandler,
        injectTo: "head",
      },
    ];

    if (
      !isDev &&
      process.env.TEMPLATE_BANNER_SCRIPT_URL &&
      process.env.TEMPLATE_REDIRECT_URL
    ) {
      tags.push({
        tag: "script",
        attrs: {
          src: process.env.TEMPLATE_BANNER_SCRIPT_URL,
          "template-redirect-url": process.env.TEMPLATE_REDIRECT_URL,
        },
        injectTo: "head",
      });
    }

    return { html, tags };
  },
};

console.warn = () => {};

const logger = createLogger();
const loggerError = logger.error;

logger.error = (msg, options) => {
  if (options?.error?.toString().includes("CssSyntaxError: [postcss]")) {
    return;
  }
  loggerError(msg, options);
};

export default defineConfig({
  customLogger: logger,
  plugins: [
    ...(isDev
      ? [
          inlineEditPlugin(),
          editModeDevPlugin(),
          iframeRouteRestorationPlugin(),
          selectionModePlugin(),
        ]
      : []),
    react(),
    addTransformIndexHtml,
  ],
  server: {
    cors: true,
    headers: {
      "Cross-Origin-Embedder-Policy": "credentialless",
      // Ajouter CSP pour frame-ancestors si l'app ne doit pas être iframée
      // ou limiter aux origines autorisées
      ...(isDev
        ? {}
        : {
            "Content-Security-Policy": `frame-ancestors ${ALLOWED_PARENT_ORIGINS.join(
              " "
            )}`,
            "X-Frame-Options": "SAMEORIGIN", // Fallback pour anciens navigateurs
          }),
    },
    allowedHosts: true,
    hmr: { overlay: false },
    watch: { usePolling: true, ignored: ["**/.git/**"] },
  },
  optimizeDeps: { force: true },
  // esbuild: {
  //   loader: 'jsx',
  //   include: /\.js$/,
  // },
  resolve: {
    extensions: [".jsx", ".js", ".tsx", ".ts", ".json"],
    alias: { "@": path.resolve(__dirname, "./src") },
  },
  build: {
    rollupOptions: {
      external: [
        "@babel/parser",
        "@babel/traverse",
        "@babel/generator",
        "@babel/types",
      ],
    },
  },
  cacheDir: "node_modules/.vite",
});

// import path from 'node:path';
// import react from '@vitejs/plugin-react';
// import { createLogger, defineConfig } from 'vite';
// import inlineEditPlugin from './plugins/visual-editor/vite-plugin-react-inline-editor.js';
// import editModeDevPlugin from './plugins/visual-editor/vite-plugin-edit-mode.js';
// import iframeRouteRestorationPlugin from './plugins/vite-plugin-iframe-route-restoration.js';
// import selectionModePlugin from './plugins/selection-mode/vite-plugin-selection-mode.js';

// const isDev = process.env.NODE_ENV !== 'production';

// const configHorizonsViteErrorHandler = `
// const observer = new MutationObserver((mutations) => {
// 	for (const mutation of mutations) {
// 		for (const addedNode of mutation.addedNodes) {
// 			if (
// 				addedNode.nodeType === Node.ELEMENT_NODE &&
// 				(
// 					addedNode.tagName?.toLowerCase() === 'vite-error-overlay' ||
// 					addedNode.classList?.contains('backdrop')
// 				)
// 			) {
// 				handleViteOverlay(addedNode);
// 			}
// 		}
// 	}
// });

// observer.observe(document.documentElement, {
// 	childList: true,
// 	subtree: true
// });

// function handleViteOverlay(node) {
// 	if (!node.shadowRoot) {
// 		return;
// 	}

// 	const backdrop = node.shadowRoot.querySelector('.backdrop');

// 	if (backdrop) {
// 		const overlayHtml = backdrop.outerHTML;
// 		const parser = new DOMParser();
// 		const doc = parser.parseFromString(overlayHtml, 'text/html');
// 		const messageBodyElement = doc.querySelector('.message-body');
// 		const fileElement = doc.querySelector('.file');
// 		const messageText = messageBodyElement ? messageBodyElement.textContent.trim() : '';
// 		const fileText = fileElement ? fileElement.textContent.trim() : '';
// 		const error = messageText + (fileText ? ' File:' + fileText : '');

// 		window.parent.postMessage({
// 			type: 'horizons-vite-error',
// 			error,
// 		}, '*');
// 	}
// }
// `;

// const configHorizonsRuntimeErrorHandler = `
// window.onerror = (message, source, lineno, colno, errorObj) => {
// 	const errorDetails = errorObj ? JSON.stringify({
// 		name: errorObj.name,
// 		message: errorObj.message,
// 		stack: errorObj.stack,
// 		source,
// 		lineno,
// 		colno,
// 	}) : null;

// 	window.parent.postMessage({
// 		type: 'horizons-runtime-error',
// 		message,
// 		error: errorDetails
// 	}, '*');
// };
// `;

// const configHorizonsConsoleErrroHandler = `
// const originalConsoleError = console.error;
// console.error = function(...args) {
// 	originalConsoleError.apply(console, args);

// 	let errorString = '';

// 	for (let i = 0; i < args.length; i++) {
// 		const arg = args[i];
// 		if (arg instanceof Error) {
// 			errorString = arg.stack || \`\${arg.name}: \${arg.message}\`;
// 			break;
// 		}
// 	}

// 	if (!errorString) {
// 		errorString = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
// 	}

// 	window.parent.postMessage({
// 		type: 'horizons-console-error',
// 		error: errorString
// 	}, '*');
// };
// `;

// const configWindowFetchMonkeyPatch = `
// const originalFetch = window.fetch;

// window.fetch = function(...args) {
// 	const url = args[0] instanceof Request ? args[0].url : args[0];

// 	// Skip WebSocket URLs
// 	if (url.startsWith('ws:') || url.startsWith('wss:')) {
// 		return originalFetch.apply(this, args);
// 	}

// 	return originalFetch.apply(this, args)
// 		.then(async response => {
// 			const contentType = response.headers.get('Content-Type') || '';

// 			// Exclude HTML document responses
// 			const isDocumentResponse =
// 				contentType.includes('text/html') ||
// 				contentType.includes('application/xhtml+xml');

// 			if (!response.ok && !isDocumentResponse) {
// 					const responseClone = response.clone();
// 					const errorFromRes = await responseClone.text();
// 					const requestUrl = response.url;
// 					console.error(\`Fetch error from \${requestUrl}: \${errorFromRes}\`);
// 			}

// 			return response;
// 		})
// 		.catch(error => {
// 			if (!url.match(/\.html?$/i)) {
// 				console.error(error);
// 			}

// 			throw error;
// 		});
// };
// `;

// const configNavigationHandler = `
// if (window.navigation && window.self !== window.top) {
// 	window.navigation.addEventListener('navigate', (event) => {
// 		const url = event.destination.url;

// 		try {
// 			const destinationUrl = new URL(url);
// 			const destinationOrigin = destinationUrl.origin;
// 			const currentOrigin = window.location.origin;

// 			if (destinationOrigin === currentOrigin) {
// 				return;
// 			}
// 		} catch (error) {
// 			return;
// 		}

// 		window.parent.postMessage({
// 			type: 'horizons-navigation-error',
// 			url,
// 		}, '*');
// 	});
// }
// `;

// const addTransformIndexHtml = {
// 	name: 'add-transform-index-html',
// 	transformIndexHtml(html) {
// 		const tags = [
// 			{
// 				tag: 'script',
// 				attrs: { type: 'module' },
// 				children: configHorizonsRuntimeErrorHandler,
// 				injectTo: 'head',
// 			},
// 			{
// 				tag: 'script',
// 				attrs: { type: 'module' },
// 				children: configHorizonsViteErrorHandler,
// 				injectTo: 'head',
// 			},
// 			{
// 				tag: 'script',
// 				attrs: {type: 'module'},
// 				children: configHorizonsConsoleErrroHandler,
// 				injectTo: 'head',
// 			},
// 			{
// 				tag: 'script',
// 				attrs: { type: 'module' },
// 				children: configWindowFetchMonkeyPatch,
// 				injectTo: 'head',
// 			},
// 			{
// 				tag: 'script',
// 				attrs: { type: 'module' },
// 				children: configNavigationHandler,
// 				injectTo: 'head',
// 			},
// 		];

// 		if (!isDev && process.env.TEMPLATE_BANNER_SCRIPT_URL && process.env.TEMPLATE_REDIRECT_URL) {
// 			tags.push(
// 				{
// 					tag: 'script',
// 					attrs: {
// 						src: process.env.TEMPLATE_BANNER_SCRIPT_URL,
// 						'template-redirect-url': process.env.TEMPLATE_REDIRECT_URL,
// 					},
// 					injectTo: 'head',
// 				}
// 			);
// 		}

// 		return {
// 			html,
// 			tags,
// 		};
// 	},
// };

// console.warn = () => {};

// const logger = createLogger()
// const loggerError = logger.error

// logger.error = (msg, options) => {
// 	if (options?.error?.toString().includes('CssSyntaxError: [postcss]')) {
// 		return;
// 	}

// 	loggerError(msg, options);
// }

// export default defineConfig({
// 	customLogger: logger,
// 	plugins: [
// 		...(isDev ? [inlineEditPlugin(), editModeDevPlugin(), iframeRouteRestorationPlugin(), selectionModePlugin()] : []),
// 		react(),
// 		addTransformIndexHtml
// 	],
// 	server: {
// 		cors: true,
// 		headers: {
// 			'Cross-Origin-Embedder-Policy': 'credentialless',
// 		},
// 		allowedHosts: true,
// 		// watch: {
// 		// 	ignored: ['**/.git/**']
// 		// },
// 		hmr: {
// 			overlay: true, // Afficher les erreurs en overlay
// 		},
// 		watch: {
// 			usePolling: true, // Utile sur certains systèmes
// 		}
// 	},
// 	optimizeDeps: {
// 		force: true, // Force la ré-optimisation des dépendances
// 	},
// 	resolve: {
// 		extensions: ['.jsx', '.js', '.tsx', '.ts', '.json', ],
// 		alias: {
// 			'@': path.resolve(__dirname, './src'),
// 		},
// 	},
// 	build: {
// 		rollupOptions: {
// 			external: [
// 				'@babel/parser',
// 				'@babel/traverse',
// 				'@babel/generator',
// 				'@babel/types'
// 			]
// 		}
// 	},
// 	// optimizeDeps: {
// 	// 	exclude: ['.git']
// 	// },
// 	// Vider le cache au démarrage si nécessaire
//   	cacheDir: 'node_modules/.vite',
// });
