"""Release the two held pairs, move one figure, and apply the content-matched links.

Everything here is the editorial session's decision; what this adds is that it
is done through the services rather than by hand, and that it says what it did.
"""
import csv
import sys
from datetime import datetime

from app.database import SessionLocal
from app.models.article import Article, ArticleTopicClaim, QuestionArticleLink
from app.models.question import Question
from app.services import article_figures, topic_claims

APPLY = "--apply" in sys.argv
db = SessionLocal()


def repoint(retire_id, default_keeper, named=None, claim_for=None):
    """Move a retired article's question links, then trash it."""
    named = named or {}
    goner = db.get(Article, retire_id)
    if not goner or goner.deleted_at is not None:
        print(f"   {retire_id} already trashed")
        return
    links = db.query(QuestionArticleLink).filter_by(article_id=retire_id).all()
    plan = {}
    for row in links:
        target = named.get(row.question_id, default_keeper)
        plan.setdefault(target, []).append(row)
    for target, rows in sorted(plan.items()):
        title = (db.get(Article, target).title or "")[:34]
        print(f"   {len(rows):2} -> {target} {title}")
        if not APPLY:
            continue
        already = {r[0] for r in db.query(QuestionArticleLink.question_id)
                   .filter_by(article_id=target).all()}
        for row in rows:
            if row.question_id in already:
                db.delete(row)
            else:
                row.article_id = target
                row.section_id = None
    if APPLY:
        goner.deleted_at = datetime.utcnow()
        db.query(ArticleTopicClaim).filter_by(article_id=retire_id).delete()
        db.commit()
        if claim_for:
            article_id, category_id = claim_for
            claim = db.query(ArticleTopicClaim).filter_by(
                article_id=article_id, category_id=category_id, section_id=None).first()
            if claim is None:
                claim = ArticleTopicClaim(article_id=article_id, category_id=category_id,
                                          section_id=None, include_subtopics=True,
                                          fill_only=True, user_id=None)
                db.add(claim)
                db.commit()
                db.refresh(claim)
            print(f"   claim {article_id} over {category_id}: linked {topic_claims.apply(db, claim)}")


print("Gastroenteritis 273 -> 168")
repoint(273, 168, claim_for=(168, 14932))

print("Viral Infections 447 -> 232 and four others")
repoint(447, 232, named={851: 174, 1428: 338, 2847: 297, 2504: 455},
        claim_for=(232, 15959))

print("Cryptorchidism figure 322 -> 356 section 6e521453")
figures = db.query(QuestionArticleLink).first()  # noqa — placeholder, see below
from app.models.media import ArticleMedia  # noqa: E402
held = db.query(ArticleMedia).filter_by(article_id=322).all()
for row in held:
    print(f"   asset {row.media_id} on section {row.section_id}")
if APPLY and held:
    keeper = db.get(Article, 356)
    try:
        out = article_figures.place_existing(db, keeper, "6e521453", held[0].media_id)
        print("   placed:", out.get("asset_id") or out)
    except Exception as exc:
        print("   could not place:", exc)

print("content-matched links")
written = skipped = missing = 0
with open("/app/apply-links.csv") as handle:
    for row in csv.DictReader(handle):
        qid, aid = int(row["question_id"]), int(row["article_id"])
        if not db.get(Question, qid) or not db.get(Article, aid):
            missing += 1
            continue
        if db.query(QuestionArticleLink.id).filter_by(question_id=qid).first():
            skipped += 1
            continue
        written += 1
        if APPLY:
            db.add(QuestionArticleLink(question_id=qid, article_id=aid,
                                       section_id=None, user_id=None))
if APPLY:
    db.commit()
print(f"   would write {written}, already linked {skipped}, unknown id {missing}")
print("applied:", APPLY)
db.close()
