const { app, BrowserWindow, ipcMain } = require('electron');
const { autoUpdater } = require('electron-updater');
const path = require('path');
const fs = require('fs');
const https = require('https');
const http = require('http');
const { exec } = require('child_process');

const BACKEND_BASE_URL = process.env.BACKEND_BASE_URL || 'https://api.example.com';

let mainWindow;

function getAppDataPath() {
  return app.getPath('userData');
}

function getAppsDir() {
  const dir = path.join(getAppDataPath(), 'apps');
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
  return dir;
}

function getSecretsPath() {
  const dir = path.join(getAppDataPath(), 'secrets');
  if (!fs.existsSync(dir)) {
    fs.mkdirSync(dir, { recursive: true });
  }
  return path.join(dir, 'secure.json');
}

function loadSecureStore() {
  const secretsPath = getSecretsPath();
  if (!fs.existsSync(secretsPath)) {
    return { data: {} };
  }
  try {
    const content = fs.readFileSync(secretsPath, 'utf8');
    return JSON.parse(content);
  } catch {
    return { data: {} };
  }
}

function saveSecureStore(store) {
  const secretsPath = getSecretsPath();
  fs.writeFileSync(secretsPath, JSON.stringify(store, null, 2), 'utf8');
}

function getOpenCodeBinaryPath() {
  const base = path.join(getAppDataPath(), 'opencode');
  if (!fs.existsSync(base)) {
    fs.mkdirSync(base, { recursive: true });
  }
  const name = process.platform === 'win32' ? 'opencode.exe' : 'opencode';
  return path.join(base, name);
}

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1280,
    height: 800,
    webPreferences: {
      preload: path.join(__dirname, 'electron-preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
    },
    title: 'Plugin Compass',
    show: false,
  });

  mainWindow.once('ready-to-show', () => {
    mainWindow.show();
  });

  const uiDistPath = path.join(__dirname, 'ui-dist');
  const indexPath = path.join(uiDistPath, 'index.html');
  
  if (fs.existsSync(indexPath)) {
    mainWindow.loadFile(indexPath);
  } else {
    mainWindow.loadURL('http://localhost:3000');
  }

  mainWindow.webContents.on('did-finish-load', () => {
    mainWindow.webContents.send('app-version', app.getVersion());
  });
}

app.whenReady().then(() => {
  createWindow();
  
  autoUpdater.checkForUpdatesAndNotify();

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

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

autoUpdater.on('update-available', () => {
  if (mainWindow) {
    mainWindow.webContents.send('update-available');
  }
});

autoUpdater.on('update-downloaded', () => {
  if (mainWindow) {
    mainWindow.webContents.send('update-downloaded');
  }
});

autoUpdater.on('error', (err) => {
  if (mainWindow) {
    mainWindow.webContents.send('update-error', err.message);
  }
});

autoUpdater.on('download-progress', (progressObj) => {
  if (mainWindow) {
    mainWindow.webContents.send('download-progress', {
      percent: progressObj.percent,
      transferred: progressObj.transferred,
      total: progressObj.total,
    });
  }
});

ipcMain.handle('check-for-updates', async () => {
  try {
    const result = await autoUpdater.checkForUpdates();
    return {
      available: result && result.updateInfo && result.updateInfo.version !== app.getVersion(),
      currentVersion: app.getVersion(),
      latestVersion: result ? result.updateInfo.version : app.getVersion(),
    };
  } catch (err) {
    return { error: err.message };
  }
});

ipcMain.handle('download-update', async () => {
  try {
    await autoUpdater.downloadUpdate();
    return { success: true };
  } catch (err) {
    return { error: err.message };
  }
});

ipcMain.handle('install-update', () => {
  autoUpdater.quitAndInstall();
});

ipcMain.handle('get-version', () => {
  return app.getVersion();
});

ipcMain.handle('save-api-key', async (event, token) => {
  if (!token || typeof token !== 'string' || token.trim() === '') {
    throw new Error('token is required');
  }
  const store = loadSecureStore();
  store.data['opencode_api_key'] = token;
  saveSecureStore(store);
  return { success: true };
});

ipcMain.handle('persist-app', async (event, appData) => {
  if (!appData || typeof appData !== 'object') {
    throw new Error('App payload must be an object');
  }
  if (!appData.id || appData.id.trim() === '') {
    throw new Error('app.id is required');
  }
  
  const dir = getAppsDir();
  const appPath = path.join(dir, `${appData.id}.json`);
  fs.writeFileSync(appPath, JSON.stringify(appData, null, 2), 'utf8');
  return { success: true };
});

ipcMain.handle('list-apps', async () => {
  const dir = getAppsDir();
  const apps = [];
  
  if (!fs.existsSync(dir)) {
    return apps;
  }
  
  const entries = fs.readdirSync(dir, { withFileTypes: true });
  for (const entry of entries) {
    if (entry.isFile() && entry.name.endsWith('.json')) {
      const appPath = path.join(dir, entry.name);
      try {
        const content = fs.readFileSync(appPath, 'utf8');
        apps.push(JSON.parse(content));
      } catch {}
    }
  }
  return apps;
});

ipcMain.handle('sync-app', async (event, appId) => {
  if (!appId || appId.trim() === '') {
    throw new Error('appId is required');
  }
  
  const dir = getAppsDir();
  const appPath = path.join(dir, `${appId}.json`);
  
  if (!fs.existsSync(appPath)) {
    throw new Error(`App not found: ${appId}`);
  }
  
  const appData = JSON.parse(fs.readFileSync(appPath, 'utf8'));
  const url = `${BACKEND_BASE_URL}/desktop/apps/sync`;
  
  return new Promise((resolve, reject) => {
    const client = url.startsWith('https') ? https : http;
    const postData = JSON.stringify(appData);
    
    const req = client.request(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Content-Length': Buffer.byteLength(postData),
      },
    }, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => {
        if (res.statusCode >= 200 && res.statusCode < 300) {
          resolve({ success: true });
        } else {
          reject(new Error(`Sync failed: ${res.statusCode} ${data}`));
        }
      });
    });
    
    req.on('error', (err) => reject(new Error(`Sync request failed: ${err.message}`)));
    req.write(postData);
    req.end();
  });
});

ipcMain.handle('run-opencode-task', async (event, appId, taskName, args = []) => {
  if (!appId || appId.trim() === '') {
    throw new Error('appId is required');
  }
  if (!taskName || taskName.trim() === '') {
    throw new Error('taskName is required');
  }
  
  const binaryPath = getOpenCodeBinaryPath();
  if (!fs.existsSync(binaryPath)) {
    throw new Error('OpenCode binary not found on device');
  }
  
  const store = loadSecureStore();
  const apiKey = store.data['opencode_api_key'];
  if (!apiKey) {
    throw new Error('API key not set');
  }
  
  return new Promise((resolve, reject) => {
    const allArgs = [taskName, ...args];
    const child = exec(
      `"${binaryPath}" ${allArgs.map(a => `"${a}"`).join(' ')}`,
      {
        env: {
          ...process.env,
          OPENCODE_API_KEY: apiKey,
          APP_ID: appId,
        },
      },
      (error, stdout, stderr) => {
        if (error) {
          reject(new Error(`OpenCode exited with error: ${stderr || error.message}`));
          return;
        }
        resolve(stdout);
      }
    );
  });
});
