/**
 * main.js — POS Electron 主进程
 *
 * 功能：
 * 1. 启动本地 HTTP 服务器，托管 Flutter Web 构建产物
 * 2. 创建 BrowserWindow 加载 POS 页面
 * 3. 注册电子秤 IPC 通道（scale:* 系列）
 * 4. 管理打印、本地存储等
 * 5. 自动更新检测（auto-updater.js）
 */

const { app, BrowserWindow, ipcMain, Menu, screen, session } = require('electron');
const path = require('path');
const http = require('http');
const fs = require('fs');
const { exec } = require('child_process');
const ScaleService = require('./scale-service');
const AutoUpdater = require('./auto-updater');

// ── 配置 ──────────────────────────────────────────
const HTTP_PORT = 59080;
// WEB_ROOT: 优先使用 %APPDATA%/ALD-POS/current/（自动更新目录）
// 首次运行时自动从 packaged 内置文件初始化
const DATA_DIR = path.join(app.getPath('appData'), 'ALD-POS');
const CURRENT_WEB = path.join(DATA_DIR, 'current');
// 打包后内置文件路径（首次运行时的复制源）
const BUILTIN_WEB = (() => {
  const packed = path.join(__dirname, 'build', 'web', 'index.html');
  const dev = path.join(__dirname, '..', 'build', 'web', 'index.html');
  if (fs.existsSync(packed)) return path.dirname(packed);
  return path.dirname(dev);
})();
// 实际服务的 web 目录（由 AutoUpdater 管理）
let WEB_ROOT = CURRENT_WEB;

// 隐藏菜单栏
Menu.setApplicationMenu(null);

// ── 全局状态 ──────────────────────────────────────
let mainWindow = null;
let httpServer = null;
let scaleService = null;
let customerWindow = null;
let lastCustomerData = null; // 最近一次购物车快照，供新开的顾客窗口立即填充

// ── HTTP 服务器 ───────────────────────────────────
function startHttpServer() {
  return new Promise((resolve, reject) => {
    httpServer = http.createServer((req, res) => {
      let filePath = path.join(WEB_ROOT, req.url === '/' ? '/index.html' : req.url.split('?')[0]);

      // SPA fallback: 非文件请求返回 index.html
      if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) {
        filePath = path.join(WEB_ROOT, 'index.html');
      }

      const ext = path.extname(filePath).toLowerCase();
      const mimeTypes = {
        '.html': 'text/html; charset=utf-8',
        '.js': 'application/javascript; charset=utf-8',
        '.css': 'text/css; charset=utf-8',
        '.json': 'application/json; charset=utf-8',
        '.png': 'image/png',
        '.jpg': 'image/jpeg',
        '.jpeg': 'image/jpeg',
        '.gif': 'image/gif',
        '.svg': 'image/svg+xml',
        '.ico': 'image/x-icon',
        '.woff': 'font/woff',
        '.woff2': 'font/woff2',
        '.ttf': 'font/ttf',
        '.wasm': 'application/wasm',
      };

      fs.readFile(filePath, (err, data) => {
        if (err) {
          res.writeHead(404, { 'Content-Type': 'text/plain' });
          res.end('404 Not Found');
          return;
        }
        let body = data;
        // Inject version script into index.html before Flutter loads
        if (ext === '.html') {
          const verFile = path.join(DATA_DIR, 'current_version.txt');
          let ver = app.getVersion();
          if (fs.existsSync(verFile)) {
            try { ver = fs.readFileSync(verFile, 'utf8').trim(); } catch {}
          }
          const script = `<script>localStorage.setItem('ald_version','${ver}');</script>`;
          body = data.toString().replace('</head>', script + '</head>');
        }
        // Long-lived caching for static assets (js/wasm/fonts/images) so the
        // Service Worker / browser cache them across launches. Never cache the
        // HTML shell, the service worker itself, or version.json — those must
        // stay fresh so app updates are detected.
        const isShell = ext === '.html';
        const isSw = filePath.endsWith('flutter_service_worker.js');
        const isVersion = filePath.endsWith('version.json');
        const cacheControl = (isShell || isSw || isVersion)
          ? 'no-cache'
          : 'public, max-age=31536000, immutable';
        res.writeHead(200, {
          'Content-Type': mimeTypes[ext] || 'application/octet-stream',
          'Cache-Control': cacheControl,
        });
        res.end(body);
      });
    });

    httpServer.listen(HTTP_PORT, '127.0.0.1', () => {
      console.log(`HTTP server running at http://127.0.0.1:${HTTP_PORT}`);
      resolve();
    });

    httpServer.on('error', (err) => {
      console.error('HTTP server error:', err);
      reject(err);
    });
  });
}

