import { app, BrowserWindow, session, ipcMain } from 'electron';
import { fileURLToPath } from 'url';
import path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';
import { existsSync, readFileSync } from 'fs';

const execAsync = promisify(exec);

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const isDev = process.env.NODE_ENV === 'development' || !app.isPackaged;

// 读取配置文件
function loadConfig() {
  try {
    const configPath = path.join(__dirname, 'config.js');
    if (existsSync(configPath)) {
      const configContent = readFileSync(configPath, 'utf-8');
      // 解析 JSON（移除可能的注释和尾随逗号）
      const jsonContent = configContent.replace(/\/\/.*$/gm, '').replace(/,(\s*[}\]])/g, '$1');
      return JSON.parse(jsonContent);
    }
  } catch (error) {
    console.warn('Failed to load config.js:', error.message);
  }
  return null;
}

// 查找 ADB 可执行文件路径
function getAdbPath() {
  // 首先尝试从配置文件读取
  const config = loadConfig();
  if (config && config['adb-path']) {
    const configAdbPath = path.join(config['adb-path'], 'adb.exe');
    if (existsSync(configAdbPath)) {
      console.log('Using ADB path from config.js:', configAdbPath);
      return configAdbPath;
    }
    // 如果配置的路径不存在，尝试直接使用配置的路径（可能已经是完整路径）
    if (existsSync(config['adb-path'])) {
      console.log('Using ADB path from config.js:', config['adb-path']);
      return config['adb-path'];
    }
  }

  // 如果配置文件没有或路径不存在，使用常见 ADB 安装位置（按优先级排序）
  const possiblePaths = [
    path.join(process.env.LOCALAPPDATA || '', 'Android', 'Sdk', 'platform-tools', 'adb.exe'),
    path.join(process.env.USERPROFILE || '', 'AppData', 'Local', 'Android', 'Sdk', 'platform-tools', 'adb.exe'),
    path.join(process.env.ProgramFiles || '', 'Android', 'android-sdk', 'platform-tools', 'adb.exe'),
    path.join(process.env['ProgramFiles(x86)'] || '', 'Android', 'android-sdk', 'platform-tools', 'adb.exe'),
  ];

  // 检查常见位置
  for (const adbPath of possiblePaths) {
    if (existsSync(adbPath)) {
      return adbPath;
    }
  }

  // 如果都找不到，尝试使用 PATH 中的 adb
  return 'adb';
}

// 缓存 ADB 路径
let adbPathCache = null;
function getCachedAdbPath() {
  if (!adbPathCache) {
    adbPathCache = getAdbPath();
  }
  return adbPathCache;
}

// 设置内容安全策略（CSP），防止 XSS 攻击
function setContentSecurityPolicy() {
  session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
    const csp = isDev
      ? "default-src 'self'; script-src 'self' 'unsafe-inline' http://localhost:*; style-src 'self' 'unsafe-inline'; connect-src 'self' http://localhost:* ws://localhost:*; img-src 'self' data: https: blob:; font-src 'self' data:; worker-src 'self' blob:;"
      : "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self'; img-src 'self' data: https:; font-src 'self' data:;";
    
    const responseHeaders = Object.assign({}, details.responseHeaders);
    responseHeaders['Content-Security-Policy'] = [csp];
    
    callback({ responseHeaders });
  });
}

// 全局主窗口引用，用于发送实时事件
let mainWindow = null;

// 创建主窗口，根据环境加载不同内容源
function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.cjs'),
      nodeIntegration: false,
      contextIsolation: true
    }
  });

  // 禁用窗口关闭确认对话框，直接关闭
  mainWindow.on('close', (event) => {
    // 不阻止关闭事件，直接关闭窗口
    // 如果需要清理资源，可以在这里添加
  });
  
  // 禁用 webContents 的 beforeunload 确认对话框
  mainWindow.webContents.on('will-prevent-unload', (event) => {
    // 不阻止卸载，直接关闭
    // 注意：这里不需要调用 event.preventDefault()，因为我们要允许关闭
  });
  
  // 禁用 beforeunload 事件（前端页面可能触发的确认对话框）
  mainWindow.webContents.setWindowOpenHandler(() => {
    return { action: 'allow' };
  });
  
  // 禁用所有可能阻止关闭的事件
  mainWindow.webContents.on('beforeunload', (event) => {
    // 不阻止卸载
  });

  if (isDev) {
    mainWindow.loadURL('http://localhost:5173');
    mainWindow.webContents.openDevTools();
  } else {
    mainWindow.loadFile(path.join(__dirname, 'dist/index.html'));
  }
}

