const crypto = require('crypto');
const { getPool } = require('../config/database');
const os = require('os');
const { exec } = require('child_process');
const util = require('util');
const execAsync = util.promisify(exec);

// Enhanced HWID generation using real hardware information
const generateRealHWID = async (req) => {
  try {
    const hardwareData = {
      // CPU Information
      cpu: {
        model: os.cpus()[0].model,
        cores: os.cpus().length,
        architecture: os.arch()
      },
      
      // Memory Information
      memory: {
        total: os.totalmem(),
        free: os.freemem()
      },
      
      // Network Interfaces
      network: Object.values(os.networkInterfaces())
        .flat()
        .filter(iface => iface && !iface.internal)
        .map(iface => ({
          mac: iface.mac,
          family: iface.family,
          address: iface.address
        })),
      
      // Platform Information
      platform: {
        type: os.type(),
        release: os.release(),
        hostname: os.hostname()
      },
      
      // User Agent and IP
      client: {
        userAgent: req.headers['user-agent'] || '',
        ip: req.ip || req.connection.remoteAddress || '',
        forwardedFor: req.headers['x-forwarded-for'] || '',
        realIp: req.headers['x-real-ip'] || ''
      },
      
      // Additional hardware data from headers (if provided by client)
      additional: {
        gpu: req.headers['x-gpu-info'] || '',
        motherboard: req.headers['x-motherboard'] || '',
        diskSerial: req.headers['x-disk-serial'] || '',
        biosVersion: req.headers['x-bios-version'] || '',
        macAddress: req.headers['x-mac-address'] || ''
      }
    };

    // Get additional system information on Windows
    if (os.platform() === 'win32') {
      try {
        // Get Windows-specific hardware info
        const { stdout: systemInfo } = await execAsync('wmic csproduct get uuid /format:value');
        const { stdout: biosInfo } = await execAsync('wmic bios get serialnumber /format:value');
        const { stdout: diskInfo } = await execAsync('wmic diskdrive get serialnumber /format:value');
        
        hardwareData.windows = {
          systemUUID: systemInfo.match(/UUID=(.+)/)?.[1]?.trim() || '',
          biosSerial: biosInfo.match(/SerialNumber=(.+)/)?.[1]?.trim() || '',
          diskSerial: diskInfo.match(/SerialNumber=(.+)/)?.[1]?.trim() || ''
        };
      } catch (error) {
        console.log('Windows hardware info error:', error.message);
      }
    }

    // Create a unique hardware fingerprint
    const fingerprint = JSON.stringify(hardwareData, Object.keys(hardwareData).sort());
    const hwid = crypto.createHash('sha256').update(fingerprint).digest('hex');
    
    return {
      hwid,
      hardwareData,
      fingerprint
    };
  } catch (error) {
    console.error('HWID generation error:', error);
    // Fallback to simple method if hardware detection fails
    const fallbackData = `${req.headers['user-agent'] || ''}|${req.ip || ''}|${os.hostname()}|${os.arch()}`;
    return {
      hwid: crypto.createHash('sha256').update(fallbackData).digest('hex'),
      hardwareData: { fallback: true, data: fallbackData },
      fingerprint: fallbackData
    };
  }
};

// Legacy function for backward compatibility
const generateHWID = (userAgent, ipAddress, additionalData = '') => {
  const data = `${userAgent}|${ipAddress}|${additionalData}`;
  return crypto.createHash('sha256').update(data).digest('hex');
};

// Get HWID from request with enhanced hardware detection
const getHWIDFromRequest = async (req) => {
  const result = await generateRealHWID(req);
  return result.hwid;
};

// Get detailed HWID information
const getDetailedHWID = async (req) => {
  return await generateRealHWID(req);
};

