"""Unwrap link markers that were written into table rows.

`[[Label|slug]]` in a cell splits it at the pipe, so the row gains a column
and the marker reaches the reader in halves. The link goes; the words it was
wrapped around stay, because they are the author's text.
"""
import re
import sys

from app.database import SessionLocal
from app.models.article import Article
from app.services import article_service

DRY = "--apply" not in sys.argv
#: Both marker forms, because both carry a pipe and both break a cell.
#: `[[Label|slug]]` is what autolink writes; `[[288|Label]]` is what an
#: educator writes by hand, with the id first. Either way the words a reader
#: should be left with are the half that is not the target.
BY_SLUG = re.compile(r"\[\[([^\]|]+)\|[a-z0-9-]+\]\]")
BY_ID = re.compile(r"\[\[\d+(?:#[A-Za-z0-9_-]+)?\|([^\]]+)\]\]")


def unwrap(line: str) -> str:
    return BY_SLUG.sub(lambda m: m.group(1), BY_ID.sub(lambda m: m.group(1), line))

db = SessionLocal()
rows = fixed = 0
touched = []
for article in db.query(Article).filter(Article.deleted_at.is_(None)).all():
    sections = list(article.sections or [])
    changed = False
    for index, section in enumerate(sections):
        lines = (section.get("content") or "").split("\n")
        out = []
        for line in lines:
            if line.strip().startswith("|") and "[[" in line:
                rows += 1
                repaired = unwrap(line)
                fixed += line.count("[[")
                out.append(repaired)
                changed = True
            else:
                out.append(line)
        if changed:
            sections[index] = {**section, "content": "\n".join(out)}
    if changed:
        touched.append((article.id, article.title))
        if not DRY:
            article_service.snapshot(db, article, None, note="links removed from table rows")
            article.sections = sections
            db.add(article)
if not DRY:
    db.commit()
print(f"{'would repair' if DRY else 'repaired'} {fixed} markers in {rows} rows "
      f"across {len(touched)} articles")
for row in touched[:12]:
    print("  ", row)
db.close()
