"""Take out the model-drawn figures so the spec renderer can draw them again.

Only figures whose target is an illustrate asset — media/*.svg with no owner.
An image an educator added to an article is somebody's work and is left alone.
"""
import re
import sys

from app.database import SessionLocal
from app.models.article import Article
from app.models.media import MediaAsset
from app.services import article_service, storage_service

DRY = "--apply" not in sys.argv
FIGURE = re.compile(r"\n*!\[[^\]]*\]\(/uploads/(media/[a-f0-9]+\.svg)\)")

db = SessionLocal()
owned = {row[0] for row in db.query(MediaAsset.path).filter(
    MediaAsset.path.like("media/%.svg"), MediaAsset.user_id.is_(None)).all()}

touched = removed = 0
gone: set[str] = set()
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):
        body = section.get("content") or ""
        if "![" not in body:
            continue

        def drop(match):
            global removed
            if match.group(1) in owned:
                removed += 1
                gone.add(match.group(1))
                return ""
            return match.group(0)

        fixed = FIGURE.sub(drop, body)
        if fixed != body:
            sections[index] = {**section, "content": fixed.rstrip() + "\n" if fixed.strip() else fixed}
            changed = True
    if changed:
        touched += 1
        if not DRY:
            article_service.snapshot(db, article, None, note="figures removed before redraw")
            article.sections = sections
            db.add(article)

if not DRY:
    db.commit()
    # The assets themselves, now that nothing points at them. Orphans from
    # earlier runs go with them — an SVG no article references is a file
    # nobody can reach.
    referenced: set[str] = set()
    for article in db.query(Article).filter(Article.deleted_at.is_(None)).all():
        for match in FIGURE.finditer(article_service.sections_text(article.sections)
                                     if hasattr(article_service, "sections_text")
                                     else " ".join(s.get("content") or "" for s in (article.sections or []))):
            referenced.add(match.group(1))
    dead = [path for path in owned if path not in referenced]
    for path in dead:
        try:
            storage_service.delete(path)
        except Exception as exc:
            print(f"  could not remove {path}: {exc}")
    db.query(MediaAsset).filter(MediaAsset.path.in_(dead)).delete(synchronize_session=False)
    db.commit()
    print(f"deleted {len(dead)} assets")

print(f"{'would strip' if DRY else 'stripped'} {removed} figures from {touched} articles")
db.close()
