"""Transactional shared-stock engine. No third-party dependencies."""
import sqlite3,json,uuid,datetime

def now(): return datetime.datetime.now(datetime.timezone.utc).isoformat()
def ident(): return uuid.uuid4().hex
class DomainError(Exception): pass
class Engine:
 def __init__(self,path):
  self.db=sqlite3.connect(path,timeout=30,isolation_level=None,check_same_thread=False)
  self.db.row_factory=sqlite3.Row
  self.db.executescript('''PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON;
CREATE TABLE IF NOT EXISTS products(id TEXT PRIMARY KEY,sku TEXT UNIQUE NOT NULL,name TEXT NOT NULL,stock INTEGER NOT NULL CHECK(stock>=0),safety INTEGER NOT NULL DEFAULT 0 CHECK(safety>=0),price REAL NOT NULL CHECK(price>=0),reorder INTEGER NOT NULL DEFAULT 5 CHECK(reorder>=0));
CREATE TABLE IF NOT EXISTS stores(id TEXT PRIMARY KEY,name TEXT NOT NULL,platform TEXT NOT NULL CHECK(platform IN ('amazon','ebay')),enabled INTEGER DEFAULT 0);
CREATE TABLE IF NOT EXISTS mappings(id TEXT PRIMARY KEY,product TEXT NOT NULL REFERENCES products(id),store TEXT NOT NULL REFERENCES stores(id),listing_sku TEXT NOT NULL,offer_id TEXT DEFAULT '',UNIQUE(store,listing_sku));
CREATE TABLE IF NOT EXISTS orders(id TEXT PRIMARY KEY,external_id TEXT NOT NULL,store TEXT NOT NULL REFERENCES stores(id),items TEXT NOT NULL,status TEXT NOT NULL,total REAL NOT NULL,created TEXT NOT NULL,tracking TEXT DEFAULT '',UNIQUE(store,external_id));
CREATE TABLE IF NOT EXISTS audit(id TEXT PRIMARY KEY,created TEXT NOT NULL,action TEXT NOT NULL,detail TEXT NOT NULL);
CREATE TABLE IF NOT EXISTS jobs(id TEXT PRIMARY KEY,store TEXT NOT NULL,product TEXT NOT NULL,status TEXT NOT NULL DEFAULT 'pending',error TEXT DEFAULT '',updated TEXT NOT NULL,UNIQUE(store,product));
CREATE TABLE IF NOT EXISTS sync_state(store TEXT PRIMARY KEY,cursor TEXT NOT NULL);
''')
 def close(self): self.db.close()
 def rows(self,t): return [dict(x) for x in self.db.execute('SELECT * FROM '+t)]
 def audit(self,a,d): self.db.execute('INSERT INTO audit VALUES(?,?,?,?)',(ident(),now(),a,d))
 def transaction(self,fn):
  self.db.execute('BEGIN IMMEDIATE')
  try:
   result=fn();self.db.execute('COMMIT');return result
  except: self.db.execute('ROLLBACK');raise
 def queue(self,p):
  for s in self.db.execute('SELECT DISTINCT store FROM mappings WHERE product=?',(p,)):
   self.db.execute("INSERT INTO jobs(id,store,product,status,error,updated) VALUES(?,?,?,'pending','',?) ON CONFLICT(store,product) DO UPDATE SET status='pending',error='',updated=excluded.updated",(ident(),s[0],p,now()))
 def seed(self):
  if self.db.execute('SELECT COUNT(*) FROM stores').fetchone()[0]: return
  for platform in ['amazon','ebay']:
   for n in range(1,11): self.db.execute('INSERT INTO stores(id,name,platform) VALUES(?,?,?)',(f'{platform}-{n:02}',f'{"Amazon UK" if platform=="amazon" else "eBay UK"} {n:02}',platform))
 def state(self):
  out={t:self.rows(t) for t in ['products','stores','mappings','orders','audit','jobs']}
  for o in out['orders']: o['items']=json.loads(o['items'])
  out['audit']=sorted(out['audit'],key=lambda x:x['created'],reverse=True)[:500]
  return out
 def apply(self,action,d):
  def work():
   if action=='product':
    sku=str(d.get('sku','')).strip();name=str(d.get('name','')).strip()
    if not sku or not name: raise DomainError('SKU and product name are required')
    values=[d.get('stock',0),d.get('safety',0),d.get('reorder',5)]
    if any(isinstance(x,bool) or not isinstance(x,int) or x<0 for x in values): raise DomainError('Quantities must be nonnegative whole numbers')
    price=float(d.get('price',0))
    if not 0<=price<=100000000: raise DomainError('Invalid price')
    pid=d.get('id') or ident()
    if d.get('id'):
     if not self.db.execute('SELECT id FROM products WHERE id=?',(pid,)).fetchone(): raise DomainError('Product not found')
     self.db.execute('UPDATE products SET sku=?,name=?,safety=?,price=?,reorder=? WHERE id=?',(sku,name,values[1],price,values[2],pid))
    else: self.db.execute('INSERT INTO products VALUES(?,?,?,?,?,?,?)',(pid,sku,name,values[0],values[1],price,values[2]))
    self.queue(pid);self.audit('Product saved',sku)
   elif action=='adjust':
    p=self.db.execute('SELECT * FROM products WHERE id=?',(d['product'],)).fetchone()
    delta=d.get('delta')
    if not p or not isinstance(delta,int) or isinstance(delta,bool) or delta==0 or p['stock']+delta<0 or not str(d.get('reason','')).strip(): raise DomainError('Valid quantity and adjustment reason required; stock cannot be negative')
    self.db.execute('UPDATE products SET stock=stock+? WHERE id=?',(delta,p['id']));self.queue(p['id']);self.audit('Stock adjusted',f"{p['sku']}: {delta:+}; {d['reason']}")
   elif action=='mapping':
    if not str(d.get('listing_sku','')).strip(): raise DomainError('Listing SKU required')
    self.db.execute('INSERT INTO mappings VALUES(?,?,?,?,?) ON CONFLICT(store,listing_sku) DO UPDATE SET product=excluded.product,offer_id=excluded.offer_id',(ident(),d['product'],d['store'],d['listing_sku'].strip(),d.get('offer_id','')))
    self.queue(d['product']);self.audit('Listing mapped',d['listing_sku'])
   elif action=='unmap':
    self.db.execute('DELETE FROM mappings WHERE id=?',(d['id'],));self.audit('Listing unlinked',d['id'])
   elif action=='store':
    name=str(d.get('name','')).strip()
    if not name: raise DomainError('Store name required')
    self.db.execute('UPDATE stores SET name=? WHERE id=?',(name,d['id']));self.audit('Store renamed',name)
   elif action=='order':
    if not str(d.get('external_id','')).strip(): raise DomainError('External order ID required')
    if self.db.execute('SELECT id FROM orders WHERE store=? AND external_id=?',(d['store'],d['external_id'])).fetchone(): return {'duplicate':True}
    items=d.get('items',[])
    if not items: raise DomainError('Order needs at least one item')
    totals={};total=0;clean=[]
    for i in items:
     q=i.get('qty')
     if not isinstance(q,int) or isinstance(q,bool) or q<=0: raise DomainError('Order quantity must be a positive whole number')
     p=self.db.execute('SELECT * FROM products WHERE id=?',(i['product'],)).fetchone()
     if not p: raise DomainError('Unknown product')
     totals[p['id']]=totals.get(p['id'],0)+q
     clean.append({'product':p['id'],'sku':p['sku'],'qty':q,'price':p['price']});total+=q*p['price']
    for pid,q in totals.items():
     r=self.db.execute('UPDATE products SET stock=stock-? WHERE id=? AND stock>=?',(q,pid,q))
     if not r.rowcount: raise DomainError('Insufficient shared stock; order not applied')
     self.queue(pid)
    self.db.execute('INSERT INTO orders(id,external_id,store,items,status,total,created) VALUES(?,?,?,?,?,?,?)',(ident(),d['external_id'],d['store'],json.dumps(clean),'open',round(total,2),now()));self.audit('Order received',d['external_id'])
   elif action=='cancel':
    o=self.db.execute('SELECT * FROM orders WHERE id=?',(d['id'],)).fetchone()
    if not o: raise DomainError('Order not found')
    if o['status']=='cancelled': return {'duplicate':True}
    if o['status']!='open': raise DomainError('Only open orders can be cancelled; process shipped returns separately')
    for i in json.loads(o['items']):
     self.db.execute('UPDATE products SET stock=stock+? WHERE id=?',(i['qty'],i['product']));self.queue(i['product'])
    self.db.execute("UPDATE orders SET status='cancelled' WHERE id=?",(d['id'],));self.audit('Order cancelled / stock restored',o['external_id'])
   elif action=='ship':
    if not str(d.get('tracking','')).strip(): raise DomainError('Tracking reference required')
    r=self.db.execute("UPDATE orders SET status='shipped',tracking=? WHERE id=? AND status='open'",(d['tracking'],d['id']))
    if not r.rowcount: raise DomainError('Only open orders can be shipped')
    self.audit('Marked shipped locally',d['tracking'])
   else: raise DomainError('Unknown action')
   return {'ok':True}
  return self.transaction(work)
