"""Build the reading page and CSV annexes from the frozen research document."""
import base64
import csv
import html
import json
import math
import subprocess
from html.parser import HTMLParser
from pathlib import Path

OUT = Path(__file__).resolve().parent


def csv_write(name, rows):
    with (OUT/name).open('w',encoding='utf-8-sig',newline='') as f:
        csv.writer(f).writerows(rows)


def plain(node):
    if isinstance(node,list):
        return ''.join(plain(n) for n in node)
    if isinstance(node,dict):
        kind=node.get('t')
        c=node.get('c')
        if kind=='Str': return c
        if kind in ('Space','SoftBreak','LineBreak'): return ' '
        if kind=='Code': return c[1]
        if kind in ('Link','Image'): return plain(c[1])
        return plain(c)
    return ''


doc=json.loads(subprocess.check_output(['pandoc',str(OUT/'market-research.md'),'-t','json']))
section=''
tables={}
for b in doc['blocks']:
    if b['t']=='Header': section=plain(b['c'][2])
    if b['t']=='Table':
        c=b['c']
        rows=c[3][1]+[row for body in c[4] for row in body[2]+body[3]]+c[5][1]
        tables.setdefault(section,[]).append([[plain(cell[4]).strip() for cell in row[1]] for row in rows])
mapping={
    'segment-decision-matrix.csv':('5. 六大场景要拆成十种购买市场',0),
    'buyer-unit.csv':('7. 用户画像：要分别找付款人、执行人和受益人',0),
    'competitive-budget-map.csv':('9. 竞争要比较同一笔预算',0),
    'validation-backlog.csv':('11. 接下来90天怎样干',0),
    'market-sizing-model.csv':('4.3 正确的TAM/SAM/SOM模型',0),
    'market-scenarios.csv':('4.3 正确的TAM/SAM/SOM模型',1),
}
for dest,(heading,index) in mapping.items(): csv_write(dest,tables[heading][index])
journey=[['track','stage','buyer_question','deliverable_or_evidence','next_gate']]
for heading,track in [('经营采购：从问题到验收','经营'),('健康购买：从明确目标到再次付费','健康')]:
    for row in tables[heading][0][1:]: journey.append([track]+row+([''] if len(row)==3 else []))
csv_write('journey-gates.csv',journey)
ledger=[['evidence_id','source','level','fact','not_proven','read_status']]
with (OUT/'deep-read-manifest.csv').open(encoding='utf-8-sig') as f:
    for r in csv.DictReader(f): ledger.append([r['evidence_id'],r['source_path'],r['level'],r['fact'],r['not_proven'],r['read_status']])
with (OUT/'public-sources.csv').open(encoding='utf-8-sig') as f:
    for r in csv.DictReader(f): ledger.append([r['source_id'],r['url'],r['level'],r['claim'],r['boundary'],r['access_status']])
ledger.extend([
    ['U01','task:01a0bcbf-3131-7e93-a0cd-aa912beab181','B','用户陈述30多个客户主要购买结算，健康付费未验证','经营者自述非逐合同审计','thread_read'],
    ['L01','E16引用原Excel;营养结算63行/食安27行/采购17行','B','质保后维保参考为合同总金额5%','不是续约事实，非健康服务年费','xlsx_read'],
])
csv_write('evidence-ledger.csv',ledger)

body=subprocess.check_output(['pandoc',str(OUT/'market-research.md'),'-t','html5','--wrap=none'],text=True)
# CSV links stay local. Evidence files are available in the same project folder.
class TableWrapper(HTMLParser):
    def __init__(self):
        super().__init__(convert_charrefs=False)
        self.parts=[]
    def handle_starttag(self,tag,attrs):
        if tag=='table': self.parts.append('<div class="table-scroll">')
        self.parts.append(self.get_starttag_text())
    def handle_startendtag(self,tag,attrs): self.parts.append(self.get_starttag_text())
    def handle_endtag(self,tag):
        self.parts.append(f'</{tag}>')
        if tag=='table': self.parts.append('</div>')
    def handle_data(self,data): self.parts.append(data)
    def handle_entityref(self,name): self.parts.append(f'&{name};')
    def handle_charref(self,name): self.parts.append(f'&#{name};')
    def handle_comment(self,data): self.parts.append(f'<!--{data}-->')
