"""Local fictional learning reference. No website/database/cloud connection."""
import csv,json,sqlite3,hashlib,math,re,statistics,collections
from pathlib import Path

def rows(source,name):
 with (Path(source)/name).open(encoding='utf-8',newline='') as f:return list(csv.DictReader(f))

def fit_service(source):
 import numpy as np
 data=[r for r in rows(source,'telemetry.csv') if r['period']=='train'];x=np.array([[1,float(r['distance_km']),float(r['load_ratio'])] for r in data]);y=np.array([float(r['actual_hours']) for r in data]);coef=np.linalg.lstsq(x,y,rcond=None)[0]
 return {'schema_version':1,'model_id':'haven-duration-v1','features':['distance_km','load_ratio'],'coefficients':coef.tolist(),'target_unit':'hours','training_rows':len(data),'bounds':{'distance_km':[0,250],'load_ratio':[0,1.2]}}

def predict_payload(payload,model):
 if not isinstance(payload,dict) or set(payload)!=set(model['features']):raise ValueError('Exactly distance_km and load_ratio are required')
 values=[]
 for key in model['features']:
  value=payload[key]
  if isinstance(value,bool) or not isinstance(value,(int,float)) or not math.isfinite(value):raise ValueError('Finite numeric input required')
  lo,hi=model['bounds'][key]
  if not lo<=value<=hi:raise ValueError('Outside supported teaching range')
  values.append(value)
 answer=model['coefficients'][0]+sum(c*v for c,v in zip(model['coefficients'][1:],values))
 return {'model_id':model['model_id'],'prediction_hours':answer,'unit':'hours','automated_decision':False}

def mlops_api(source,out):
 model=fit_service(source);(Path(out)/'model.json').write_text(json.dumps(model,indent=2)+'\n');cases=[]
 for payload in [{'distance_km':100,'load_ratio':.5},{'distance_km':-1,'load_ratio':.5},{'distance_km':True,'load_ratio':.5},{'distance_km':100}]:
  try:cases.append({'input':payload,'response':predict_payload(payload,model)})
  except ValueError as e:cases.append({'input':payload,'error':str(e)})
 return {'cases':cases,'model':'model.json','binding':'Optional server example binds only 127.0.0.1; never installed on this website.'}

if __name__=='__main__':
    import argparse,platform
    parser=argparse.ArgumentParser();parser.add_argument('--source',default='.');parser.add_argument('--output',required=True);args=parser.parse_args()
    source=Path(args.source).resolve();out=Path(args.output).resolve()
    if source==out:raise ValueError('Source and output must differ')
    out.mkdir(parents=False,exist_ok=False)
    # Partial folders after an error are NOT successful; result.json is written last.
    result=mlops_api(source,out)
    with (out/'result.json').open('x',encoding='utf-8') as handle:json.dump(result,handle,indent=2,allow_nan=False);handle.write(chr(10))
    print(json.dumps(result,indent=2,allow_nan=False))