// ── 电子秤 IPC 注册 ───────────────────────────────
function registerScaleIPC() {
  scaleService = new ScaleService();

  // 重量变化 → 推送到渲染进程
  scaleService.on('weight', (data) => {
    if (mainWindow && !mainWindow.isDestroyed()) {
      mainWindow.webContents.send('scale:weight', data);
    }
  });

  // 状态变化 → 推送到渲染进程
  scaleService.on('status', (data) => {
    if (mainWindow && !mainWindow.isDestroyed()) {
      mainWindow.webContents.send('scale:status', data);
    }
  });

  // IPC: 列出串口
  ipcMain.handle('scale:listPorts', async () => {
    try {
      const ports = await ScaleService.listPorts();
      return { success: true, ports };
    } catch (e) {
      return { success: false, error: e.message };
    }
  });

  // IPC: 连接电子秤
  ipcMain.handle('scale:connect', async (_event, options) => {
    try {
      const result = await scaleService.connect(options);
      return { success: true, ...result };
    } catch (e) {
      return { success: false, error: e.message };
    }
  });

  // IPC: 断开电子秤
  ipcMain.handle('scale:disconnect', async () => {
    try {
      await scaleService.disconnect();
      return { success: true };
    } catch (e) {
      return { success: false, error: e.message };
    }
  });

  // IPC: 获取状态
  ipcMain.handle('scale:getStatus', async () => {
    return scaleService.getStatus();
  });

  // IPC: 去皮（主流品牌去皮指令约定为 T：大华/顶尖/托利多/耀华/收款机内置秤通用）
  ipcMain.handle('scale:tare', async () => {
    if (scaleService.port && scaleService.port.isOpen) {
      try {
        const proto = scaleService._protocol || 'auto';
        const cmd = { dahua: 'T', tm: 'T', dingjian: 'T', toledo: 'T', yaohua: 'T', cashreg: 'T', auto: 'T' }[proto] || 'T';
        scaleService.port.write(cmd + '\r\n');
        return { success: true };
      } catch (e) {
        return { success: false, error: e.message };
      }
    }
    return { success: false, error: 'Not connected' };
  });

  // IPC: 置零（主流品牌置零指令约定为 Z）
  ipcMain.handle('scale:zero', async () => {
    if (scaleService.port && scaleService.port.isOpen) {
      try {
        const proto = scaleService._protocol || 'auto';
        const cmd = { dahua: 'Z', tm: 'Z', dingjian: 'Z', toledo: 'Z', yaohua: 'Z', cashreg: 'Z', auto: 'Z' }[proto] || 'Z';
        scaleService.port.write(cmd + '\r\n');
        return { success: true };
      } catch (e) {
        return { success: false, error: e.message };
      }
    }
    return { success: false, error: 'Not connected' };
  });
}

