"""Freeze the selected research sources and audit local WeDrive metadata."""
import csv
import hashlib
import json
import os
from datetime import datetime
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]
OUT = Path(__file__).resolve().parent


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


# Facts describe the retrieved artifact, not an inference of product-market fit.
SOURCES = [
('E01','work/weekly-reports/2026-W39/direction-template/scope-and-evidence.md','B','34条场景记录，政企19、学校7、医疗/社区/部队/体育各1、终端待核4；哈尔滨按社区归类','34记录不等于34客户；项目分类不是市场份额'),
('E02','work/weekly-reports/2026-W39/direction-template/output/sources/transcript.md','B','19:40联系150家原渠道缺目标资源；20:42受访一卡通伙伴偏结算；54:17公有云2.8万人/日活5000多人；56:37哈尔滨社区整体交付自报；58:22重庆营养增购线索待方案报价；60:19政企营养现场验证；60:48学校营养开发','会议自述非验收；重庆未证实签约付款；使用量非健康活跃；150家非全国代表样本'),
('E03','work/2026-09-01-smart-canteen-sku-portfolio/sku-evidence-matrix.csv','B','18个SKU目录含不同成熟度和储备方案','不是18个已验证生意；不采历史编码'),
('E04','work/2026-09-02-sku-product-financial-statement/sku-product-financial-statement.csv','B/D','按单SKU归因字段合计119.51万元；另有可重复线索金额','非财务审计收入；不与公司板块/项目总额相加'),
('E05','work/2026-09-01-smart-canteen-sku-portfolio/harbin-nutrition-health-smart-kitchen-sku.md','B','合同派生记录含称重、体测、机器人、余量和一年云服务组合','本轮未回验签章原件；不证明单独为健康付费'),
('E06','work/2026-09-14-nutrition-settlement-narrative/summary.md','B','用户认可供餐—就餐叙事；明确取餐重量与实际吃完量差别','不能把定额/计次消费推算为具体摄入'),
('E07','work_store/VWCG-1366-school-nutrition/implementation-evidence-algorithm-r4-20260921.md','B','9月21日学校营养100测试899断言、推荐及分析本地验证；仍缺多目标及特殊供餐资料','工程实现非上线验收；早期DoR不能覆盖最新实现'),
('E08','work/2026-09-17-school-nutrition-requirement-analysis/school-nutrition-production-closure-review.md','B','9月18日规则、净料率、接口及旧链门禁的历史评审','历史阻塞按9月21日实现更新，不能据此说没有开发'),
('E09','work_store/20260915-merchant-mobile-management-prototype/verification.md','B','移动商户原型与页面检查存在','模拟接口与本地状态非生产结果'),
('E10','work/2026-09-17-procurement-outcomes-user-research/smart-restaurant-interview-questionnaire-v10.docx','D','问卷已形成；未填客户、日期、原话和结论','研究工具不是完成访谈证据'),
('E11','modules/product/products/smart-canteen/product-solutions/2026-09-18-community-standard/source-evidence.md','B/D','社区测评、餐食、反馈和家庭关怀方案，样例为虚构','无运营方独立健康预算及同人群复测效果'),
('E12','modules/product/products/smart-canteen/product-solutions/2026-09-18-community-standard/v06/summary.md','B/D','20页社区交付；体重/BMI等演示与410场景图','不是新增客户成交或真实效果'),
('E13','modules/product/products/smart-canteen/product-solutions/2026-09-21-hospital-ai-nutrition-smart-canteen/source-evidence.md','B/D','医院专版形成；HIS/EMR、病区送餐、禁忌数据仍需逐项目确认','医院职工食堂不等于患者临床营养'),
('E14','modules/product/products/smart-canteen/product-solutions/2026-09-21-enterprise-public-institution-solution/README.md','B','57页企事业材料交付','页数、备注和版式不证明购买价值'),
('E15','modules/product/products/smart-canteen/product-solutions/2026-09-21-government-agency-solution-ppt/README.md','B','55页政府机关方案，正式三系统名称统一','名称变更不是功能成熟或合同新增'),
('E16','work/2026-09-02-smart-canteen-18-sku-quotes/source-index.csv','B','18SKU报价源指向8月20日产品清单','源价格须商务确认当前有效性'),
('E17','work/2026-07-17-digital-business-market-research-v2/market-sizing-model.csv','D','历史规模混合样本池与情景','历史样本非全国TAM，不能直接沿用'),
('E18','work/2026-08-26-yangguang-zhiyuan-company-deep-research/yangguang-zhiyuan-company-deep-research.md','B/C/D','阳光智园五平台和多地区采购证据汇总','技术壁垒、当前排名、实际盈利未证实'),
('E19','work/2026-08-10-office-nutrition-health-ai-ecosystem-research/office-nutrition-health-ai-market-entry-research.md','D','历史企业健康切口假设','企业健康P0未通过付费验证，降级为候选'),
('E20','work/2026-08-13-odoo-product-quote-delivery-transformation-plan/asset-compounding-v08/plan.md','B/D','49张报价/订单和案例资产；成本、回款、归因缺口','不是49张已成交或回款订单'),
('E21','work/weekly-reports/2026-W38/illustrated-weekly-report/month-continuity.md','B','9月中旬交付范围和完成率口径差异','早期百分比按后续报告更新；不折算收入'),
('E22','work/2026-09-12-k12-campus-meal-existing-solutions/summary.md','B/D','校级、区级、阳光消费材料已存在，含明确功能边界','方案覆盖不等于完整区域采购胜任'),
]
rows = []
for eid, rel, level, fact, gap in SOURCES:
    p = ROOT / rel
    if p.exists():
        b = p.read_bytes()
        rows.append([eid,rel,datetime.fromtimestamp(p.stat().st_mtime).isoformat(timespec='seconds'),len(b),hashlib.sha256(b).hexdigest(),level,fact,gap,'read'])
    else:
        rows.append([eid,rel,'',0,'',level,'文件未读到',gap,'missing'])
