"""Write plain-text comment dumps for reading and coding, one file per batch.

usage: python3 comment_dumps.py <research_dir> [--since YYYYMMDD] [--until YYYYMMDD] [--parts N] [--name core]

Each line carries the full comment id (cid=...) so codes join back exactly; replies are indented under their
thread and the owner's replies are marked OWNER. Batches split by video, balanced by comment count.
The dumps hold commenters' names: keep them (and raw/) on your machine, never publish them.
Code every line (no sampling) into analysis/coded-<name>[-partK].jsonl:
  {"cid": "...", "cat": "praise|discussion|question|owner|criticism|personal_story|request|giveaway_entry|misunderstanding|off_topic|spam_promo|other",
   "tags": ["..."], "neg": false, "note": "짧은 근거"}"""
import argparse, json, os

def main():
    ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
    ap.add_argument('research_dir'); ap.add_argument('--since', default='00000000'); ap.add_argument('--until', default='99999999')
    ap.add_argument('--parts', type=int, default=1); ap.add_argument('--name', default='core')
    a = ap.parse_args(); r = a.research_dir
    V = {v['id']: v for v in json.load(open(os.path.join(r, 'analysis', 'videos.json')))}
    cs = [json.loads(l) for l in open(os.path.join(r, 'raw', 'comments-all.jsonl'))]
    vids = [v for v in sorted(V.values(), key=lambda v: v['upload_date'], reverse=True) if a.since <= v['upload_date'] <= a.until]
    by = {}
    for c in cs: by.setdefault(c['video'], []).append(c)
    total = sum(len(by.get(v['id'], [])) for v in vids)
    parts = [[] for _ in range(a.parts)]; acc = 0
    for v in vids:
        parts[min(a.parts - 1, int(acc / max(total, 1) * a.parts))].append(v); acc += len(by.get(v['id'], []))
    for k, p in enumerate(parts, 1):
        name = a.name if a.parts == 1 else f'{a.name}-part{k}'
        path = os.path.join(r, 'analysis', f'comments-{name}.txt'); n = 0
        with open(path, 'w') as f:
            for v in p:
                sel = by.get(v['id'])
                if not sel: continue
                f.write(f"\n### {v['id']} [{v['fmt']}] {v['upload_date']} {v['title']}\n")
                roots = sorted([c for c in sel if c.get('parent') in (None, 'root')], key=lambda c: c['ts'] or 0)
                for rt in roots:
                    for c in [rt] + sorted([c for c in sel if c.get('parent') == rt['cid']], key=lambda c: c['ts'] or 0):
                        ind = '  ↳ ' if c is not rt else '- '
                        text = (c['text'] or '').replace('\n', ' / ')
                        f.write(f"{ind}cid={c['cid']} {'OWNER ' if c['is_owner'] else ''}{c['author']} (♥{c['likes']}): {text}\n"); n += 1
                orphans = [c for c in sel if c.get('parent') not in (None, 'root') and c['parent'] not in {x['cid'] for x in roots}]
                for c in orphans:
                    f.write(f"  ↳? cid={c['cid']} {'OWNER ' if c['is_owner'] else ''}{c['author']}: {(c['text'] or '').replace(chr(10), ' / ')}\n"); n += 1
        print(path, 'videos', len(p), 'comments', n)

if __name__ == '__main__':
    main()
