"""Preenche campos de extração a partir dos metadados do artigo importado."""

from __future__ import annotations

from reviews.models import Article, DataExtraction, DataExtractionField
from rsl.services.extraction_values import normalize_value

# Campos do formulário preenchíveis automaticamente
METADATA_GETTERS: dict[str, str] = {
    "Title": "title",
    "Authors": "authors",
    "Year": "year",
    "Source": "source_name",
}


def metadata_value_for_field(article: Article, field_description: str) -> str:
    """Valor sugerido a partir do cadastro do artigo (importação/seleção)."""
    key = METADATA_GETTERS.get(field_description)
    if not key:
        return ""
    if key == "title":
        return (article.title or "").strip()
    if key == "authors":
        return (article.authors or "").strip()
    if key == "year":
        return (article.year or "").strip()
    if key == "source_name":
        return (article.source.name if article.source else "").strip()
    return ""


def extraction_display_value(article: Article, field: DataExtractionField) -> str:
    """Valor salvo na extração ou, se vazio, metadado do artigo (nunca o abstract em Descrição)."""
    extraction = next(
        (e for e in article.extractions.all() if e.field_id == field.id), None
    )
    if extraction and (extraction.value or "").strip():
        return extraction.value.strip()
    if field.field_type == "S" or field.description == "Descrição":
        return ""
    return metadata_value_for_field(article, field.description)


def _set_extraction_value(
    article: Article,
    field: DataExtractionField,
    raw: str,
    user_id: int,
    only_if_empty: bool,
) -> bool:
    raw = (raw or "").strip()
    if not raw:
        return False

    extraction = DataExtraction.objects.filter(
        article_id=article.id, field_id=field.id
    ).first()
    if extraction and only_if_empty and (extraction.value or "").strip():
        return False
    if field.field_type == "S":
        return False

    value, err = normalize_value(field.field_type, raw)
    if err:
        return False

    if not extraction:
        extraction = DataExtraction(
            article_id=article.id,
            field_id=field.id,
            user_id=user_id,
        )
        extraction.save()

    extraction.value = value or ""
    extraction.user_id = user_id
    return True


def prefill_article_metadata(
    article: Article,
    user_id: int,
    *,
    only_if_empty: bool = True,
    pending_only: bool = False,
) -> int:
    """Preenche Title, Authors, Year, Source. Retorna quantidade de campos atualizados."""
    if pending_only and article.finished_data_extraction:
        return 0

    review = article.review
    fields_by_name = {f.description: f for f in review.extraction_fields.all()}
    updated = 0

    for desc in METADATA_GETTERS:
        field = fields_by_name.get(desc)
        if not field:
            continue
        raw = metadata_value_for_field(article, desc)
        if _set_extraction_value(article, field, raw, user_id, only_if_empty):
            updated += 1

    return updated


def prefill_review_metadata(
    review,
    user_id: int,
    *,
    only_if_empty: bool = True,
    pending_only: bool = True,
) -> dict:
    articles = Article.objects.filter(review_id=review.id, status="A").all()
    articles_updated = 0
    fields_updated = 0

    for article in articles:
        n = prefill_article_metadata(
            article,
            user_id,
            only_if_empty=only_if_empty,
            pending_only=pending_only,
        )
        if n:
            articles_updated += 1
            fields_updated += n

    return {
        "articles": len(articles),
        "articles_updated": articles_updated,
        "fields_updated": fields_updated,
    }