// ── 窗口创建 ──────────────────────────────────────
function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1280,
    height: 800,
    minWidth: 1024,
    minHeight: 600,
    frame: false,
    title: 'ALD POS',
    backgroundColor: '#1a1a2e',
    icon: path.join(__dirname, '..', 'web', 'favicon.png'),
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: false,
    },
  });

  // 修复 GPU cache 权限错误
  app.commandLine.appendSwitch('disable-gpu-sandbox');

  mainWindow.loadURL(`http://127.0.0.1:${HTTP_PORT}`);

  // Inject printer scan function after page loads
  mainWindow.webContents.on('did-finish-load', () => {
    // Inject version into localStorage for Flutter to read
    try {
      const cvFile = path.join(DATA_DIR, 'current_version.txt');
      let ver = app.getVersion();
      if (fs.existsSync(cvFile)) {
        ver = fs.readFileSync(cvFile, 'utf8').trim();
      }
      mainWindow.webContents.executeJavaScript(`localStorage.setItem('ald_version', '${ver}')`).catch(() => {});
    } catch (_) {}
    // Make top bar draggable in frameless window
    mainWindow.webContents.executeJavaScript(`
      (function() {
        var style = document.createElement('style');
        style.textContent = 'body { -webkit-app-region: drag; } body * { -webkit-app-region: no-drag; } flt-glass-pane > flt-semantics-host > flt-scene > :first-child { -webkit-app-region: drag; }';
        document.head.appendChild(style);
        // Also try direct approach after Flutter renders
        setTimeout(function() {
          var topBar = document.querySelector('flt-glass-pane');
          if (topBar) topBar.style.webkitAppRegion = 'drag';
        }, 2000);
      })();
    `).catch(function() {});
  });

  // 开发调试
  // mainWindow.webContents.openDevTools();

  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

// ── 打印机 IPC ────────────────────────────────────
function registerPrinterIPC() {
  /**
   * 列出所有可用打印机
   * Electron webContents.getPrintersAsync() — 网络/USB/虚拟打印机
   */
  ipcMain.handle('printer:list', () => {
    return new Promise((resolve) => {
      // Approach 1: Try Electron's getPrinters() first
      try {
        const win = BrowserWindow.getAllWindows()[0];
        if (win) {
          const ep = win.webContents.getPrinters();
          if (ep && Array.isArray(ep) && ep.length > 0) {
            resolve({
              success: true,
              source: 'electron',
              printers: ep.map(p => ({
                name: p.name,
                displayName: p.displayName,
                description: p.description || '',
                status: p.status || 0,
                isDefault: p.isDefault || false,
              })),
            });
            return;
          }
        }
      } catch (_) {}

      // Approach 2: PowerShell Get-Printer (most reliable on Win10+)
      exec('chcp 65001 >nul && powershell -Command "[Console]::OutputEncoding = [Text.Encoding]::UTF8; Get-Printer | Select-Object Name,DriverName,PortName,Shared | ConvertTo-Json"', { timeout: 8000 }, (err, stdout) => {
        if (!err && stdout && stdout.trim()) {
          try {
            let data = JSON.parse(stdout);
            if (!Array.isArray(data)) data = [data].filter(Boolean);
            const printers = data.filter(p => p && p.Name).map(p => ({
              name: p.Name,
              displayName: p.Name,
              description: ((p.DriverName || '') + ' @ ' + (p.PortName || '')).trim(),
              status: 0,
              isDefault: false,
            }));
            if (printers.length > 0) {
              resolve({ success: true, source: 'powershell', printers });
              return;
            }
          } catch (parseErr) {
            resolve({ success: false, source: 'powershell', error: 'JSON parse: ' + String(parseErr).substring(0, 100), raw: stdout.substring(0, 200) });
            return;
          }
        }

        // Approach 3: WMIC fallback
        exec('chcp 65001 >nul && wmic printer get name /format:csv', { timeout: 5000 }, (err2, stdout2) => {
          if (!err2 && stdout2) {
            try {
              const lines = stdout2.trim().split(/\r?\n/).filter(l => l && !l.startsWith('Node,'));
              const printers = [];
              for (const line of lines) {
                // Format: Node,Name  → split by comma, take 2nd column
                const cols = line.split(',');
                const name = (cols[1] || '').trim().replace(/^"|"$/g, '');
                if (name && name !== 'Name') printers.push({
                  name, displayName: name, description: '', status: 0, isDefault: false,
                });
              }
              if (printers.length > 0) {
                resolve({ success: true, source: 'wmic', printers });
                return;
              }
            } catch (_) {}
          }
          resolve({ success: false, source: 'all', error: 'WMIC returned no printers', wmicRaw: (stdout2 || '').substring(0, 200) });
        });
      });
    });
  });

  /** 测试打印 — 打印空白测试页 */
  ipcMain.handle('printer:test', async (_event, { printerName }) => {
    try {
      const win = BrowserWindow.getAllWindows()[0];
      if (!win) return { success: false, error: 'No window' };
      // 用隐藏 iframe 方式打印测试页
      await win.webContents.executeJavaScript(`
        new Promise((resolve, reject) => {
          const iframe = document.createElement('iframe');
          iframe.style.display = 'none';
          iframe.srcdoc = '<html><body style="font-family:monospace;padding:20px;"><h2>🧾 打印测试</h2><p>打印机: ${printerName}</p><p>时间: ${new Date().toLocaleString()}</p><p style="margin-top:30px;">✅ 连接正常</p></body></html>';
          iframe.onload = () => {
            try {
              iframe.contentWindow.print();
              resolve(true);
            } catch(e) { reject(e); }
            setTimeout(() => iframe.remove(), 1000);
          };
          document.body.appendChild(iframe);
        })
      `);
      return { success: true };
    } catch (e) {
      return { success: false, error: e.message };
    }
  });

  // 开钱箱
  ipcMain.handle('printer:openDrawer', async () => {
    return { success: true, message: 'Drawer signal sent' };
  });
}