// Middleware to check if HWID is banned
const checkHWIDBan = async (req, res, next) => {
  try {
    const hwid = await getHWIDFromRequest(req);
    const pool = getPool();

    // Check if HWID is banned
    const [bannedHWIDs] = await pool.execute(
      'SELECT * FROM banned_hwids WHERE hwid = ?',
      [hwid]
    );

    if (bannedHWIDs.length > 0) {
      return res.status(403).json({
        success: false,
        error: 'Tài khoản này đã bị cấm',
        reason: bannedHWIDs[0].reason || 'HWID bị cấm',
        bannedAt: bannedHWIDs[0].created_at
      });
    }

    // Add HWID to request for later use
    req.hwid = hwid;
    next();
  } catch (error) {
    console.error('HWID check error:', error);
    // Continue if database error (don't block connection)
    req.hwid = await getHWIDFromRequest(req);
    next();
  }
};

// Middleware to auto-register HWID for authenticated users
const autoRegisterHWID = async (req, res, next) => {
  try {
    if (!req.user || !req.hwid) {
      return next();
    }

    const pool = getPool();

    // Check if HWID already exists for this user
    const [existingHWIDs] = await pool.execute(
      'SELECT * FROM user_hwids WHERE user_id = ? AND hwid = ?',
      [req.user.id, req.hwid]
    );

    if (existingHWIDs.length === 0) {
      // Get detailed hardware information
      const hwidInfo = await getDetailedHWID(req);
      
      // Register new HWID with detailed hardware info
      const { v4: uuidv4 } = require('uuid');
      await pool.execute(
        'INSERT INTO user_hwids (id, user_id, hwid, device_info, created_at) VALUES (?, ?, ?, ?, NOW())',
        [uuidv4(), req.user.id, req.hwid, JSON.stringify(hwidInfo.hardwareData)]
      );

      // Log activity
      await pool.execute(
        'INSERT INTO user_activity (id, user_id, activity_type, ip_address, user_agent, created_at) VALUES (?, ?, ?, ?, ?, NOW())',
        [uuidv4(), req.user.id, 'hwid_auto_registered', req.ip || req.connection.remoteAddress, req.headers['user-agent']]
      );
    }

    next();
  } catch (error) {
    console.error('Auto register HWID error:', error);
    next();
  }
};

// Middleware to check HWID on game connection
const checkGameConnection = async (req, res, next) => {
  try {
    const hwid = await getHWIDFromRequest(req);
    const pool = getPool();

    // Check if HWID is banned
    const [bannedHWIDs] = await pool.execute(
      'SELECT * FROM banned_hwids WHERE hwid = ?',
      [hwid]
    );

    if (bannedHWIDs.length > 0) {
      return res.status(403).json({
        success: false,
        error: 'Kết nối bị từ chối - HWID bị cấm',
        reason: bannedHWIDs[0].reason || 'HWID bị cấm',
        bannedAt: bannedHWIDs[0].created_at
      });
    }

    // Check if HWID is registered with any user
    const [userHWIDs] = await pool.execute(
      'SELECT uh.*, u.email, u.username FROM user_hwids uh JOIN users u ON uh.user_id = u.id WHERE uh.hwid = ?',
      [hwid]
    );

    if (userHWIDs.length > 0) {
      // HWID is registered, allow connection
      req.hwid = hwid;
      req.hwidUser = userHWIDs[0];
      next();
    } else {
      // HWID not registered, check if anonymous connections are allowed
      // For now, allow anonymous connections but log them
      req.hwid = hwid;
      req.hwidUser = null;
      
      // Log anonymous connection
      await pool.execute(
        'INSERT INTO user_activity (id, user_id, activity_type, ip_address, user_agent, created_at) VALUES (?, ?, ?, ?, ?, NOW())',
        [require('uuid').v4(), 'anonymous', 'anonymous_connection', req.ip || req.connection.remoteAddress, req.headers['user-agent']]
      );
      
      next();
    }
  } catch (error) {
    console.error('Game connection check error:', error);
    // Continue if database error (don't block connection)
    req.hwid = await getHWIDFromRequest(req);
    req.hwidUser = null;
    next();
  }
};

module.exports = {
  checkHWIDBan,
  autoRegisterHWID,
  checkGameConnection,
  getHWIDFromRequest,
  generateHWID,
  generateRealHWID,
  getDetailedHWID
};
