import json
import re
import sys
from pathlib import Path
from openpyxl import Workbook
from openpyxl.cell.cell import ILLEGAL_CHARACTERS_RE

output = Path("archive-tweets.xlsx")
if output.exists():
    raise FileExistsError("Move the previous workbook before running again")
if len(sys.argv) < 2:
    raise SystemExit("Pass one or more post-data .js files")

wb = Workbook()
ws = wb.active
ws.title = "Posts"
ws.append(["tweet_id", "created_at_source", "text"])
seen = set()
duplicates = 0
for filename in sys.argv[1:]:
    text = Path(filename).read_text(encoding="utf-8-sig")
    match = re.fullmatch(
        r"\s*window\.YTD\.tweets\.part\d+\s*=\s*(\[.*\])\s*;?\s*",
        text, flags=re.DOTALL
    )
    if not match:
        raise ValueError(f"Unexpected wrapper: {filename}")
    records = json.loads(match.group(1))
    if not isinstance(records, list):
        raise ValueError("Expected an array")
    for record in records:
        tweet = record["tweet"]
        post_id = tweet["id_str"]
        if not isinstance(post_id, str) or not re.fullmatch(r"[0-9]+", post_id):
            raise ValueError("Expected a string id_str; inspect this archive")
        if post_id in seen:
            duplicates += 1
            continue
        seen.add(post_id)
        values = [post_id, tweet.get("created_at", ""), tweet.get("full_text", "")]
        if ws.max_row >= 1048576:
            raise ValueError("Too many records for one Excel worksheet")
        row = ws.max_row + 1
        for col, value in enumerate(values, start=1):
            if not isinstance(value, str):
                raise ValueError("Expected text fields; inspect this record")
            if len(value) > 32767 or "\r" in value or ILLEGAL_CHARACTERS_RE.search(value):
                raise ValueError("A value cannot be preserved exactly in this worksheet")
            cell = ws.cell(row=row, column=col, value=value)
            cell.data_type = "s"  # Store even '=...' as literal text, not a formula.
            cell.number_format = "@"
ws.freeze_panes = "A2"
ws.auto_filter.ref = ws.dimensions
wb.save(output)
print(f"Saved {len(seen)} distinct posts to {output}; skipped {duplicates} duplicate IDs")
