"""Unwrap cross-references an article should never have made to itself.

The rule arrived after the links did: Adolescent Depression was linking the
word "depression", which offers the reader a door to the room they are
standing in. The words stay; only the marker around them goes.
"""
import re
import sys

from app.database import SessionLocal
from app.models.article import Article
from app.models.question_category import QuestionCategory
from app.services import article_service, autolink

DRY = "--apply" not in sys.argv
MARKER = re.compile(r"\[\[([^\]|]+)\|([a-z0-9-]+)\]\]")

db = SessionLocal()
titles = [(a.title, a.slug) for a in db.query(Article).filter(
    Article.deleted_at.is_(None), Article.status == "published").all()]
categories = {c.id: c.name for c in db.query(QuestionCategory).all()}

removed = 0
touched = []
for article in db.query(Article).filter(Article.deleted_at.is_(None)).all():
    drop = autolink.self_referential(
        article.title, categories.get(article.category_id), titles)
    drop.add(article.slug)
    sections = list(article.sections or [])
    changed = False
    for index, section in enumerate(sections):
        body = section.get("content") or ""

        def unwrap(match):
            global removed
            if match.group(2) in drop:
                removed += 1
                return match.group(1)
            return match.group(0)

        fixed = MARKER.sub(unwrap, body)
        if fixed != body:
            sections[index] = {**section, "content": fixed}
            changed = True
    if changed:
        touched.append((article.id, article.title))
        if not DRY:
            article_service.snapshot(db, article, None,
                                     note="self-referential links removed")
            article.sections = sections
            db.add(article)
if not DRY:
    db.commit()
print(f"{'would unwrap' if DRY else 'unwrapped'} {removed} self-referential links "
      f"across {len(touched)} articles")
for row in touched[:10]:
    print("  ", row[0], row[1][:40])
db.close()
