const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');
const fs = require('fs');
const http = require('http');
const { spawn } = require('child_process');
const { loadConfig } = require('../backend/config');

let mainWindow;

const SERVER_CONFIG = loadConfig();
const BACKEND_PORT = SERVER_CONFIG.server.port;
const BACKEND_HOST = SERVER_CONFIG.server.host;
const BACKEND_URL = SERVER_CONFIG.client.serverUrl || `http://${BACKEND_HOST === '0.0.0.0' ? '127.0.0.1' : BACKEND_HOST}:${BACKEND_PORT}`;
const BACKEND_ACCESS_KEY = SERVER_CONFIG.client.accessKey || SERVER_CONFIG.security.accessKey || '';
let activeSessionToken = '';
let backendStartedByLauncher = false;
const REQUIRE_BACKEND = SERVER_CONFIG.server.allowExternalPlayers === true || SERVER_CONFIG.client.autoStartLocalBackend === false || !isLocalBackendUrl();

function isLocalBackendUrl() {
  return /^https?:\/\/(127\.0\.0\.1|localhost)(:|\/|$)/i.test(BACKEND_URL);
}

function backendUrl(route) {
  return `${BACKEND_URL}${route}`;
}

function requestBackend(method, route, body = null, timeoutMs = 1800, extraHeaders = {}) {
  return new Promise((resolve, reject) => {
    const payload = body ? JSON.stringify(body) : null;
    const req = http.request(backendUrl(route), {
      method,
      timeout: timeoutMs,
      headers: {
        ...(payload ? {
          'Content-Type': 'application/json; charset=utf-8',
          'Content-Length': Buffer.byteLength(payload)
        } : {}),
        ...(BACKEND_ACCESS_KEY ? { 'X-Reinos-Token': BACKEND_ACCESS_KEY } : {}),
        ...(activeSessionToken ? { 'X-Reinos-Session': activeSessionToken } : {}),
        ...extraHeaders
      }
    }, res => {
      let raw = '';
      res.setEncoding('utf8');
      res.on('data', chunk => { raw += chunk; });
      res.on('end', () => {
        try {
          const parsed = raw ? JSON.parse(raw) : {};
          if (res.statusCode >= 200 && res.statusCode < 300 && parsed.ok !== false) resolve(parsed);
          else reject(new Error(parsed.error || `Backend respondeu ${res.statusCode}`));
        } catch (error) {
          reject(error);
        }
      });
    });
    req.on('timeout', () => req.destroy(new Error('Tempo de resposta do backend excedido.')));
    req.on('error', reject);
    if (payload) req.write(payload);
    req.end();
  });
}

async function isBackendOnline() {
  try {
    await requestBackend('GET', '/health', null, 650);
    return true;
  } catch (_) {
    return false;
  }
}

function backendScriptPath() {
  const unpacked = path.join(process.resourcesPath || '', 'app.asar.unpacked', 'backend', 'server.js');
  const dev = path.join(__dirname, '..', 'backend', 'server.js');
  if (fs.existsSync(unpacked)) return unpacked;
  return dev;
}

async function ensureBackendStarted() {
  if (await isBackendOnline()) return true;
  if (!SERVER_CONFIG.client.autoStartLocalBackend || !isLocalBackendUrl()) return false;
  const script = backendScriptPath();
  if (!fs.existsSync(script)) return false;
  try {
    const child = spawn(process.execPath, [script], {
      detached: true,
      stdio: 'ignore',
      env: {
        ...process.env,
        ELECTRON_RUN_AS_NODE: '1',
        REINOS_BACKEND_PORT: String(BACKEND_PORT),
        REINOS_BACKEND_HOST: BACKEND_HOST,
        REINOS_ACCESS_KEY: SERVER_CONFIG.security.accessKey || BACKEND_ACCESS_KEY,
        REINOS_ADMIN_KEY: SERVER_CONFIG.security.adminKey || '',
        REINOS_BACKEND_DATA_DIR: SERVER_CONFIG.server.dataDir,
        REINOS_CLIENT_DATA_FILE: dataFilePath()
      }
    });
    child.unref();
    backendStartedByLauncher = true;
  } catch (_) {
    return false;
  }
  for (let attempt = 0; attempt < 14; attempt += 1) {
    await new Promise(resolve => setTimeout(resolve, 220));
    if (await isBackendOnline()) return true;
  }
  return false;
}