// 获取已连接的 ADB 设备列表
async function getADBDevices() {
  try {
    const adbPath = getCachedAdbPath();
    const { stdout } = await execAsync(`${adbPath} devices`);
    const lines = stdout.split('\n').slice(1);
    const devices = [];
    
    for (const line of lines) {
      const parts = line.trim().split(/\s+/);
      if (parts.length >= 2 && parts[0] && parts[1] === 'device') {
        devices.push({
          id: parts[0],
          status: parts[1]
        });
      }
    }
    return devices;
  } catch (error) {
    console.error('获取设备列表失败:', error);
    return [];
  }
}

// 网络扫描：从 192.168.0.1 开始扫描网段，尝试连接设备（实时推送结果）
async function scanNetworkDevices(event) {
  const adbPath = getCachedAdbPath();
  const baseIP = '192.168.0';
  const port = 5555;
  const maxConcurrent = 20; // 限制并发数，避免过载
  const connectTimeout = 1500; // 连接超时时间（毫秒）
  
  // 生成 IP 地址列表
  const ipList = [];
  for (let i = 1; i <= 255; i++) {
    ipList.push(`${baseIP}.${i}`);
  }
  
  const foundDevices = new Set(); // 使用 Set 避免重复
  
  // 分批并发扫描
  for (let i = 0; i < ipList.length; i += maxConcurrent) {
    const batch = ipList.slice(i, i + maxConcurrent);
    const promises = batch.map(async (ip) => {
      const ipPort = `${ip}:${port}`;
      try {
        // 先尝试连接设备
        await execAsync(`${adbPath} connect ${ipPort}`, {
          timeout: connectTimeout,
          maxBuffer: 1024 * 1024
        });
        
        // 连接后稍等片刻，让设备注册到 ADB 服务器
        await new Promise(resolve => setTimeout(resolve, 500));
      } catch (error) {
        // 连接失败是正常的，继续检查设备列表
      }
      
      // 直接使用 adb -s IP:PORT devices 命令检查该设备是否在列表中
      try {
        const { stdout } = await execAsync(`${adbPath} -s ${ipPort} devices`, {
          timeout: 2000,
          maxBuffer: 1024 * 1024
        });
        
        // 检查输出中是否包含 IP:PORT，如果有则说明设备存在
        if (stdout.includes(ipPort)) {
          // 发现设备，实时推送
          if (!foundDevices.has(ipPort)) {
            foundDevices.add(ipPort);
            const device = {
              id: ipPort,
              status: 'device'
            };
            // 实时发送发现的设备
            if (event && event.sender) {
              event.sender.send('device-found', device);
            } else if (mainWindow) {
              mainWindow.webContents.send('device-found', device);
            }
            console.log('发现设备:', ipPort);
          }
          return ipPort;
        }
      } catch (checkError) {
        // 检查失败，忽略
      }
      return null;
    });
    
    await Promise.all(promises);
  }
  
  // 返回所有发现的设备
  return Array.from(foundDevices).map(ipPort => ({
    id: ipPort,
    status: 'device'
  }));
}

// IPC 处理程序：获取 ADB 路径配置
ipcMain.handle('get-adb-path-config', async () => {
  const config = loadConfig();
  return config ? config['adb-path'] : null;
});

// IPC 处理程序：获取 ADB 设备列表
ipcMain.handle('get-adb-devices', async () => {
  return await getADBDevices();
});

// IPC 处理程序：扫描网络设备（支持实时推送）
ipcMain.handle('scan-adb-devices', async (event) => {
  try {
    const devices = await scanNetworkDevices(event);
    return devices;
  } catch (error) {
    console.error('网络扫描失败:', error);
    return [];
  }
});

// IPC 处理程序：连接 ADB 设备
ipcMain.handle('connect-adb-device', async (event, ipPort) => {
  try {
    const adbPath = getCachedAdbPath();
    await execAsync(`${adbPath} connect ${ipPort}`);
    return { success: true };
  } catch (error) {
    console.error('连接设备失败:', error);
    return { success: false, error: error.message };
  }
});

