from pathlib import Path
import base64
import hashlib
from html.parser import HTMLParser
import json
import re

ROOT = Path(__file__).resolve().parents[2]
OUT = ROOT / 'modules/product/product-group-ai-native/ipd-ltc-itr'
source = (OUT / 'review.html').read_text()

pending = '''<section id="systems"><p class="eyebrow">第三层 · 本次先共识业务与协作</p><h2>先把流程与责任讲清，工具方案另行决定</h2><div class="banner">本次讨论IPD／LTC／ITR的边界、岗位交接、客户版本同步和问题关闭标准。软件系统、实施路线与工具选型暂不定案。</div><p>已明确的协作口径：IPD客户接口为销售和交付；项目负责人默认由交付承担。后续系统应帮助大家遵守这些流程。</p></section>'''
page, count = re.subn(r'<section id="systems">.*?</section>', pending, source, count=1, flags=re.S)
assert count == 1
consensus = '''<details class="references"><summary>这次请大家重点共识什么</summary><ul><li>三条流程边界：客户承诺走LTC，共性能力走IPD，投产问题走ITR。</li><li>每次交接说清：谁交给谁、交付物、接收条件、下一动作和结果记录。</li><li>A客户上线后，B需要自己的适用、权益、兼容、实施和验收决定。</li><li>客户问题恢复、根因解决、现场验证和客户确认分别记录。</li><li>项目负责人默认交付；IPD客户输入由销售与交付提供。</li></ul><p>本页用于讨论共识，具体人员、价格、工期、权限和上线计划仍按相应授权确认。</p></details>'''
page, count = re.subn(r'<details class="references"><summary>展开原体系、岗位分工和执行文件</summary>.*?</details>', consensus, page, count=1, flags=re.S)
assert count == 1
page = page.replace('V1.2 岗位修订与工具承载版', 'V1.3 流程协同共识版')
page = page.replace('03 工具与规则', '03 共识要点')
page = page.replace('原体系、岗位责任和执行模板', '岗位责任、交接要求与讨论重点')
page = page.replace('<title>IPD／LTC／ITR · 渐进讲解与岗位协同</title>', '<title>IPD／LTC／ITR · 流程协同共识</title>')
page = page.replace('本次更新讲解方式和协同示例。岗位用角色表示；具体人员、收费、权限与试点由相应负责人确认。未修改在线流程或实施客户升级。', '本页为流程协同共识材料。岗位以角色表示，A／B为演示客户；工具选型待定，具体人员与实施安排后续确认。')

assets = {}
for p in sorted((OUT / 'images').glob('*.svg')):
    name = p.stem
    assets[name] = {
        'png': 'data:image/png;base64,' + base64.b64encode(p.with_suffix('.png').read_bytes()).decode(),
        'svg': 'data:image/svg+xml;base64,' + base64.b64encode(p.read_bytes()).decode(),
    }

def asset_link(match):
    name, ext = match.group(1), match.group(2)
    return 'href="' + assets[name][ext] + '" download="' + name + '.' + ext + '"'

page = re.sub(r'href="images/([a-zA-Z0-9-]+)\.(png|svg)" download', asset_link, page)
old_png = "document.getElementById('download-png').href='images/'+button.dataset.image+'.png';"
old_svg = "document.getElementById('download-svg').href='images/'+button.dataset.image+'.svg';"
assert old_png in page and old_svg in page
page = page.replace(old_png, "document.getElementById('download-png').href=source.src;document.getElementById('download-png').download=button.dataset.image+'.png';")
page = page.replace(old_svg, "document.getElementById('download-svg').href=shareSVG[button.dataset.image];document.getElementById('download-svg').download=button.dataset.image+'.svg';")
svg_map = {name: value['svg'] for name, value in assets.items()}
page = page.replace('<script>', '<script>const shareSVG=' + json.dumps(svg_map) + ';', 1)

class Audit(HTMLParser):
    def __init__(self):
        super().__init__()
        self.links, self.resources, self.images = [], [], []
    def handle_starttag(self, tag, attrs):
        a = dict(attrs)
        if 'href' in a:
            self.links.append(a['href'])
        if 'src' in a:
            self.resources.append(a['src'])
        if tag == 'img' and 'src' in a:
            self.images.append(a['src'])

audit = Audit()
audit.feed(page)
assert all(u.startswith(('#', 'data:')) for u in audit.links + audit.resources)
assert len([u for u in audit.images if u.startswith('data:image/png')]) == 6
for term in ['NocoBase', '简道云', 'Frappe', 'Odoo', '127.0.0.1', 'localhost', '/Users/', 'doc.weixin.qq.com', 'AKIA', 'LTAI', 'woQsFF']:
    assert term not in page, term
assert len(assets) == 6
target = OUT / 'share.html'
target.write_text(page)
receipt = {
    'date': '2026-10-09', 'version': '1.3 share', 'local_file': str(target.relative_to(ROOT)),
    'sha256': hashlib.sha256(target.read_bytes()).hexdigest(), 'bytes': target.stat().st_size,
    'scope': 'workflow and role consensus; tool selection deferred',
    'embedded_png': 6, 'embedded_svg_downloads': 6, 'external_resource_dependencies': 0,
    'relative_file_links': 0, 'sensitivity_scan': 'passed selected patterns; manual business content review passed',
    'remote_published': False,
}
(Path(__file__).resolve().parent / 'share-publication.json').write_text(json.dumps(receipt, ensure_ascii=False, indent=2) + '\n')
print(json.dumps(receipt, ensure_ascii=False))
