# aider-watch-client buffer | 2026-04-20 @ Asia/Taipei
"""JSONL buffer 當 awoooi API 不可達時緩衝 events；launchd 定期呼 flush()。"""
from __future__ import annotations
import json
from pathlib import Path
from typing import Callable

# Late-import to allow tests to monkey-patch
import aider_watch_client.config as _config
BUFFER_DIR: Path = _config.BUFFER_DIR

from ulid import ULID


def _ensure():
    _config.ensure_dirs()


def _get_buffer_dir() -> Path:
    # test 可 monkey-patch 這個 module-level BUFFER_DIR
    import aider_watch_client.buffer as _self
    return _self.BUFFER_DIR


def write(events: list[dict]) -> Path:
    """批次寫一個 pending file。"""
    bd = _get_buffer_dir()
    bd.mkdir(parents=True, exist_ok=True)
    fp = bd / f"pending_{ULID()}.jsonl"
    with fp.open("w") as f:
        for ev in events:
            f.write(json.dumps(ev, ensure_ascii=False, default=str) + "\n")
    return fp


def flush(post_fn: Callable[[list[dict]], bool]) -> int:
    """把 buffer 下所有 pending file 重送；成功刪檔，失敗保留。回傳成功筆數。"""
    bd = _get_buffer_dir()
    bd.mkdir(parents=True, exist_ok=True)
    total = 0
    for fp in list(bd.glob("pending_*.jsonl")):
        lines = [l for l in fp.read_text().splitlines() if l.strip()]
        if not lines:
            fp.unlink(); continue
        batch = [json.loads(l) for l in lines]
        ok_all = True
        # API max 50 per request
        for i in range(0, len(batch), 50):
            chunk = batch[i:i+50]
            if not post_fn(chunk):
                ok_all = False
                break
            total += len(chunk)
        if ok_all:
            fp.unlink()
    return total