// IPC 处理程序：获取设备分辨率
ipcMain.handle('get-device-resolution', async (event, ipPort) => {
  if (!ipPort) {
    return { success: false, error: '缺少设备 ID' };
  }
  try {
    // 使用 wm size 命令获取设备分辨率
    const adbPath = getCachedAdbPath();
    const { stdout } = await execAsync(`${adbPath} -s ${ipPort} shell wm size`);
    // 输出格式通常是: "Physical size: 1080x2400" 或 "1080x2400"
    const match = stdout.match(/(\d+)x(\d+)/);
    if (match) {
      return {
        success: true,
        width: parseInt(match[1], 10),
        height: parseInt(match[2], 10)
      };
    }
    // 如果解析失败，返回默认值
    return { success: true, width: 1280, height: 2400 };
  } catch (error) {
    console.error('获取设备分辨率失败:', error);
    // 返回默认值
    return { success: true, width: 1280, height: 2400 };
  }
});

// IPC 处理程序：抓取设备截屏（返回 base64 PNG/JPEG）
ipcMain.handle('capture-screenshot', async (event, ipPort, options = {}) => {
  if (!ipPort) {
    return { success: false, error: '缺少设备 ID' };
  }
  try {
    const adbPath = getCachedAdbPath();
    
    // 从选项或默认值获取参数
    const format = options.format || 'png'; // 'png' 或 'jpeg'
    const quality = options.quality || 80; // JPEG 质量 1-100
    const scale = options.scale || 1.0; // 缩放比例 0.1-1.0
    
    // 构建 screencap 命令
    let command = `${adbPath} -s ${ipPort} exec-out screencap`;
    
    // 根据格式选择参数
    if (format === 'jpeg') {
      // JPEG 格式（更小，延迟更低）
      command += ` -j ${quality}`;
    } else {
      // PNG 格式（默认）
      command += ' -p';
    }
    
    // 如果缩放比例不是 1.0，需要通过 shell 命令处理
    // 注意：screencap 本身不支持缩放，需要通过其他方式实现
    // 这里先实现基本功能，缩放可以在后续优化
    
    const { stdout } = await execAsync(command, {
      encoding: 'buffer',
      maxBuffer: 25 * 1024 * 1024,
    });
    
    return { success: true, data: stdout.toString('base64') };
  } catch (error) {
    console.error('截屏失败:', error);
    return { success: false, error: error.message };
  }
});

// IPC 处理程序：发送 tap 事件到设备
ipcMain.handle('send-tap', async (event, ipPort, x, y) => {
  if (!ipPort) {
    return { success: false, error: '缺少设备 ID' };
  }
  if (typeof x !== 'number' || typeof y !== 'number') {
    return { success: false, error: '坐标必须是数字' };
  }
  try {
    const adbPath = getCachedAdbPath();
    const command = `${adbPath} -s ${ipPort} shell input tap ${x} ${y}`;
    await execAsync(command, {
      timeout: 5000,
      maxBuffer: 1024 * 1024
    });
    return { success: true };
  } catch (error) {
    console.error('Tap 失败:', error.message);
    return { success: false, error: error.message };
  }
});

// IPC 处理程序：发送 swipe 事件到设备
ipcMain.handle('send-swipe', async (event, ipPort, x1, y1, x2, y2, duration = 300) => {
  if (!ipPort) {
    return { success: false, error: '缺少设备 ID' };
  }
  if (typeof x1 !== 'number' || typeof y1 !== 'number' || typeof x2 !== 'number' || typeof y2 !== 'number') {
    return { success: false, error: '坐标必须是数字' };
  }
  try {
    const adbPath = getCachedAdbPath();
    const command = `${adbPath} -s ${ipPort} shell input swipe ${x1} ${y1} ${x2} ${y2} ${duration}`;
    await execAsync(command, {
      timeout: 5000,
      maxBuffer: 1024 * 1024
    });
    return { success: true };
  } catch (error) {
    console.error('Swipe 失败:', error.message);
    return { success: false, error: error.message };
  }
});

