#!/usr/bin/env node
/**
 * IP Leak Validation Script
 *
 * Scans the extension bundle for potential IP leaks before publishing to marketplace.
 * This script should be run as part of the pre-publish workflow.
 *
 * Checks for:
 * 1. Proprietary algorithm patterns (velocity thresholds, detection formulas)
 * 2. THREAT_PATTERNS exposure (security detection regexes)
 * 3. AI_TOOLS dictionary (if not obfuscated)
 * 4. Confidence scoring constants
 * 5. Source maps accidentally included
 * 6. Comments revealing implementation details
 *
 * @usage
 * node scripts/validate-ip-protection.js
 * pnpm run validate:ip
 */

const fs = require("node:fs");
const path = require("node:path");

// =============================================================================
// Configuration
// =============================================================================

const CONFIG = {
	bundlePath: path.join(__dirname, "..", "dist", "extension.js"),
	maxPatternMatches: 0, // Any match is a failure for critical patterns
	warningThreshold: 3, // Warn if more than N suspicious patterns
};

// =============================================================================
// IP Leak Patterns
// =============================================================================

/**
 * CRITICAL patterns - Any match is a failure
 * These indicate proprietary algorithm exposure
 */
const CRITICAL_PATTERNS = [
	{
		name: "Velocity threshold exposure",
		pattern: /velocityThreshold\s*[:=]\s*\d+/gi,
		description: "AI detection velocity threshold value exposed",
	},
	{
		name: "AI_TOOLS dictionary",
		pattern: /AI_TOOLS\s*[:=]\s*\{[^}]*github\.copilot[^}]*\}/gi,
		description: "AI tools identification dictionary exposed",
	},
	{
		name: "THREAT_PATTERNS dictionary",
		pattern: /THREAT_PATTERNS\s*[:=]\s*\{/gi,
		description: "Security threat detection patterns exposed",
	},
	{
		name: "Detection confidence formula",
		pattern: /confidence\s*[:=]\s*Math\.(min|max)\s*\([^)]*0\.\d+/gi,
		description: "Confidence scoring algorithm exposed",
	},
	{
		name: "Complexity scoring weights",
		pattern: /patternComplexity\s*\+=\s*Math\.min\s*\(\s*0\.\d+/gi,
		description: "Complexity scoring formula exposed",
	},
	{
		name: "SimHash algorithm",
		pattern: /simhash|SimHash|similarity64/gi,
		description: "Fingerprinting algorithm reference exposed",
	},
];

/**
 * WARNING patterns - May indicate issues but not automatic failures
 */
const WARNING_PATTERNS = [
	{
		name: "Source map reference",
		pattern: /\/\/# sourceMappingURL=/gi,
		description: "Source map reference found in bundle",
	},
	{
		name: "Proprietary comment",
		pattern: /\/\*\*?\s*(PROPRIETARY|CONFIDENTIAL|INTERNAL ONLY)/gi,
		description: "Comment indicating proprietary code",
	},
	{
		name: "Algorithm explanation",
		pattern: /\/\/.*algorithm|\/\*.*detection.*logic/gi,
		description: "Comment explaining algorithm logic",
	},
	{
		name: "Debug logging of patterns",
		pattern: /console\.(log|debug).*pattern|console\.(log|debug).*threshold/gi,
		description: "Debug logging that may expose detection logic",
	},
];

/**
 * EXPECTED patterns - These should be obfuscated in production
 * If found unobfuscated, it indicates obfuscation didn't work
 */
const OBFUSCATION_CHECK_PATTERNS = [
	{
		name: "Function names in clear text",
		pattern: /function\s+(detectByVelocity|detectByPattern|calculateFileComplexity|computeSimilarity)/gi,
		description: "Proprietary function names not obfuscated",
	},
	{
		name: "Class names in clear text",
		pattern: /class\s+(AIDetector|ThreatDetector|ComplexityAnalyzer)/gi,
		description: "Proprietary class names not obfuscated",
	},
];

// =============================================================================
// Validation Logic
// =============================================================================

class ValidationResult {
	constructor() {
		this.critical = [];
		this.warnings = [];
		this.obfuscationIssues = [];
		this.passed = true;
	}

	addCritical(name, matches, description) {
		this.critical.push({ name, matches, description });
		this.passed = false;
	}

	addWarning(name, matches, description) {
		this.warnings.push({ name, matches, description });
	}

	addObfuscationIssue(name, matches, description) {
		this.obfuscationIssues.push({ name, matches, description });
		// Obfuscation issues are warnings, not failures
	}
}

function scanBundle(bundlePath) {
	const result = new ValidationResult();

	// Check if bundle exists
	if (!fs.existsSync(bundlePath)) {
		console.error(`❌ Bundle not found: ${bundlePath}`);
		console.error("   Run 'pnpm build' first");
		process.exit(1);
	}

	const bundleContent = fs.readFileSync(bundlePath, "utf-8");
	const bundleSize = bundleContent.length;

	console.log(`📦 Scanning bundle: ${bundlePath}`);
	console.log(`   Size: ${Math.round(bundleSize / 1024)}KB`);
	console.log("");

	// Check critical patterns
	console.log("🔴 Checking CRITICAL patterns (any match = failure)...");
	for (const { name, pattern, description } of CRITICAL_PATTERNS) {
		const matches = bundleContent.match(pattern);
		if (matches && matches.length > 0) {
			result.addCritical(name, matches.length, description);
			console.log(`   ❌ ${name}: ${matches.length} match(es)`);
			// Log first match for context (truncated)
			const firstMatch = matches[0].substring(0, 100);
			console.log(`      Sample: "${firstMatch}..."`);
		} else {
			console.log(`   ✅ ${name}: OK`);
		}
	}
	console.log("");

	// Check warning patterns
	console.log("🟡 Checking WARNING patterns...");
	for (const { name, pattern, description } of WARNING_PATTERNS) {
		const matches = bundleContent.match(pattern);
		if (matches && matches.length > 0) {
			result.addWarning(name, matches.length, description);
			console.log(`   ⚠️  ${name}: ${matches.length} match(es)`);
		} else {
			console.log(`   ✅ ${name}: OK`);
		}
	}
	console.log("");

	// Check obfuscation effectiveness
	console.log("🔵 Checking obfuscation effectiveness...");
	for (const { name, pattern, description } of OBFUSCATION_CHECK_PATTERNS) {
		const matches = bundleContent.match(pattern);
		if (matches && matches.length > 0) {
			result.addObfuscationIssue(name, matches.length, description);
			console.log(`   ⚠️  ${name}: ${matches.length} unobfuscated`);
		} else {
			console.log(`   ✅ ${name}: Obfuscated`);
		}
	}
	console.log("");

	return result;
}

function printSummary(result) {
	console.log("═══════════════════════════════════════════════════════════════");
	console.log("                    IP PROTECTION VALIDATION SUMMARY");
	console.log("═══════════════════════════════════════════════════════════════");
	console.log("");

	if (result.passed) {
		console.log("✅ PASSED - No critical IP leaks detected");
	} else {
		console.log("❌ FAILED - Critical IP leaks detected");
	}
	console.log("");

	if (result.critical.length > 0) {
		console.log("🔴 CRITICAL ISSUES (must fix before publish):");
		for (const issue of result.critical) {
			console.log(`   • ${issue.name}: ${issue.matches} match(es)`);
			console.log(`     ${issue.description}`);
		}
		console.log("");
	}

	if (result.warnings.length > 0) {
		console.log("🟡 WARNINGS (review recommended):");
		for (const issue of result.warnings) {
			console.log(`   • ${issue.name}: ${issue.matches} match(es)`);
		}
		console.log("");
	}

	if (result.obfuscationIssues.length > 0) {
		console.log("🔵 OBFUSCATION ISSUES (obfuscator may not be running):");
		for (const issue of result.obfuscationIssues) {
			console.log(`   • ${issue.name}: ${issue.matches} unobfuscated`);
		}
		console.log("");
		console.log("   Tip: Ensure javascript-obfuscator is installed:");
		console.log("   pnpm add -D javascript-obfuscator");
		console.log("");
	}

	if (!result.passed) {
		console.log("═══════════════════════════════════════════════════════════════");
		console.log("                    RECOMMENDED ACTIONS");
		console.log("═══════════════════════════════════════════════════════════════");
		console.log("");
		console.log("1. Move proprietary algorithms to server-side API");
		console.log("2. Use MinimalAIDetector for client-side fallback");
		console.log("3. Ensure javascript-obfuscator is installed and running");
		console.log("4. Review and remove any comments explaining algorithms");
		console.log("5. Check that source maps are not included");
		console.log("");
	}

	console.log("═══════════════════════════════════════════════════════════════");
}

// =============================================================================
// Main
// =============================================================================

function main() {
	console.log("");
	console.log("🛡️  SnapBack IP Protection Validation");
	console.log("    Pre-publish security check for VS Code extension");
	console.log("");

	const result = scanBundle(CONFIG.bundlePath);
	printSummary(result);

	// Exit with error code if validation failed
	if (!result.passed) {
		console.log("❌ Validation FAILED - Do NOT publish this build");
		process.exit(1);
	}

	// Warn if there are obfuscation issues
	if (result.obfuscationIssues.length > 0) {
		console.log("⚠️  Validation PASSED with warnings - Review obfuscation");
		process.exit(0);
	}

	console.log("✅ Validation PASSED - Safe to publish");
	process.exit(0);
}

main();
