console.log('[Oasis Mobile] Node.js backend starting...');

process.env.HOME = process.env.HOME || require('path').resolve(__dirname, '..', '..');
process.env.ssb_appname = process.env.ssb_appname || 'ssb';
process.env.OASIS_MOBILE = '1';
process.env.CHLORIDE_JS = '1';

const path = require('path');
const fs = require('fs');

const tmpDir = path.join(process.env.HOME, 'tmp');
try { fs.mkdirSync(tmpDir, { recursive: true }); } catch (e) {}
process.env.TMPDIR = tmpDir;
process.env.TMP = tmpDir;
process.env.TEMP = tmpDir;
try { require('os').tmpdir = () => tmpDir; } catch (e) {}

try {
    const dns = require('dns');
    const net = require('net');
    const servers = ['8.8.8.8', '1.1.1.1', '8.8.4.4'];
    try { dns.setServers(servers); } catch (e) {}
    try { if (dns.promises && dns.promises.setServers) dns.promises.setServers(servers); } catch (e) {}

    const localResolve = (hostname, family) => {
        if (hostname === 'localhost' || hostname === 'localhost.localdomain' || hostname === 'ip6-localhost') {
            return family === 6 ? { address: '::1', family: 6 } : { address: '127.0.0.1', family: 4 };
        }
        const ipv = net.isIP(hostname);
        if (ipv) return { address: hostname, family: ipv };
        return null;
    };

    const safeLookup = function (hostname, options, callback) {
        if (typeof options === 'function') { callback = options; options = {}; }
        options = options || {};
        const family = options.family === 6 ? 6 : 4;
        const direct = localResolve(hostname, family);
        if (direct) {
            return process.nextTick(() => options.all
                ? callback(null, [direct])
                : callback(null, direct.address, direct.family));
        }
        const resolver = family === 6 ? dns.resolve6 : dns.resolve4;
        resolver.call(dns, hostname, (err, addrs) => {
            if (err || !addrs || !addrs.length) return callback(err || new Error('ENOTFOUND ' + hostname));
            if (options.all) return callback(null, addrs.map((a) => ({ address: a, family })));
            return callback(null, addrs[0], family);
        });
    };

    dns.lookup = safeLookup;
    if (dns.promises) {
        dns.promises.lookup = (hostname, options) => new Promise((resolve, reject) => {
            safeLookup(hostname, options || {}, (err, address, family) => {
                if (err) return reject(err);
                if (options && options.all) return resolve(address);
                resolve({ address, family });
            });
        });
    }
} catch (e) {}

const backendPath = path.join(__dirname, 'src', 'backend', 'backend.js');

console.log('[Oasis] Launching Oasis Social Network Utopia...');
console.log('[Oasis] Backend path:', backendPath);
console.log('[Oasis] HOME:', process.env.HOME);

const http = require('http');
const keylock = require('./src/models/keylock');
const configPath = path.join(process.env.HOME, '.ssb');

let backendStarted = false;
function startBackend() {
  if (backendStarted) return;
  backendStarted = true;
  try {
    require(backendPath);
    console.log('[Oasis] Backend started on port 3000');
  } catch (error) {
    console.error('[Oasis] Error starting backend:', error);
  }
}

function unlockAndStart(keys) {
  global.__OASIS_KEYS__ = keys;
  for (const s of sockets) { try { s.destroy(); } catch (_) {} }
  try { lockServer.close(() => startBackend()); } catch (_) { startBackend(); }
}

const MODE = keylock.isConfigured(configPath) ? 'unlock' : 'setup';