wrapper=TableWrapper()
wrapper.feed(body)
body=''.join(wrapper.parts)
nav=[]
for b in doc['blocks']:
    if b['t']=='Header' and b['c'][0]==2:
        nav.append(f'<a href="#{html.escape(b["c"][1][0])}">{html.escape(plain(b["c"][2]))}</a>')
css=(OUT/'report.css').read_text()
tools=(OUT/'calculator.html').read_text()
chart=''
try:
    import matplotlib
    matplotlib.use('Agg')
    import matplotlib.pyplot as plt
    fig,axes=plt.subplots(1,2,figsize=(9,2.7),layout='constrained')
    for ax,values,title,unit in [(axes[0],[902.596485,810.43249],'Digital sports services revenue','RMB 10,000'),(axes[1],[42.44,27.44],'Gross margin','%')]:
        ax.barh(['2025 H1','2026 H1'],values,color=['#b7c2c6','#11756c'],height=.48)
        ax.set_title(title,loc='left',fontsize=11)
        ax.set_xlabel(unit,fontsize=9)
        ax.spines[['top','right','left']].set_visible(False)
        ax.set_xlim(0,max(values)*1.25)
        for i,v in enumerate(values): ax.text(v+max(values)*.025,i,f'{v:.2f}',va='center',fontsize=10)
    fig.savefig(OUT/'financial-evidence.png',dpi=150)
    plt.close(fig)
    uri=base64.b64encode((OUT/'financial-evidence.png').read_bytes()).decode()
    chart=f'<figure><img alt="数字体育服务：2025H1收入902.60万元及毛利率42.44%，2026H1收入810.43万元及毛利率27.44%" src="data:image/png;base64,{uri}"><figcaption>公司半年报口径，含食堂之外业务；不是健康服务收入或单SKU毛利。</figcaption></figure>'
except ImportError:
    if (OUT/'financial-evidence.png').exists():
        uri=base64.b64encode((OUT/'financial-evidence.png').read_bytes()).decode()
        chart=f'<figure><img alt="2025与2026上半年数字体育板块收入和毛利率对比" src="data:image/png;base64,{uri}"><figcaption>公司半年报口径，含食堂之外业务；不是健康服务收入或单SKU毛利。</figcaption></figure>'
    else:
        raise RuntimeError('Render financial-chart.html using verify_page.cjs --chart first')
page=f'''<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>康比特市场研究 · 2026年9月21日</title><style>{css}</style></head><body>
<header class="top"><strong>CPT / 决策研究</strong><span>2026.09.21 · 内部阅读</span></header>
<nav aria-label="报告目录">{''.join(nav)}<a href="#calculator">情景测算</a><a href="evidence-ledger.csv">证据账本</a></nav>
<main><div class="lead"><span class="eyebrow">MARKET RESEARCH</span><h1>经营已有业务，验证健康付费。</h1><p>产品和交付能力正在形成。接下来要证明的是：谁为营养健康额外付钱、服务怎样执行、双方能否持续赚钱。</p><div class="status"><span>经营：已有项目基础</span><span>健康：独立付费待证</span><span>扩张：取决于单位经济</span></div></div>{chart}<article>{body}</article>{tools}<footer>本地资料和公开来源冻结于本次研究。规划、预算、候选、合同、验收、收入和现金分别标记。<br><a href="market-research.md">Markdown全文</a> · <a href="deep-read-manifest.csv">深读清单</a> · <a href="public-sources.csv">公开来源</a> · <a href="source-refresh-audit.csv">刷新审计</a></footer></main></body></html>'''
(OUT/'market-research.html').write_text(page,encoding='utf-8')
checks={
    'channel_new_projects': math.ceil((30+30-20*(30*.05*.25-.15))/5),
    'maintenance_reference_wan': 30*.05,
    'single_renewal_contribution_wan':30*.05*.25-.15,
    'division_margin_percent':round((8104324.90-5880500.83)/8104324.90*100,2),
    'division_gross_profit_wan':round((8104324.90-5880500.83)/10000,4),
    'ledger_count':len(ledger)-1,
    'csv_table_exports':len(mapping)+1,
}
assert checks['channel_new_projects']==12
assert checks['division_margin_percent']==27.44
(OUT/'calculation-checks.json').write_text(json.dumps(checks,ensure_ascii=False,indent=2),encoding='utf-8')
print(json.dumps(checks,ensure_ascii=False))
