"""Package safe review pages for OSS; embed exact existing dependencies, never credentials."""
from pathlib import Path
import base64,json,mimetypes,re,hashlib,subprocess,sys
from html import escape
R=Path(__file__).parent.resolve();repo=R.parents[1]
front=repo.parent/'zhctproject/store/public/static'
out=R/'public-build';out.mkdir(exist_ok=True)
def data(path):return 'data:'+(mimetypes.guess_type(path.name)[0] or 'application/octet-stream')+';base64,'+base64.b64encode(path.read_bytes()).decode()
def css(path):
 text=path.read_text()
 def replace(m):
  u=m.group(1).strip('"\' ')
  if u.startswith(('data:','http:','https:','#')):return m.group(0)
  p=(path.parent/u.split('?')[0].split('#')[0]).resolve()
  if not p.exists():raise RuntimeError('CSS asset not found: '+str(p))
  return 'url("'+data(p)+'")'
 return re.sub(r'url\(([^)]+)\)',replace,text)
def script(path):return path.read_text().replace('</script','<\\/script')
pc=(R/'food-record-reuse.html').read_text()
styles={'/runtime/element.css':front/'node_modules/element-ui/lib/theme-chalk/index.css','preview.css':R/'preview.css'}
js={'/runtime/exceljs.js':Path('/Users/jack/.codex/ruflo-runtime/diet-photo-20260914/deps/node_modules/exceljs/dist/exceljs.min.js'),'diet-workbook.js':R/'diet-workbook.js','/runtime/jszip.js':Path('/Users/jack/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/jszip/dist/jszip.min.js'),'/runtime/vue.js':front/'node_modules/vue/dist/vue.min.js','/runtime/element.js':front/'node_modules/element-ui/lib/index.js','/runtime/echarts.js':front/'node_modules/echarts/dist/echarts.min.js','recognition-policy.js':R/'recognition-policy.js','department-export.js':R/'department-export.js','fixture.js':R/'fixture.js','preview-bundle.js':R/'preview-bundle.js'}
for url,p in styles.items():pc=pc.replace(f'<link rel="stylesheet" href="{url}">','<style>'+css(p)+'</style>')
for url,p in js.items():pc=pc.replace(f'<script src="{url}"></script>','<script>'+script(p)+'</script>')
pc=pc.replace('/runtime/logo.png',data(front/'static/cptNewLogoH.png')).replace('https://zhct.yyangpt.cn/dist/#/homeMain','linked-review.html').replace('真实演示系统 ↗','返回评审入口 ↗').replace('/task/diet-weight-review.html','linked-review.html')
bridge="""<script>window.addEventListener('message',function(e){if(e.origin!==location.origin||e.source!==parent||e.data?.type!=='dwm-review-step')return;const vm=window.storeReuse;if(!vm)return;if(e.data.step==='detail'){vm.after=true;vm.member='demo-a';vm.range=['2026-09-11','2026-09-11'];vm.open('2')}else if(e.data.step==='pc')vm.dialog=false;});parent.postMessage({type:'dwm-pc-ready'},location.origin);</script>"""
licenses='\n\n'.join(name+'\n'+(front/'node_modules'/name/'LICENSE').read_text() for name in ['vue','element-ui','echarts'])+'\n\n'+(front/'node_modules/echarts/NOTICE').read_text()
licenses+='\n\nExcelJS\n'+Path('/Users/jack/.codex/ruflo-runtime/diet-photo-20260914/deps/node_modules/exceljs/LICENSE').read_text()
licenses+='\n\nJSZip\n'+Path('/Users/jack/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/jszip/LICENSE.markdown').read_text()
for extra in sorted((front/'node_modules/echarts/licenses').glob('*')):
 if extra.is_file():licenses+='\n\n'+extra.name+'\n'+extra.read_text()
# ECharts contains literal </body> inside JS strings: append only at the document tail.
pc_head,pc_tail=pc.rsplit('</body>',1)
pc=pc_head+bridge+'<pre hidden id="third-party-licenses">'+escape(licenses)+'</pre></body>'+pc_tail
assert pc.count('id="third-party-licenses"')==1
(out/'pc-review.html').write_text(pc)
# Only the actual ai_app source excerpt is allowed for the mini-program surface.
subprocess.run([sys.executable,str(R/'build-meal-entry-from-code.py')],check=True)
(out/'linked-review.html').write_text((R/'linked-review.html').read_text())
manifest={}
for p in [R/'linked-review.html',out/'pc-review.html',out/'mini-program-review.html']:
 s=p.read_text()
 for forbidden in ['127.0.0.1','http://localhost','/runtime/','/Users/jack','x-yunxiao-token']:
  assert forbidden not in s,(p.name,forbidden)
 assert not re.search(r'<(?:script|link|img|iframe)[^>]+(?:src|href)=["\'](?:/(?!/)|\.\./)',s),p.name
 manifest[p.name]={'bytes':p.stat().st_size,'sha256':hashlib.sha256(p.read_bytes()).hexdigest()}
(R/'public-package-manifest.json').write_text(json.dumps({'files':manifest,'private_inputs_excluded':['demo login','original PDFs','real-user screenshots'],'runtime':'Existing local Vue2, ElementUI, ECharts embedded with original license comments','interaction':'review-only navigation; no real upload or production data'},ensure_ascii=False,indent=2)+'\n')
print(json.dumps(manifest,ensure_ascii=False))
