#!/usr/bin/env node
import{join as e}from"path";import{closeSync as t,constants as n,existsSync as r,mkdirSync as i,openSync as a,readFileSync as o,statSync as s,unlinkSync as c,writeSync as l}from"fs";import{homedir as u}from"os";import{spawn as d}from"child_process";const f=`http://localhost:${parseInt(process.env.OCTOCODE_PORT||`1987`,10)}/health`,p=e(u(),`.octocode`),m=e(p,`server-init.lock`),h=parseInt(process.env.OCTOCODE_LOCK_TIMEOUT||`60000`,10),g=parseInt(process.env.OCTOCODE_INIT_TIMEOUT||`30000`,10),_=parseInt(process.env.OCTOCODE_POLL_INTERVAL||`500`,10);function v(){r(p)||i(p,{recursive:!0})}function y(e){if(!r(e))return!0;try{let t=o(e,`utf-8`);if(t&&t.trim().length>0){let e=JSON.parse(t);if(Date.now()-e.timestamp>h)return!0;try{return process.kill(e.pid,0),!1}catch{return!0}}}catch{}try{let t=s(e);return Date.now()-t.mtimeMs>h}catch{return!0}}function b(e){try{r(e)&&c(e)}catch{}}async function x(){v();for(let e=0;e<3;e++)try{let e=a(m,n.O_CREAT|n.O_EXCL|n.O_WRONLY),r={pid:process.pid,timestamp:Date.now()};return l(e,JSON.stringify(r)),t(e),!0}catch(e){let t=e;if(t.code===`EEXIST`){if(y(m)){b(m),await new Promise(e=>setTimeout(e,50));continue}return!1}else return console.error(`[server-init] Lock error: ${t.message}`),!1}return!1}function S(){try{r(m)&&JSON.parse(o(m,`utf-8`)).pid===process.pid&&c(m)}catch{}}async function C(){try{let e=await fetch(f,{signal:AbortSignal.timeout(5e3)});return e.ok?await e.json():null}catch(e){return e instanceof Error&&!e.message.includes(`ECONNREFUSED`)&&console.error(`[server-init] Health check error: ${e.message}`),null}}function w(){return new Promise((t,n)=>{let r=new URL(`.`,import.meta.url).pathname,i=d(`node`,[e(r,`server.js`)],{detached:!0,stdio:`ignore`,cwd:r});i.on(`error`,e=>{console.error(`[server-init] Failed to start server: ${e.message}`),n(e)}),setTimeout(()=>{i.unref(),console.log(`[server-init] Started server process (pid: ${i.pid})`),t()},100)})}async function T(){let e=Date.now(),t=_;for(;Date.now()-e<g;){let e=await C();if(e?.status===`ok`)return!0;e?.status===`initializing`&&console.log(`[server-init] Server initializing...`),await new Promise(e=>setTimeout(e,t)),t=Math.min(t*1.5,2e3)}return!1}async function E(){let e=await C();e?.status===`ok`&&(console.log(`ok`),process.exit(0)),e?.status===`initializing`&&(console.log(`[server-init] Server is initializing, waiting...`),await T()?(console.log(`ok`),process.exit(0)):(console.error(`[server-init] ERROR: Server stuck in initializing state`),process.exit(1))),await x()||(console.log(`[server-init] Another process is starting server, waiting...`),await T()?(console.log(`ok`),process.exit(0)):(console.error(`[server-init] ERROR: Timeout waiting for server`),process.exit(1)));try{let e=await C();e?.status===`ok`&&(console.log(`ok`),S(),process.exit(0)),e?.status===`initializing`&&(console.log(`[server-init] Server is initializing, waiting...`),await T()?(console.log(`ok`),S(),process.exit(0)):(console.error(`[server-init] ERROR: Server stuck in initializing state`),S(),process.exit(1))),console.log(`[server-init] Server not running, starting...`);try{await w()}catch{console.error(`[server-init] ERROR: Failed to spawn server process`),S(),process.exit(1)}await T()?(console.log(`ok`),S(),process.exit(0)):(console.error(`[server-init] ERROR: Server failed to start within timeout`),S(),process.exit(1))}catch(e){console.error(`[server-init] ERROR:`,e instanceof Error?e.message:e),S(),process.exit(1)}}process.on(`SIGINT`,()=>{S(),process.exit(130)}),process.on(`SIGTERM`,()=>{S(),process.exit(143)}),E();export{};