async function loadDataWithBackend() {
  const online = await ensureBackendStarted();
  if (online) {
    try {
      const result = await requestBackend('GET', '/data', null, 6000);
      return result.data || safeDefaultData();
    } catch (error) {
      if (REQUIRE_BACKEND) throw new Error(`Servidor indisponível ou sessão inválida. ${error?.message || ''}`.trim());
    }
  }
  if (REQUIRE_BACKEND) throw new Error(`Servidor indisponível. Confirma se o backend está ligado em ${BACKEND_URL}.`);
  return loadData();
}

async function saveDataWithBackend(data) {
  const online = await ensureBackendStarted();
  if (online) {
    try {
      const result = await requestBackend('POST', '/data', data, 6000);
      if (result?.data) saveData(result.data);
      return true;
    } catch (error) {
      if (REQUIRE_BACKEND) throw new Error(`Não foi possível guardar no servidor. ${error?.message || ''}`.trim());
    }
  }
  if (REQUIRE_BACKEND) throw new Error(`Servidor indisponível. O jogo multiplayer não guarda dados locais.`);
  return saveData(data);
}

async function loginWithBackend(username, password) {
  const result = await requestBackend('POST', '/auth/login', { username, password }, 6000);
  if (result?.sessionToken) activeSessionToken = result.sessionToken;
  if (result?.data) saveData(result.data);
  return result;
}

async function registerWithBackend(username, password, userId = '', profile = null) {
  const result = await requestBackend('POST', '/auth/register', { username, password, userId, profile }, 6000);
  if (result?.sessionToken) activeSessionToken = result.sessionToken;
  if (result?.data) saveData(result.data);
  return result;
}

async function changePasswordWithBackend(currentPassword, newPassword) {
  const result = await requestBackend('POST', '/auth/change-password', { currentPassword, newPassword }, 6000);
  if (result?.data) saveData(result.data);
  return result;
}

async function resetProfileWithBackend(profile) {
  const result = await requestBackend('POST', '/profile/reset', { profile }, 6000);
  if (result?.data) saveData(result.data);
  return result;
}

async function adminGrantResourcesWithBackend(targetUserId, resources) {
  const result = await requestBackend('POST', '/admin/resources', { targetUserId, resources }, 6000);
  if (result?.data) saveData(result.data);
  return result;
}

async function adminGrantInventoryWithBackend(targetUserId, inventory = {}) {
  const result = await requestBackend('POST', '/admin/inventory', {
    targetUserId,
    resources: inventory.resources || {},
    troops: inventory.troops || {},
    siegeTools: inventory.siegeTools || {}
  }, 6000);
  if (result?.data) saveData(result.data);
  return result;
}

async function adminSetAccessWithBackend(targetUserId, enabled) {
  const result = await requestBackend('POST', '/admin/access', { targetUserId, enabled }, 6000);
  if (result?.data) saveData(result.data);
  return result;
}

async function marketSendResourcesWithBackend(targetUserId, resources) {
  const result = await requestBackend('POST', '/market/send', { targetUserId, resources }, 6000);
  if (result?.data) saveData(result.data);
  return result;
}

async function backendStatus() {
  const online = await ensureBackendStarted();
  if (!online) return { online: false, fallback: !REQUIRE_BACKEND, dataPath: dataFilePath(), serverUrl: BACKEND_URL, required: REQUIRE_BACKEND };
  try {
    const status = await requestBackend('GET', '/health', null, 1200);
    return { online: true, launchedByGame: backendStartedByLauncher, serverUrl: BACKEND_URL, required: REQUIRE_BACKEND, ...status };
  } catch (_) {
    return { online: false, fallback: !REQUIRE_BACKEND, dataPath: dataFilePath(), serverUrl: BACKEND_URL, required: REQUIRE_BACKEND };
  }
}


