#!/usr/bin/env node
import{existsSync as e,mkdirSync as t,readFileSync as n,renameSync as r,rmSync as i,writeFileSync as a}from"node:fs";import{dirname as o,join as s,resolve as c}from"node:path";import{fileURLToPath as l}from"node:url";import{createLogger as u}from"../../core/dist/index.js";import{homedir as d}from"node:os";import{execFile as f,execSync as p}from"node:child_process";const m=`@vpxa/aikit`,h=`https://registry.npmjs.org/${m}/latest`,g=u(`server`),_=s(d(),`.aikit`),v=s(_,`current-version.json`),y=s(_,`versions`),b=/^\d+\.\d+\.\d+(-[\w.+]+)?(\+[\w.]+)?$/;function x(e){if(!b.test(e))throw Error(`Invalid semver version: ${JSON.stringify(e)}`)}function S(){let e=c(o(l(import.meta.url)),`..`,`..`,`..`,`package.json`);try{return JSON.parse(n(e,`utf-8`)).version??`0.0.0`}catch{return`0.0.0`}}function C(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){let t=(n[e]??0)-(r[e]??0);if(t!==0)return t>0?1:-1}return 0}function w(e,t){let n=e.split(`.`).map(Number),r=t.split(`.`).map(Number);for(let e=0;e<3;e++){if((n[e]??0)>(r[e]??0))return!0;if((n[e]??0)<(r[e]??0))return!1}return!1}async function T(n){x(n);let o=`v${n}`,c=s(y,`${o}-staging`),l=s(y,o);try{e(c)&&i(c,{recursive:!0,force:!0}),t(c,{recursive:!0}),p(`tar -xzf "${p(`npm pack ${m}@${n}`,{cwd:c,encoding:`utf-8`,timeout:6e4,windowsHide:!0}).trim()}"`,{cwd:c,encoding:`utf-8`,timeout:3e4,windowsHide:!0});let u=s(c,`package`);p(`npm install --production --install-strategy=nested --no-audit --no-fund`,{cwd:u,encoding:`utf-8`,timeout:12e4,windowsHide:!0});let d=s(u,`packages`,`server`,`dist`,`bin.js`);if(!e(d))throw Error(`Server entry not found at ${d}`);if(!e(s(u,`node_modules`)))throw Error(`node_modules not found — npm install may have failed`);let f=`${v}.tmp`;a(f,JSON.stringify({version:n,installedAt:new Date().toISOString()},null,2)),r(f,v),e(l)&&i(l,{recursive:!0,force:!0}),r(u,l),g.info(`Installed version ${o}`,{targetDir:l})}finally{e(c)&&i(c,{recursive:!0,force:!0})}}async function E(){try{let t=n(v,`utf-8`),{version:i}=JSON.parse(t),o=await fetch(h,{signal:AbortSignal.timeout(1e4)});if(!o.ok)return;let c=(await o.json()).version;if(!c||c===i||!w(c,i))return;if(e(s(y,`v${c}`))){let e=`${v}.tmp`;a(e,JSON.stringify({version:c,installedAt:new Date().toISOString()},null,2)),r(e,v),g.info(`Re-activated existing version v${c} — no download needed`);return}g.info(`New version available: ${c}. Installing...`),await T(c),g.info(`Updated to v${c}. Restart to use.`)}catch(e){g.error(`Background update check failed: ${e instanceof Error?e.message:String(e)}`)}}function D(){if(e(v)){E();return}let t=S();fetch(h,{signal:AbortSignal.timeout(1e4)}).then(e=>{if(e.ok)return e.json()}).then(async e=>{if(!e||typeof e!=`object`)return;let n=e.version;if(n&&C(t,n)<0){g.info(`Newer version available — installing`,{currentVersion:t,latestVersion:n});try{await T(n),g.info(`Installed v${n}. Restart MCP to use.`)}catch(e){g.warn(`Auto-install failed`,{error:e instanceof Error?e.message:String(e),latestVersion:n})}}}).catch(()=>{})}function O(){try{let t=c(d(),`.copilot`,`.aikit-scaffold.json`);return e(t)?JSON.parse(n(t,`utf-8`)).version??null:null}catch{return null}}function k(){try{let t=c(process.cwd(),`.github`,`.aikit-scaffold.json`);return e(t)?JSON.parse(n(t,`utf-8`)).version??null:null}catch{return null}}let A=`idle`,j=null,M=null;function N(){return{state:A,error:j}}function P(){A=`idle`,j=null}function F(){try{let t=S(),n=O(),r=k(),i=n!=null&&n!==t,a=r!=null&&r!==t;if(D(),!i&&!a||(M!==t&&(P(),M=t),A!==`idle`))return;A=`pending`,j=null,g.info(`Scaffold version mismatch — auto-upgrading`,{serverVersion:t,userScaffoldVersion:n,workspaceScaffoldVersion:r});let s=o(l(import.meta.url)),u=[c(s,`..`,`..`,`..`,`bin`,`aikit.mjs`),c(s,`..`,`bin`,`aikit.mjs`),...process.argv[1]?[c(o(process.argv[1]),`aikit.mjs`)]:[]],d=u.find(t=>e(t));if(!d){A=`failed`,j=`aikit CLI binary not found. Tried: ${u.join(`, `)}`,g.warn(`Cannot auto-upgrade: aikit CLI binary not found`,{candidates:u,platform:process.platform});return}f(process.execPath,[d,`upgrade`],{timeout:3e4,windowsHide:!0},(e,n,r)=>{e?(A=`failed`,j=e.message,g.warn(`Auto-upgrade failed`,{error:e.message,stderr:r?.slice(0,500),binPath:d,platform:process.platform})):(A=`success`,j=null,g.info(`Auto-upgrade completed to version ${t}`))}).unref()}catch(e){A=`failed`,j=e instanceof Error?e.message:String(e),g.warn(`Auto-upgrade check failed`,{error:j})}}export{F as autoUpgradeScaffold,D as checkForUpdates,S as getCurrentVersion,N as getUpgradeState};