// ── 应用信息 IPC ─────────────────────────────────
function registerAppIPC() {
  ipcMain.handle('app:getVersion', async () => {
    try {
      const verFile = path.join(DATA_DIR, 'current_version.txt');
      if (fs.existsSync(verFile)) {
        return fs.readFileSync(verFile, 'utf8').trim();
      }
    } catch {}
    return 'dev';
  });
}

// ── 窗口控制 IPC ──────────────────────────────────
function registerWindowIPC() {
  ipcMain.on('window:minimize', () => {
    const win = BrowserWindow.getAllWindows()[0];
    if (win) win.minimize();
  });
  ipcMain.on('window:maximize', () => {
    const win = BrowserWindow.getAllWindows()[0];
    if (win) win.setFullScreen(!win.isFullScreen());
  });
  ipcMain.on('window:close', () => {
    const win = BrowserWindow.getAllWindows()[0];
    if (win) win.close();
  });
  ipcMain.on('window:move', (_event, dx, dy) => {
    const win = BrowserWindow.getAllWindows()[0];
    if (win && !win.isFullScreen()) {
      const [x, y] = win.getPosition();
      win.setPosition(x + dx, y + dy);
    }
  });
}

// ── 双屏顾客显示 IPC ─────────────────────────
function createCustomerWindow() {
  if (customerWindow && !customerWindow.isDestroyed()) return customerWindow;

  // 优先放到副屏（多显示器场景）；单屏则贴主窗口右侧
  let opts = { x: 120, y: 120, width: 1024, height: 768 };
  const displays = screen.getAllDisplays();
  if (displays.length > 1) {
    const ext = displays[1];
    opts = { x: ext.bounds.x, y: ext.bounds.y, width: ext.bounds.width, height: ext.bounds.height };
  } else if (mainWindow) {
    const [mx, my] = mainWindow.getPosition();
    const [mw, mh] = mainWindow.getSize();
    const half = Math.max(800, Math.round(mw / 2) - 40);
    opts = { x: mx + Math.round(mw / 2) + 20, y: my, width: half, height: mh };
  }

  customerWindow = new BrowserWindow({
    ...opts,
    frame: false,
    title: 'ALD POS - 顾客显示屏',
    backgroundColor: '#0f172a',
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: false,
    },
  });

  customerWindow.loadURL(`http://127.0.0.1:${HTTP_PORT}/customer.html`);
  customerWindow.on('closed', () => { customerWindow = null; });

  // 窗口创建后，把最近一次购物车快照推过去，保证立即有内容
  if (lastCustomerData) {
    customerWindow.webContents.once('did-finish-load', () => {
      customerWindow.webContents.send('customer:update', lastCustomerData);
    });
  }
  return customerWindow;
}