write_csv('deep-read-manifest.csv',['evidence_id','source_path','file_mtime_not_publication','bytes','sha256','level','fact','not_proven','read_status'],rows)

# Scan roots without copying raw files or changing the shared knowledge index.
base = Path('/Users/jack/Library/Containers/com.tencent.WeWorkMac/Data/WeDrive/康比特')
root_names = ['项目交付管理共享空间','数字技术中心知识库','交付实施部']
old = {}
with (ROOT/'work_company_knowledge/indexes/file-inventory.tsv').open(encoding='utf-8-sig') as f:
    for r in csv.DictReader(f,delimiter='\t'):
        old[r.get('abs_path','')] = r
audit=[]
for name in root_names:
    root=base/name
    count=docs=new=changed=0
    seen=set()
    errors=[]
    for folder, dirs, files in os.walk(root,onerror=lambda e: errors.append(type(e).__name__)):
        for name2 in files:
            p=Path(folder)/name2
            try:
                stat=p.stat()
            except OSError as e:
                errors.append(type(e).__name__)
                continue
            count+=1
            docs+=p.suffix.lower() in {'.pdf','.docx','.pptx','.xlsx','.md','.csv','.txt','.doc','.xls','.ppt'}
            seen.add(str(p))
            prev=old.get(str(p))
            if not prev:
                new+=1
            else:
                size=prev.get('size_bytes',prev.get('size',''))
                stamp=prev.get('modified_at',prev.get('mtime',''))
                changed+=str(stat.st_size)!=str(size) or (bool(stamp) and datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S')!=stamp)
    prior={p for p in old if p.startswith(str(root)+'/')}
    audit.append([str(root),count,docs,len(prior),new,changed,len(prior-seen),len(errors),'local_metadata_only; cloud_sync_not_confirmed'])
write_csv('source-refresh-audit.csv',['root','current_files','documents','previous_index_files','new_paths','metadata_changed','previous_paths_not_seen','scan_errors','boundary'],audit)
print(json.dumps({'manifest_count':len(rows),'source_missing':[r[0] for r in rows if r[-1]=='missing'],'drive_audit':audit},ensure_ascii=False))
