#!/usr/bin/env python3
"""Install this bundle on the host; preserve its existing data, config and runs."""
import argparse
from datetime import datetime,timezone
import hashlib
from pathlib import Path
import shutil
ROOT=Path(__file__).resolve().parent

def sha(p):
 h=hashlib.sha256()
 with p.open('rb') as f:
  for b in iter(lambda:f.read(1024*1024),b''):h.update(b)
 return h.digest()

def install(target):
 target=Path(target).expanduser().resolve()
 if target==ROOT:raise ValueError('Choose an installation folder distinct from this source bundle')
 stamp=datetime.now(timezone.utc).strftime('%Y%m%dT%H%M%S%fZ');backup=target/'backups'/('journey_'+stamp)
 installed=0;preserved=[]
 for source in sorted(ROOT.rglob('*')):
  rel=source.relative_to(ROOT)
  if not source.is_file() or '__pycache__' in rel.parts or rel.parts[0] in ('backups','runs') or rel.name=='MANIFEST.json':continue
  dest=target/rel
  if dest.is_symlink():raise ValueError('Refusing to replace symlink: '+str(dest))
  if dest.exists():
   if sha(source)==sha(dest):continue
   if rel.parts[0] in ('data','vendor') or rel.name=='replay_config.json':
    # Never replace a fuller host dataset with this bounded source delivery.
    dest=target/'incoming_journey'/stamp/rel;preserved.append(str(rel))
   else:
    old=backup/rel;old.parent.mkdir(parents=True,exist_ok=True);shutil.copy2(dest,old)
  dest.parent.mkdir(parents=True,exist_ok=True);shutil.copy2(source,dest);installed+=1
 print('Installed files:',installed,'\nProject:',target,'\nData:',target/'data')
 if preserved:print('Existing data/config preserved. Incoming differing copies are under incoming_journey/'+stamp+':',', '.join(preserved))
 print('No service restarted. Existing run databases and attempt counters remain untouched.')

if __name__=='__main__':
 p=argparse.ArgumentParser(description=__doc__);p.add_argument('--target',type=Path,default=Path('/Users/bpa/Desktop/ForesixaQuant/FinBot_Century_Gauntlet'));a=p.parse_args();install(a.target)