async function clearSessionWithBackend() {
  activeSessionToken = '';
  try {
    const current = loadData();
    current.sessionUserId = null;
    saveData(current);
  } catch (_) {}
  return true;
}

async function getRankingWithBackend() {
  if (await ensureBackendStarted()) {
    try {
      const result = await requestBackend('GET', '/ranking', null, 6000);
      return { ok: true, entries: Array.isArray(result?.entries) ? result.entries : [], userId: result?.userId || '' };
    } catch (error) {
      return { ok: false, entries: [], error: error?.message || String(error) };
    }
  }
  return { ok: false, entries: [], error: 'Backend indisponível.' };
}


function dataFilePath() {
  return path.join(SERVER_CONFIG.server.dataDir, 'reinos-de-ferro-client-data.json');
}

function safeDefaultData() {
  return { version: 1, users: [], profiles: {}, sessionUserId: null };
}

function loadData() {
  const file = dataFilePath();
  try {
    if (!fs.existsSync(file)) return safeDefaultData();
    const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
    return { ...safeDefaultData(), ...parsed };
  } catch (error) {
    const backup = `${file}.corrompido-${Date.now()}`;
    try { fs.copyFileSync(file, backup); } catch (_) {}
    return safeDefaultData();
  }
}

function saveData(data) {
  const file = dataFilePath();
  fs.mkdirSync(path.dirname(file), { recursive: true });
  const tmp = `${file}.tmp`;
  fs.writeFileSync(tmp, JSON.stringify(data, null, 2), 'utf8');
  fs.renameSync(tmp, file);
  return true;
}

function createWindow() {
  mainWindow = new BrowserWindow({
    width: 1440,
    height: 900,
    minWidth: 1180,
    minHeight: 720,
    backgroundColor: '#111318',
    show: false,
    autoHideMenuBar: true,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true,
      nodeIntegration: false,
      sandbox: true
    }
  });

  mainWindow.loadFile(path.join(__dirname, 'index.html'));
  mainWindow.once('ready-to-show', () => mainWindow.show());
}

ipcMain.handle('data:load', () => loadDataWithBackend());
ipcMain.handle('data:save', (_event, data) => saveDataWithBackend(data));
ipcMain.handle('auth:login', (_event, username, password) => loginWithBackend(username, password));
ipcMain.handle('auth:register', (_event, username, password, userId, profile) => registerWithBackend(username, password, userId, profile));
ipcMain.handle('auth:change-password', (_event, currentPassword, newPassword) => changePasswordWithBackend(currentPassword, newPassword));
ipcMain.handle('profile:reset', (_event, profile) => resetProfileWithBackend(profile));
ipcMain.handle('admin:resources', (_event, targetUserId, resources) => adminGrantResourcesWithBackend(targetUserId, resources));
ipcMain.handle('admin:inventory', (_event, targetUserId, inventory) => adminGrantInventoryWithBackend(targetUserId, inventory));
ipcMain.handle('admin:access', (_event, targetUserId, enabled) => adminSetAccessWithBackend(targetUserId, enabled));
ipcMain.handle('market:send-resources', (_event, targetUserId, resources) => marketSendResourcesWithBackend(targetUserId, resources));
ipcMain.handle('auth:clear-session', () => clearSessionWithBackend());
ipcMain.handle('app:version', () => app.getVersion());
ipcMain.handle('app:data-path', () => dataFilePath());
ipcMain.handle('backend:status', () => backendStatus());
ipcMain.handle('ranking:list', () => getRankingWithBackend());

app.whenReady().then(async () => {
  await ensureBackendStarted();
  createWindow();
  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

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