import crypto from 'crypto';

/**
 * Privacy and Anonymity Utilities for LocalGreenChain
 * Provides tools for anonymous plant tracking while maintaining blockchain integrity
 */

export interface PrivacySettings {
  anonymousMode: boolean;
  locationPrivacy: 'exact' | 'fuzzy' | 'city' | 'country' | 'hidden';
  identityPrivacy: 'real' | 'pseudonym' | 'anonymous';
  sharePlantDetails: boolean;
}

export interface FuzzyLocation {
  latitude: number;
  longitude: number;
  accuracy: number; // radius in km
  displayName: string;
}

/**
 * Generate anonymous user ID using cryptographic hash
 */
export function generateAnonymousId(): string {
  const randomBytes = crypto.randomBytes(32);
  return 'anon_' + crypto.createHash('sha256').update(randomBytes).digest('hex').substring(0, 16);
}

/**
 * Generate pseudonymous wallet address
 */
export function generateWalletAddress(): string {
  const randomBytes = crypto.randomBytes(20);
  return '0x' + randomBytes.toString('hex');
}

/**
 * Obfuscate location based on privacy level
 * This prevents exact home address tracking while allowing geographic discovery
 */
export function obfuscateLocation(
  latitude: number,
  longitude: number,
  privacyLevel: 'exact' | 'fuzzy' | 'city' | 'country' | 'hidden'
): FuzzyLocation {
  switch (privacyLevel) {
    case 'exact':
      return {
        latitude,
        longitude,
        accuracy: 0.1, // ~100m
        displayName: 'Exact location',
      };

    case 'fuzzy':
      // Add random offset within 1-5km radius
      const fuzzRadius = 1 + Math.random() * 4; // 1-5 km
      const angle = Math.random() * 2 * Math.PI;
      const latOffset = (fuzzRadius / 111) * Math.cos(angle); // 111 km per degree
      const lonOffset = (fuzzRadius / (111 * Math.cos(latitude * Math.PI / 180))) * Math.sin(angle);

      return {
        latitude: latitude + latOffset,
        longitude: longitude + lonOffset,
        accuracy: fuzzRadius,
        displayName: `Within ${Math.round(fuzzRadius)} km`,
      };

    case 'city':
      // Round to ~10km grid (0.1 degree ≈ 11km)
      return {
        latitude: Math.round(latitude * 10) / 10,
        longitude: Math.round(longitude * 10) / 10,
        accuracy: 10,
        displayName: 'City area',
      };

    case 'country':
      // Round to ~100km grid (1 degree ≈ 111km)
      return {
        latitude: Math.round(latitude),
        longitude: Math.round(longitude),
        accuracy: 100,
        displayName: 'Country/Region',
      };

    case 'hidden':
      return {
        latitude: 0,
        longitude: 0,
        accuracy: 999999,
        displayName: 'Location hidden',
      };

    default:
      return obfuscateLocation(latitude, longitude, 'fuzzy');
  }
}

/**
 * Generate anonymous plant name
 */
export function generateAnonymousPlantName(plantType: string, generation: number): string {
  const hash = crypto.randomBytes(4).toString('hex');
  return `${plantType}-Gen${generation}-${hash}`;
}

/**
 * Encrypt sensitive data for storage
 */
export function encryptData(data: string, key: string): string {
  const algorithm = 'aes-256-cbc';
  const keyHash = crypto.createHash('sha256').update(key).digest();
  const iv = crypto.randomBytes(16);

  const cipher = crypto.createCipheriv(algorithm, keyHash, iv);
  let encrypted = cipher.update(data, 'utf8', 'hex');
  encrypted += cipher.final('hex');

  return iv.toString('hex') + ':' + encrypted;
}

/**
 * Decrypt sensitive data
 */
export function decryptData(encryptedData: string, key: string): string {
  const algorithm = 'aes-256-cbc';
  const keyHash = crypto.createHash('sha256').update(key).digest();

  const parts = encryptedData.split(':');
  const iv = Buffer.from(parts[0], 'hex');
  const encrypted = parts[1];

  const decipher = crypto.createDecipheriv(algorithm, keyHash, iv);
  let decrypted = decipher.update(encrypted, 'hex', 'utf8');
  decrypted += decipher.final('utf8');

  return decrypted;
}

/**
 * Generate Tor-friendly onion address from plant ID
 * This creates a deterministic onion-style identifier
 */
export function generateOnionIdentifier(plantId: string): string {
  const hash = crypto.createHash('sha256').update(plantId).digest('hex');
  return hash.substring(0, 16) + '.onion';
}

/**
 * Create anonymous contact method
 */
export function createAnonymousContact(realEmail: string, privateKey: string): string {
  // Hash email with private key to create anonymous identifier
  const hash = crypto.createHash('sha256')
    .update(realEmail + privateKey)
    .digest('hex');
  return `anon-${hash.substring(0, 12)}@localgreenchain.onion`;
}

/**
 * Validate Tor connection
 */
export async function isTorConnection(req: any): Promise<boolean> {
  // Check if request is coming through Tor
  const forwardedFor = req.headers['x-forwarded-for'];
  const realIp = req.headers['x-real-ip'];

  // Tor exit nodes typically set specific headers
  // This is a simplified check
  return (
    req.headers['x-tor-connection'] === 'true' ||
    req.socket?.remoteAddress?.includes('127.0.0.1') // Tor proxy
  );
}

/**
 * Generate privacy report for plant
 */
export interface PrivacyReport {
  locationPrivacy: string;
  identityPrivacy: string;
  dataEncryption: boolean;
  torEnabled: boolean;
  riskLevel: 'low' | 'medium' | 'high';
  recommendations: string[];
}

export function generatePrivacyReport(settings: PrivacySettings): PrivacyReport {
  const recommendations: string[] = [];
  let riskLevel: 'low' | 'medium' | 'high' = 'low';

  if (settings.locationPrivacy === 'exact') {
    recommendations.push('Consider using fuzzy location to protect your privacy');
    riskLevel = 'high';
  }

  if (settings.identityPrivacy === 'real') {
    recommendations.push('Using real identity may compromise anonymity');
    if (riskLevel === 'low') riskLevel = 'medium';
  }

  if (settings.sharePlantDetails && !settings.anonymousMode) {
    recommendations.push('Sharing detailed plant info without anonymous mode enabled');
  }

  if (settings.anonymousMode && settings.locationPrivacy !== 'hidden') {
    riskLevel = 'low';
    recommendations.push('Good privacy settings enabled');
  }

  return {
    locationPrivacy: settings.locationPrivacy,
    identityPrivacy: settings.identityPrivacy,
    dataEncryption: settings.anonymousMode,
    torEnabled: false, // Will be detected at runtime
    riskLevel,
    recommendations: recommendations.length > 0 ? recommendations : ['Privacy settings are optimal'],
  };
}