// IPC 处理程序：发送文字到设备
ipcMain.handle('send-text', async (event, ipPort, text) => {
  if (!ipPort) {
    return { success: false, error: '缺少设备 ID' };
  }
  if (typeof text !== 'string') {
    return { success: false, error: '文字必须是字符串' };
  }
  try {
    const adbPath = getCachedAdbPath();
    // ADB input text 需要转义特殊字符
    // 使用单引号包裹，并转义单引号
    const escapedText = text
      .replace(/\\/g, '\\\\')  // 先转义反斜杠
      .replace(/'/g, "'\\''")   // 转义单引号
      .replace(/ /g, '%s')      // 空格转换为 %s
      .replace(/&/g, '\\&')     // 转义 &
      .replace(/</g, '\\<')     // 转义 <
      .replace(/>/g, '\\>')     // 转义 >
      .replace(/\(/g, '\\(')    // 转义 (
      .replace(/\)/g, '\\)')    // 转义 )
      .replace(/;/g, '\\;')     // 转义 ;
      .replace(/\|/g, '\\|')    // 转义 |
      .replace(/\*/g, '\\*')    // 转义 *
      .replace(/\?/g, '\\?')    // 转义 ?
      .replace(/`/g, '\\`')     // 转义 `
      .replace(/\$/g, '\\$')    // 转义 $
      .replace(/"/g, '\\"');    // 转义 "
    
    // 对于换行，使用 KEYCODE_ENTER
    if (text.includes('\n')) {
      // 如果有换行，分段发送
      const lines = text.split('\n');
      for (let i = 0; i < lines.length; i++) {
        if (lines[i]) {
          const escapedLine = lines[i]
            .replace(/\\/g, '\\\\')
            .replace(/'/g, "'\\''")
            .replace(/ /g, '%s')
            .replace(/&/g, '\\&')
            .replace(/</g, '\\<')
            .replace(/>/g, '\\>')
            .replace(/\(/g, '\\(')
            .replace(/\)/g, '\\)')
            .replace(/;/g, '\\;')
            .replace(/\|/g, '\\|')
            .replace(/\*/g, '\\*')
            .replace(/\?/g, '\\?')
            .replace(/`/g, '\\`')
            .replace(/\$/g, '\\$')
            .replace(/"/g, '\\"');
          
          await execAsync(`${adbPath} -s ${ipPort} shell input text "${escapedLine}"`, {
            timeout: 5000,
            maxBuffer: 1024 * 1024
          });
        }
        // 发送换行（除了最后一行）
        if (i < lines.length - 1) {
          await execAsync(`${adbPath} -s ${ipPort} shell input keyevent KEYCODE_ENTER`, {
            timeout: 5000,
            maxBuffer: 1024 * 1024
          });
        }
      }
    } else {
      // 没有换行，直接发送
      const command = `${adbPath} -s ${ipPort} shell input text "${escapedText}"`;
      await execAsync(command, {
        timeout: 5000,
        maxBuffer: 1024 * 1024
      });
    }
    
    return { success: true };
  } catch (error) {
    console.error('发送文字失败:', error.message);
    return { success: false, error: error.message };
  }
});

// IPC 处理程序：发送按键事件到设备
ipcMain.handle('send-key-event', async (event, ipPort, keyCode) => {
  if (!ipPort) {
    return { success: false, error: '缺少设备 ID' };
  }
  if (typeof keyCode !== 'string') {
    return { success: false, error: '按键代码必须是字符串' };
  }
  try {
    const adbPath = getCachedAdbPath();
    const command = `${adbPath} -s ${ipPort} shell input keyevent ${keyCode}`;
    await execAsync(command, {
      timeout: 5000,
      maxBuffer: 1024 * 1024
    });
    return { success: true };
  } catch (error) {
    console.error('发送按键失败:', error.message);
    return { success: false, error: error.message };
  }
});

// 应用启动逻辑：设置 CSP、创建窗口、监听激活事件
app.whenReady().then(() => {
  setContentSecurityPolicy();
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
  
  // 禁用 before-quit 事件的确认对话框
  app.on('before-quit', (event) => {
    // 不阻止退出，直接退出应用
    // 如果需要清理资源，可以在这里添加
  });
});

// 应用关闭逻辑：macOS 保持运行，其他平台退出
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    // 直接退出，不询问
    app.exit(0);
  }
});

