#!/usr/bin/env python3
"""MES REST contract sandbox, NOT a real MES. SQLite persistence + idempotent events.
Run behind HTTPS reverse proxy; ASLA_MES_TOKEN (24+ chars), ASLA_MES_DB.
Load work orders into SQLite orders table or POST /api/work-orders with same auth.
For a real MES replace SQL operations with its supported transaction API.
"""
import os,json,sqlite3,hmac,threading
from http.server import ThreadingHTTPServer,BaseHTTPRequestHandler
class MES:
 def __init__(self,path):
  self.db=sqlite3.connect(path,check_same_thread=False);self.lock=threading.Lock();self.db.executescript('CREATE TABLE IF NOT EXISTS orders(external_id TEXT PRIMARY KEY,body TEXT);CREATE TABLE IF NOT EXISTS events(stream TEXT,seq INTEGER,body TEXT,PRIMARY KEY(stream,seq));');self.db.commit()
 def orders(self):
  with self.lock:return{'items':[json.loads(r[0])for r in self.db.execute('SELECT body FROM orders LIMIT 100')]}
 def create(self,b):
  assert b.get('scenario')in['solo','cobot','orchestration','logistics']and isinstance(b.get('quantity'),int)and 1<=b['quantity']<=1000 and isinstance(b.get('external_id'),str),'order schema'
  with self.lock:
   old=self.db.execute('SELECT body FROM orders WHERE external_id=?',(b['external_id'],)).fetchone();text=json.dumps(b,sort_keys=True)
   assert not old or old[0]==text,'external_id conflict';self.db.execute('INSERT OR IGNORE INTO orders VALUES (?,?)',(b['external_id'],text));self.db.commit()
  return{'accepted':True,'external_id':b['external_id']}
 def events(self,b):
  rows=b.get('events');assert isinstance(rows,list)and 0<len(rows)<=200,'events schema';assert all(isinstance(r.get('seq'),int)for r in rows),'seq required';stream=str(b.get('stream_id','default'))
  with self.lock:
   for r in rows:
    text=json.dumps(r,sort_keys=True);old=self.db.execute('SELECT body FROM events WHERE stream=? AND seq=?',(stream,r['seq'])).fetchone();assert not old or old[0]==text,'event seq conflict'
   self.db.executemany('INSERT OR IGNORE INTO events VALUES (?,?,?)',[(stream,r['seq'],json.dumps(r,sort_keys=True))for r in rows]);self.db.commit()
  return{'accepted_seq':max(r['seq']for r in rows)}
def serve(mes,token,port=8089):
 class Handler(BaseHTTPRequestHandler):
  def log_message(self,*args):pass
  def reply(self,code,b):
   raw=json.dumps(b).encode();self.send_response(code);self.send_header('Content-Type','application/json');self.send_header('Content-Length',str(len(raw)));self.end_headers();self.wfile.write(raw)
  def auth(self):return hmac.compare_digest(self.headers.get('Authorization',''),'Bearer '+token)
  def do_GET(self):
   if not self.auth():return self.reply(401,{'error':'unauthorized'})
   if self.path=='/health':return self.reply(200,{'ok':True,'service':'asla-mes-adapter','sandbox':True})
   if self.path=='/api/work-orders':return self.reply(200,mes.orders())
   self.reply(404,{'error':'not found'})
  def do_POST(self):
   if not self.auth():return self.reply(401,{'error':'unauthorized'})
   try:
    n=int(self.headers.get('Content-Length',0));assert 0<n<=1024*1024,'body limit';b=json.loads(self.rfile.read(n));result=mes.events(b)if self.path=='/api/events'else mes.create(b)if self.path=='/api/work-orders'else None;assert result is not None,'unknown route';self.reply(200,result)
   except (AssertionError,ValueError)as e:self.reply(422,{'error':str(e)})
 return ThreadingHTTPServer(('127.0.0.1',port),Handler)
if __name__=='__main__':
 token=os.environ.get('ASLA_MES_TOKEN','');assert len(token)>=24,'ASLA_MES_TOKEN (24+ chars) required';serve(MES(os.environ.get('ASLA_MES_DB','mes-contract.sqlite')),token,int(os.environ.get('ASLA_MES_PORT','8089'))).serve_forever()