const LOCK_LANGS = ['en','es','fr','eu','de','it','pt','zh','ar','hi','ru'];
const LOCK_I18N = {
  en: { name:"English", t_setup:"Create your password", t_unlock:"Unlock Oasis", s_setup:"It encrypts your identity and keys on this device. <b>If you forget it, you lose the account</b> (no recovery).", s_unlock:"Enter your password to decrypt your keys and start Oasis.", ph:"Password", ph2:"Repeat password", b_setup:"Create and enter", b_unlock:"Enter", e_min:"Minimum 6 characters", e_mism:"Passwords do not match", e_wrong:"Incorrect password", e_pre:"Error: ", m_unlock:"Unlocking…" },
  es: { name:"Español", t_setup:"Crea tu contraseña", t_unlock:"Desbloquea Oasis", s_setup:"Cifrará tu identidad y tus claves en este dispositivo. <b>Si la olvidas, pierdes la cuenta</b> (no hay recuperación).", s_unlock:"Introduce tu contraseña para descifrar tus claves y arrancar Oasis.", ph:"Contraseña", ph2:"Repite la contraseña", b_setup:"Crear y entrar", b_unlock:"Entrar", e_min:"Mínimo 6 caracteres", e_mism:"Las contraseñas no coinciden", e_wrong:"Contraseña incorrecta", e_pre:"Error: ", m_unlock:"Desbloqueando…" },
  fr: { name:"Français", t_setup:"Créez votre mot de passe", t_unlock:"Déverrouiller Oasis", s_setup:"Il chiffre votre identité et vos clés sur cet appareil. <b>Si vous l'oubliez, vous perdez le compte</b> (aucune récupération).", s_unlock:"Saisissez votre mot de passe pour déchiffrer vos clés et démarrer Oasis.", ph:"Mot de passe", ph2:"Répétez le mot de passe", b_setup:"Créer et entrer", b_unlock:"Entrer", e_min:"6 caractères minimum", e_mism:"Les mots de passe ne correspondent pas", e_wrong:"Mot de passe incorrect", e_pre:"Erreur : ", m_unlock:"Déverrouillage…" },
  eu: { name:"Euskara", t_setup:"Sortu zure pasahitza", t_unlock:"Desblokeatu Oasis", s_setup:"Zure identitatea eta gakoak gailu honetan zifratzen ditu. <b>Ahazten baduzu, kontua galtzen duzu</b> (ez dago berreskuratzerik).", s_unlock:"Sartu zure pasahitza gakoak deszifratu eta Oasis abiarazteko.", ph:"Pasahitza", ph2:"Errepikatu pasahitza", b_setup:"Sortu eta sartu", b_unlock:"Sartu", e_min:"Gutxienez 6 karaktere", e_mism:"Pasahitzak ez datoz bat", e_wrong:"Pasahitz okerra", e_pre:"Errorea: ", m_unlock:"Desblokeatzen…" },
  de: { name:"Deutsch", t_setup:"Erstelle dein Passwort", t_unlock:"Oasis entsperren", s_setup:"Es verschlüsselt deine Identität und Schlüssel auf diesem Gerät. <b>Wenn du es vergisst, verlierst du das Konto</b> (keine Wiederherstellung).", s_unlock:"Gib dein Passwort ein, um deine Schlüssel zu entschlüsseln und Oasis zu starten.", ph:"Passwort", ph2:"Passwort wiederholen", b_setup:"Erstellen und eintreten", b_unlock:"Eintreten", e_min:"Mindestens 6 Zeichen", e_mism:"Passwörter stimmen nicht überein", e_wrong:"Falsches Passwort", e_pre:"Fehler: ", m_unlock:"Entsperren…" },
  it: { name:"Italiano", t_setup:"Crea la tua password", t_unlock:"Sblocca Oasis", s_setup:"Cifra la tua identità e le tue chiavi su questo dispositivo. <b>Se la dimentichi, perdi l'account</b> (nessun recupero).", s_unlock:"Inserisci la password per decifrare le chiavi e avviare Oasis.", ph:"Password", ph2:"Ripeti la password", b_setup:"Crea ed entra", b_unlock:"Entra", e_min:"Minimo 6 caratteri", e_mism:"Le password non coincidono", e_wrong:"Password errata", e_pre:"Errore: ", m_unlock:"Sblocco…" },
  pt: { name:"Português", t_setup:"Crie a sua palavra-passe", t_unlock:"Desbloquear o Oasis", s_setup:"Cifra a sua identidade e chaves neste dispositivo. <b>Se a esquecer, perde a conta</b> (sem recuperação).", s_unlock:"Introduza a sua palavra-passe para decifrar as chaves e iniciar o Oasis.", ph:"Palavra-passe", ph2:"Repita a palavra-passe", b_setup:"Criar e entrar", b_unlock:"Entrar", e_min:"Mínimo 6 caracteres", e_mism:"As palavras-passe não coincidem", e_wrong:"Palavra-passe incorreta", e_pre:"Erro: ", m_unlock:"A desbloquear…" },
  zh: { name:"中文", t_setup:"创建你的密码", t_unlock:"解锁 Oasis", s_setup:"它会在此设备上加密你的身份和密钥。<b>如果忘记，你将失去账户</b>（无法恢复）。", s_unlock:"输入密码以解密你的密钥并启动 Oasis。", ph:"密码", ph2:"重复密码", b_setup:"创建并进入", b_unlock:"进入", e_min:"至少 6 个字符", e_mism:"密码不一致", e_wrong:"密码错误", e_pre:"错误：", m_unlock:"正在解锁…" },
  ar: { name:"العربية", t_setup:"أنشئ كلمة المرور", t_unlock:"فتح Oasis", s_setup:"يشفّر هويتك ومفاتيحك على هذا الجهاز. <b>إذا نسيتها، تفقد الحساب</b> (لا استعادة).", s_unlock:"أدخل كلمة المرور لفك تشفير مفاتيحك وتشغيل Oasis.", ph:"كلمة المرور", ph2:"أعد كلمة المرور", b_setup:"إنشاء ودخول", b_unlock:"دخول", e_min:"6 أحرف على الأقل", e_mism:"كلمتا المرور غير متطابقتين", e_wrong:"كلمة مرور غير صحيحة", e_pre:"خطأ: ", m_unlock:"جارٍ الفتح…" },
  hi: { name:"हिन्दी", t_setup:"अपना पासवर्ड बनाएं", t_unlock:"Oasis अनलॉक करें", s_setup:"यह इस डिवाइस पर आपकी पहचान और कुंजियाँ एन्क्रिप्ट करता है। <b>भूल गए तो खाता खो देंगे</b> (कोई रिकवरी नहीं)।", s_unlock:"अपनी कुंजियाँ डिक्रिप्ट करने और Oasis शुरू करने के लिए पासवर्ड दर्ज करें।", ph:"पासवर्ड", ph2:"पासवर्ड दोहराएँ", b_setup:"बनाएँ और प्रवेश करें", b_unlock:"प्रवेश करें", e_min:"कम से कम 6 अक्षर", e_mism:"पासवर्ड मेल नहीं खाते", e_wrong:"गलत पासवर्ड", e_pre:"त्रुटि: ", m_unlock:"अनलॉक हो रहा है…" },
  ru: { name:"Русский", t_setup:"Создайте пароль", t_unlock:"Разблокировать Oasis", s_setup:"Он шифрует вашу личность и ключи на этом устройстве. <b>Если забудете, потеряете аккаунт</b> (без восстановления).", s_unlock:"Введите пароль, чтобы расшифровать ключи и запустить Oasis.", ph:"Пароль", ph2:"Повторите пароль", b_setup:"Создать и войти", b_unlock:"Войти", e_min:"Минимум 6 символов", e_mism:"Пароли не совпадают", e_wrong:"Неверный пароль", e_pre:"Ошибка: ", m_unlock:"Разблокировка…" },
};