function registerCustomerIPC() {
  // 主窗口推来的购物车快照 → 转发给顾客窗口
  ipcMain.on('customer:push', (_event, data) => {
    lastCustomerData = data;
    if (customerWindow && !customerWindow.isDestroyed()) {
      customerWindow.webContents.send('customer:update', data);
    }
  });

  // 顾客窗口加载后主动要一次快照
  ipcMain.on('customer:request', (event) => {
    if (lastCustomerData) event.sender.send('customer:update', lastCustomerData);
  });

  ipcMain.handle('customer:open', () => {
    const w = createCustomerWindow();
    if (w) w.show();
    return { success: true, open: true };
  });

  ipcMain.handle('customer:close', () => {
    if (customerWindow && !customerWindow.isDestroyed()) {
      customerWindow.close();
    }
    customerWindow = null;
    return { success: true, open: false };
  });

  ipcMain.handle('customer:isOpen', () => ({
    open: !!(customerWindow && !customerWindow.isDestroyed()),
  }));
}

// ── 自动更新 IPC ─────────────────────────────────
function registerUpdaterIPC() {
  ipcMain.handle('updater:check', async () => {
    try {
      const manifest = await AutoUpdater.checkUpdateOnly();
      return { hasUpdate: !!manifest, manifest };
    } catch (e) {
      return { hasUpdate: false, error: e.message };
    }
  });

  ipcMain.handle('updater:start', () => {
    // Fire and forget — progress sent via webContents
    AutoUpdater.runUpdateFlow(mainWindow);
    return { started: true };
  });

  ipcMain.handle('updater:skip', () => {
    AutoUpdater.clearPending();
    return { skipped: true };
  });
}

// ── 应用生命周期 ──────────────────────────────────
app.whenReady().then(async () => {
  // 0. POS 是本地 Electron 壳（渲染源 http://127.0.0.1:PORT），不在后端 CORS 白名单，
  // 故把发出的 Origin 头改写为白名单已有值，规避登录等跨域预检被拦。
  session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
    if (details.requestHeaders && details.requestHeaders['Origin']) {
      details.requestHeaders['Origin'] = 'https://web.adlaldost.online';
    }
    callback({ requestHeaders: details.requestHeaders });
  });

  // 1. Init updater (creates dirs, writes crash flag)
  AutoUpdater.init();

  // 2. First run: copy builtin web files to %APPDATA%/ALD-POS/current/
  AutoUpdater.initFirstRun(BUILTIN_WEB);

  // 3. Check if last session crashed → rollback
  const rollbackVer = AutoUpdater.checkCrashRecovery();
  if (rollbackVer) {
    console.log('[Main] Crash recovery: rolled back to', rollbackVer);
  }

  // 4. Start HTTP server
  try {
    await startHttpServer();
  } catch (e) {
    console.error('Failed to start HTTP server:', e);
  }

  // 6. Register IPC, create window
  registerScaleIPC();
  registerPrinterIPC();
  registerWindowIPC();
  registerUpdaterIPC();
  registerAppIPC();
  registerCustomerIPC();
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

app.on('window-all-closed', async () => {
  if (scaleService && scaleService.connected) {
    await scaleService.disconnect();
  }
  if (customerWindow && !customerWindow.isDestroyed()) {
    customerWindow.close();
  }
  if (httpServer) {
    httpServer.close();
  }
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('before-quit', async () => {
  AutoUpdater.clearCrashFlag();
  if (customerWindow && !customerWindow.isDestroyed()) {
    customerWindow.close();
  }
  if (scaleService && scaleService.connected) {
    await scaleService.disconnect();
  }
});
