import http from 'node:http';
import { readFile, stat } from 'node:fs/promises';
import { extname, join, normalize } from 'node:path';
import { fileURLToPath } from 'node:url';
import { analyzePhoto } from './src/vision-service.js';
import { probeVisionProvider, resolveVisionConfig } from './src/vision-config.js';

const root=fileURLToPath(new URL('.',import.meta.url));
const port=Number(process.env.PORT||4173);
const types={'.html':'text/html; charset=utf-8','.js':'text/javascript; charset=utf-8','.css':'text/css; charset=utf-8','.json':'application/json; charset=utf-8','.webmanifest':'application/manifest+json','.svg':'image/svg+xml'};
const visionConfig=resolveVisionConfig(process.env);

function sendJson(res,status,value){res.writeHead(status,{'content-type':'application/json; charset=utf-8','cache-control':'no-store','x-content-type-options':'nosniff'});res.end(JSON.stringify(value));}
function readJson(req,maxBytes=6*1024*1024){return new Promise((resolve,reject)=>{let size=0;const chunks=[];req.on('data',chunk=>{size+=chunk.length;if(size>maxBytes){reject(new Error('Photo request is too large.'));req.destroy();return}chunks.push(chunk)});req.on('end',()=>{try{resolve(JSON.parse(Buffer.concat(chunks).toString('utf8')))}catch{reject(new Error('Invalid JSON request.'))}});req.on('error',reject)})}

http.createServer(async(req,res)=>{
 try{
  const url=new URL(req.url,'http://localhost');
  if(url.pathname==='/api/vision-status'&&req.method==='GET'){
   const provider=await probeVisionProvider(visionConfig);
   const privacy=visionConfig.profile==='selfhost'?'The compressed image is processed by Timmy’s self-hosted model and is not forwarded to a third-party model provider.':'A compressed copy is sent to the configured AI provider only when you explicitly request analysis.';
   return sendJson(res,200,{...visionConfig.publicStatus(),providerReady:provider.ready,modelSeen:provider.modelSeen,privacy});
  }
  if(url.pathname==='/api/analyze'&&req.method==='POST'){
   if(!visionConfig.enabled)return sendJson(res,503,{error:'AI analysis is disabled. Continue manually.'});
   const payload=await readJson(req);
   try{return sendJson(res,200,await analyzePhoto({payload,config:visionConfig}))}
   catch(error){const safe=/consent|JPEG|PNG|WebP|empty|too large/i.test(error.message);return sendJson(res,safe?400:503,{error:error.message})}
  }
  if(url.pathname.startsWith('/api/'))return sendJson(res,404,{error:'Not found'});
  if(req.method!=='GET'&&req.method!=='HEAD'){res.writeHead(405,{'allow':'GET, HEAD'});return res.end()}
  const pathname=decodeURIComponent(url.pathname);
  let path=normalize(join(root,pathname==='/'?'index.html':pathname));
  if(!path.startsWith(root))throw new Error('bad path');
  const info=await stat(path);if(info.isDirectory())path=join(path,'index.html');
  const body=await readFile(path);res.writeHead(200,{'content-type':types[extname(path)]||'application/octet-stream','cache-control':'no-store','x-content-type-options':'nosniff'});if(req.method==='HEAD')res.end();else res.end(body);
 }catch{res.writeHead(404,{'content-type':'text/plain; charset=utf-8'});res.end('Not found')}
}).listen(port,'0.0.0.0',()=>console.log(`Timmy is listening on http://0.0.0.0:${port} · AI ${visionConfig.enabled?'ready for provider':'disabled'}`));