function lockPage(mode) {
  const confirmField = mode === 'setup'
    ? '<input id="c" type="password" inputmode="text" autocomplete="new-password" />'
    : '';
  return '<!doctype html><!-- OASIS_LOCK_MARKER --><html lang="en"><head><meta charset="utf-8">'
    + '<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">'
    + '<title>Oasis</title><style>'
    + '*{box-sizing:border-box}body{margin:0;background:#121212;color:#eee;font-family:system-ui,sans-serif;'
    + 'min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}'
    + '.card{width:100%;max-width:360px;text-align:center}h1{color:#FFD700;font-size:22px;margin:0 0 8px}'
    + 'p{color:#aaa;font-size:14px;line-height:1.4;margin:0 0 20px}'
    + 'input{width:100%;padding:14px;margin:8px 0;border-radius:10px;border:1px solid #333;'
    + 'background:#1c1c1c;color:#eee;font-size:16px}'
    + 'button[type=submit]{width:100%;padding:14px;margin-top:12px;border:0;border-radius:10px;background:#FFD700;'
    + 'color:#111;font-size:16px;font-weight:600}button[type=submit]:disabled{opacity:.5}'
    + '#err{color:#ff6b6b;font-size:13px;min-height:18px;margin-top:8px}#msg{color:#FFD700;font-size:14px}'
    + '#langbtn{position:fixed;top:calc(env(safe-area-inset-top,0px) + 12px);right:12px;width:42px;height:42px;'
    + 'border-radius:50%;border:1px solid #333;background:#1c1c1c;color:#FFD700;font-size:13px;font-weight:700;'
    + 'padding:0;z-index:10;cursor:pointer;display:flex;align-items:center;justify-content:center}'
    + '.langmenu{position:fixed;top:calc(env(safe-area-inset-top,0px) + 60px);right:12px;background:#1c1c1c;'
    + 'border:1px solid #333;border-radius:12px;padding:6px;z-index:11;max-height:70vh;overflow:auto;min-width:150px;'
    + 'box-shadow:0 6px 20px rgba(0,0,0,.5)}'
    + '.langmenu button{display:block;width:100%;text-align:left;background:transparent;color:#eee;border:0;'
    + 'border-radius:8px;padding:11px 12px;font-size:15px;margin:0;font-weight:400;cursor:pointer}'
    + '.langmenu button.cur{color:#FFD700;font-weight:700;background:#262626}'
    + '[dir=rtl] #langbtn,[dir=rtl] .langmenu{right:auto;left:12px}[dir=rtl] .langmenu button{text-align:right}'
    + '</style></head><body>'
    + '<button id="langbtn" type="button" aria-label="Language">EN</button>'
    + '<div id="langmenu" class="langmenu" hidden></div>'
    + '<div class="card"><h1 id="title"></h1><p id="sub"></p>'
    + '<form id="f"><input id="p" type="password" inputmode="text" autocomplete="' + (mode === 'setup' ? 'new-password' : 'current-password') + '" autofocus />'
    + confirmField
    + '<button type="submit" id="btn"></button>'
    + '<div id="err"></div><div id="msg"></div></form></div>'
    + '<script>'
    + 'var MODE="' + mode + '";var I18N=' + JSON.stringify(LOCK_I18N) + ';var LANGS=' + JSON.stringify(LOCK_LANGS) + ';'
    + 'var $=function(id){return document.getElementById(id);};'
    + 'function getLang(){try{var s=localStorage.getItem("oasisLockLang");if(s&&I18N[s])return s;}catch(e){}return "en";}'
    + 'var LANG=getLang();'
    + 'function setCookie(l){try{document.cookie="language="+l+";path=/;max-age=31536000";}catch(e){}}'
    + 'try{if(localStorage.getItem("oasisLockLang"))setCookie(LANG);}catch(e){}'
    + 'function apply(){var t=I18N[LANG]||I18N.en;'
    + 'document.documentElement.lang=LANG;document.documentElement.dir=(LANG==="ar")?"rtl":"ltr";'
    + '$("title").innerHTML=(MODE==="setup")?t.t_setup:t.t_unlock;'
    + '$("sub").innerHTML=(MODE==="setup")?t.s_setup:t.s_unlock;'
    + '$("p").placeholder=t.ph;var c=$("c");if(c)c.placeholder=t.ph2;'
    + '$("btn").textContent=(MODE==="setup")?t.b_setup:t.b_unlock;'
    + '$("langbtn").textContent=LANG.toUpperCase();}'
    + 'function buildMenu(){var m=$("langmenu");m.innerHTML="";LANGS.forEach(function(l){'
    + 'var b=document.createElement("button");b.type="button";b.textContent=(I18N[l]&&I18N[l].name)||l;'
    + 'if(l===LANG)b.className="cur";b.onclick=function(){LANG=l;try{localStorage.setItem("oasisLockLang",l);}catch(e){}'
    + 'setCookie(l);apply();buildMenu();m.hidden=true;};m.appendChild(b);});}'
    + '$("langbtn").onclick=function(){var m=$("langmenu");m.hidden=!m.hidden;};'
    + 'document.addEventListener("click",function(e){var m=$("langmenu");if(!m.hidden&&e.target!==$("langbtn")&&!m.contains(e.target))m.hidden=true;});'
    + 'buildMenu();apply();'
    + 'var f=$("f"),err=$("err"),msg=$("msg");'
    + 'f.addEventListener("submit",async function(e){e.preventDefault();var t=I18N[LANG]||I18N.en;err.textContent="";'
    + 'var p=$("p").value,c=$("c");'
    + 'if(MODE==="setup"){if(p.length<6){err.textContent=t.e_min;return;}if(c&&c.value!==p){err.textContent=t.e_mism;return;}}'
    + 'var btn=$("btn");btn.disabled=true;'
    + 'try{var r=await fetch(MODE==="setup"?"/__keylock/setup":"/__keylock/unlock",{method:"POST",'
    + 'headers:{"Content-Type":"application/json"},body:JSON.stringify({password:p})});'
    + 'if(r.ok){msg.textContent=t.m_unlock;waitReload();}else{err.textContent=t.e_wrong;btn.disabled=false;}}'
    + 'catch(e2){err.textContent=t.e_pre+e2.message;btn.disabled=false;}});'
    + 'async function waitReload(){for(var i=0;i<120;i++){try{var r=await fetch("/?_k="+Date.now(),{cache:"no-store"});'
    + 'var t=await r.text();if(t.indexOf("OASIS_LOCK_MARKER")===-1){location.reload();return;}}catch(e){}'
    + 'await new Promise(function(s){setTimeout(s,500);});}location.reload();}'
    + '</script></body></html>';
}

function readBody(req) {
  return new Promise((resolve) => {
    let b = '';
    req.on('data', (d) => { b += d; if (b.length > 1e5) req.destroy(); });
    req.on('end', () => { try { resolve(JSON.parse(b || '{}')); } catch (_) { resolve({}); } });
    req.on('error', () => resolve({}));
  });
}

const sockets = new Set();
const lockServer = http.createServer(async (req, res) => {
  try {
    if (req.method === 'POST' && req.url === '/__keylock/setup') {
      const { password } = await readBody(req);
      if (!password || String(password).length < 6) { res.writeHead(400, { 'Connection': 'close' }); return res.end('{"ok":false}'); }
      keylock.setPassword(configPath, password);
      const keys = keylock.loadOrCreateSecret(configPath);
      res.writeHead(200, { 'Content-Type': 'application/json', 'Connection': 'close' });
      res.end('{"ok":true}');
      return unlockAndStart(keys);
    }
    if (req.method === 'POST' && req.url === '/__keylock/unlock') {
      const { password } = await readBody(req);
      const kek = password ? keylock.verifyPassword(configPath, password) : null;
      if (!kek) { res.writeHead(401, { 'Connection': 'close' }); return res.end('{"ok":false}'); }
      const keys = keylock.loadOrCreateSecret(configPath);
      res.writeHead(200, { 'Content-Type': 'application/json', 'Connection': 'close' });
      res.end('{"ok":true}');
      return unlockAndStart(keys);
    }
    res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Connection': 'close' });
    res.end(lockPage(MODE));
  } catch (e) {
    res.writeHead(500, { 'Connection': 'close' });
    res.end('{"ok":false,"error":"' + String(e && e.message).replace(/"/g, '') + '"}');
  }
});
lockServer.on('connection', (s) => { sockets.add(s); s.on('close', () => sockets.delete(s)); });
lockServer.listen(3000, '127.0.0.1', () => {
  console.log('[Oasis] keylock gate escuchando en 127.0.0.1:3000 (modo: ' + MODE + ')');
});
