"""系统评价 / Meta 分析项目 CRUD API"""

import uuid

from fastapi import APIRouter, Depends, HTTPException, Query
from fastapi.responses import PlainTextResponse
from pydantic import BaseModel
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import selectinload

from app.core.permissions import get_current_user
from app.core.plans import require_feature
from app.core.tenant_context import tenant_ctx
from app.db import get_db
from app.services.cos_client import cached_get_full_text
from app.models.literature import GlobalLiterature
from app.schemas.literature import cap_pub_date
from app.models.review import ReviewLiterature, SystematicReview

router = APIRouter()


def uid(u: dict) -> uuid.UUID:
    return uuid.UUID(u["sub"])


# ─── Schemas ───

class ReviewCreate(BaseModel):
    title: str
    objective: str | None = None
    protocol: str | None = None
    inclusion_criteria: list[str] | None = None
    exclusion_criteria: list[str] | None = None
    databases_searched: list[str] | None = None
    search_strategy: dict | None = None


class ReviewUpdate(BaseModel):
    title: str | None = None
    objective: str | None = None
    protocol: str | None = None
    prisma_stage: str | None = None
    status: str | None = None
    inclusion_criteria: list[str] | None = None
    exclusion_criteria: list[str] | None = None
    databases_searched: list[str] | None = None
    search_strategy: dict | None = None
    notes: str | None = None


class LiteratureAdd(BaseModel):
    literature_id: str
    stage: str = "screening"
    notes: str | None = None


class LiteratureUpdate(BaseModel):
    stage: str | None = None
    exclusion_reason: str | None = None
    notes: str | None = None
    quality_score: str | None = None


class PicoUpdate(BaseModel):
    population: str | None = None
    intervention: str | None = None
    comparator: str | None = None
    outcome: str | None = None
    sample_size: int | None = None
    effect_size: dict | None = None


# ─── Helpers ───

async def _get_review_owned(db: AsyncSession, review_id: str, user: dict) -> SystematicReview:
    """获取评价并校验所有权（防止跨用户/跨租户越权）"""
    try:
        rid = uuid.UUID(review_id)
    except ValueError:
        raise HTTPException(400, "Invalid review ID")
    review = await db.get(SystematicReview, rid)
    if not review:
        raise HTTPException(404, "Review not found")
    raw_tid = tenant_ctx.get()
    if raw_tid:
        if review.tenant_id != uuid.UUID(raw_tid):
            raise HTTPException(404, "Review not found")
    elif review.user_id != uuid.UUID(user["sub"]):
        raise HTTPException(404, "Review not found")
    return review


def _review_to_dict(r: SystematicReview) -> dict:
    return {
        "id": str(r.id),
        "user_id": str(r.user_id),
        "tenant_id": str(r.tenant_id),
        "title": r.title,
        "objective": r.objective,
        "protocol": r.protocol,
        "inclusion_criteria": r.inclusion_criteria or [],
        "exclusion_criteria": r.exclusion_criteria or [],
        "databases_searched": r.databases_searched or [],
        "search_strategy": r.search_strategy or {},
        "prisma_stage": r.prisma_stage,
        "status": r.status,
        "notes": r.notes,
        "created_at": r.created_at.isoformat() if r.created_at else None,
        "updated_at": r.updated_at.isoformat() if r.updated_at else None,
    }


# ─── CRUD ───

@router.get("", response_model=dict, summary="系统评价列表")
async def list_reviews(
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    page: int = Query(1, ge=1),
    page_size: int = Query(20, ge=1, le=100),
    status: str = Query(""),
):
    """当前用户的系统评价列表"""
    raw_tid = tenant_ctx.get()
    if not raw_tid:
        return {"items": [], "total": 0}

    q = select(SystematicReview).where(SystematicReview.tenant_id == uuid.UUID(raw_tid))
    if status:
        q = q.where(SystematicReview.status == status)

    total = (await db.execute(select(func.count()).select_from(q.subquery()))).scalar() or 0
    result = await db.execute(
        q.order_by(SystematicReview.updated_at.desc())
        .offset((page - 1) * page_size).limit(page_size)
    )
    reviews = result.scalars().all()
    return {"items": [_review_to_dict(r) for r in reviews], "total": total}


@router.post("", response_model=dict, summary="创建系统评价")
async def create_review(
    data: ReviewCreate,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    # 检查活跃项目数配额
    from app.core.quota import check_active_project_quota
    pq = await check_active_project_quota(db)
    if pq["exceeded"] and pq["limit"] >= 0:
        raise HTTPException(
            status_code=403,
            detail=f"活跃项目数已达上限 ({pq['active']}/{pq['limit']})。请归档已完成项目后再创建新项目。",
        )
    raw_tid = tenant_ctx.get()
    if not raw_tid:
        # 查找用户的个人 tenant
        from app.models.user import UserTenant
        ut = (await db.execute(
            select(UserTenant).where(UserTenant.user_id == uid(user))
        )).scalar()
        if ut:
            raw_tid = str(ut.tenant_id)
    if not raw_tid:
        return {"status": "error", "detail": "请重新登录后重试"}

    review = SystematicReview(
        id=uuid.uuid4(),
        user_id=uid(user),
        tenant_id=uuid.UUID(raw_tid),
        title=data.title,
        objective=data.objective,
        protocol=data.protocol,
        inclusion_criteria=data.inclusion_criteria or [],
        exclusion_criteria=data.exclusion_criteria or [],
        databases_searched=data.databases_searched or [],
        search_strategy=data.search_strategy or {},
    )
    db.add(review)
    await db.commit()
    return _review_to_dict(review)


@router.get("/{review_id}", response_model=dict, summary="系统评价详情")
async def get_review(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    review = await _get_review_owned(db, review_id, user)
    return _review_to_dict(review)


@router.put("/{review_id}", response_model=dict, summary="更新系统评价")
async def update_review(
    review_id: str,
    data: ReviewUpdate,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    review = await _get_review_owned(db, review_id, user)
    update_data = data.model_dump(exclude_none=True)
    for k, v in update_data.items():
        setattr(review, k, v)
    await db.commit()
    return _review_to_dict(review)


@router.delete("/{review_id}", response_model=dict, summary="删除系统评价")
async def delete_review(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    review = await _get_review_owned(db, review_id, user)
    await db.delete(review)
    await db.commit()
    return {"status": "deleted"}


# ─── 文献管理 ───

@router.get("/{review_id}/literature", response_model=dict, summary="评价文献列表")
async def list_review_literature(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    stage: str = Query(""),
):
    """查看系统评价中的文献列表，含 PRISMA 阶段"""
    review = await _get_review_owned(db, review_id, user)
    rid = review.id

    q = (
        select(ReviewLiterature, GlobalLiterature)
        .join(GlobalLiterature, ReviewLiterature.literature_id == GlobalLiterature.id)
        .where(ReviewLiterature.review_id == rid)
    )
    if stage:
        q = q.where(ReviewLiterature.stage == stage)

    result = await db.execute(q.order_by(ReviewLiterature.created_at.desc()))
    items = []
    for rl, lit in result:
        authors = lit.authors or []
        items.append({
            "id": str(rl.id),
            "review_id": str(rl.review_id),
            "literature_id": str(rl.literature_id),
            "pmid": lit.pmid,
            "title": lit.title,
            "first_author": authors[0].get("family", "") if authors else "",
            "journal": lit.journal,
            "pub_date": cap_pub_date(lit.pub_date),
            "doi": lit.doi,
            "stage": rl.stage,
            "exclusion_reason": rl.exclusion_reason,
            "notes": rl.notes,
            "quality_score": rl.quality_score,
            "retracted": lit.retracted,
            "study_design": lit.study_design,
            "pico": rl.pico if rl.pico is not None else lit.pico,
            "created_at": rl.created_at.isoformat() if rl.created_at else None,
        })
    return {"items": items, "total": len(items)}


@router.post("/{review_id}/literature", response_model=dict, summary="添加文献")
async def add_review_literature(
    review_id: str,
    data: LiteratureAdd,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """向系统评价中添加文献"""
    review = await _get_review_owned(db, review_id, user)
    rid = review.id

    try:
        lit_id = uuid.UUID(data.literature_id)
    except ValueError:
        raise HTTPException(400, "Invalid literature ID")

    # 检查文献是否存在
    lit = await db.get(GlobalLiterature, lit_id)
    if not lit:
        raise HTTPException(404, "Literature not found")

    # 撤稿警告
    retraction_warning = None
    if lit.retracted:
        retraction_warning = "本文献已被撤稿，请谨慎使用"

    # 检查是否已添加
    existing = await db.execute(
        select(ReviewLiterature).where(
            ReviewLiterature.review_id == rid,
            ReviewLiterature.literature_id == lit_id,
        )
    )
    if existing.scalar():
        raise HTTPException(409, "Literature already in review")

    rl = ReviewLiterature(
        id=uuid.uuid4(),
        review_id=rid,
        literature_id=lit_id,
        stage=data.stage,
        notes=data.notes,
    )
    db.add(rl)
    await db.commit()

    # 如果添加时即为纳入阶段，校验纳入配额
    if data.stage == "included":
        from app.core.quota import check_included_quota
        iq = await check_included_quota(db)
        if iq["exceeded"] and iq["limit"] >= 0:
            raise HTTPException(
                status_code=403,
                detail=f"月纳入配额已用完 ({iq['used']}/{iq['limit']})。请升级方案或关闭已完成项目释放额度。",
            )

    resp = {"status": "added", "id": str(rl.id)}
    if retraction_warning:
        resp["warning"] = retraction_warning
    return resp


@router.put("/{review_id}/literature/{lit_rel_id}", response_model=dict, summary="更新文献状态")
async def update_review_literature(
    review_id: str,
    lit_rel_id: str,
    data: LiteratureUpdate,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """更新文献在系统评价中的阶段/排除原因/质量评分"""
    review = await _get_review_owned(db, review_id, user)
    rid = review.id
    try:
        lrid = uuid.UUID(lit_rel_id)
    except ValueError:
        raise HTTPException(400, "Invalid ID")

    rl = await db.get(ReviewLiterature, lrid)
    if not rl or rl.review_id != rid:
        raise HTTPException(404, "Review literature not found")

    update_data = data.model_dump(exclude_none=True)
    for k, v in update_data.items():
        setattr(rl, k, v)

    # 如果更新为纳入阶段，校验纳入配额
    if data.stage == "included" and rl.stage != "included":
        from app.core.quota import check_included_quota
        iq = await check_included_quota(db)
        if iq["exceeded"] and iq["limit"] >= 0:
            raise HTTPException(
                status_code=403,
                detail=f"月纳入配额已用完 ({iq['used']}/{iq['limit']})。请升级方案或关闭已完成项目释放额度。",
            )

    await db.commit()
    return {"status": "updated"}


@router.delete("/{review_id}/literature/{lit_rel_id}", response_model=dict, summary="移除文献")
async def remove_review_literature(
    review_id: str,
    lit_rel_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """从系统评价中移除文献"""
    review = await _get_review_owned(db, review_id, user)
    rid = review.id
    try:
        lrid = uuid.UUID(lit_rel_id)
    except ValueError:
        raise HTTPException(400, "Invalid ID")

    rl = await db.get(ReviewLiterature, lrid)
    if not rl or rl.review_id != rid:
        raise HTTPException(404, "Review literature not found")

    await db.delete(rl)
    await db.commit()
    return {"status": "removed"}


# ─── PICO 管理 ───

@router.put("/{review_id}/literature/{lit_rel_id}/pico", response_model=dict, summary="编辑 PICO")
async def update_literature_pico(
    review_id: str,
    lit_rel_id: str,
    data: PicoUpdate,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """手动编辑文献的 PICO 数据"""
    review = await _get_review_owned(db, review_id, user)
    rid = review.id
    try:
        lrid = uuid.UUID(lit_rel_id)
    except ValueError:
        raise HTTPException(400, "Invalid ID")

    rl = await db.get(ReviewLiterature, lrid)
    if not rl or rl.review_id != rid:
        raise HTTPException(404, "Review literature not found")

    lit = await db.get(GlobalLiterature, rl.literature_id)
    if not lit:
        raise HTTPException(404, "Literature not found")

    current = rl.pico or lit.pico or {}
    update = data.model_dump(exclude_none=True)
    current = {**current, **update}
    rl.pico = current
    await db.commit()
    return {"status": "updated", "pico": current}


@router.post("/{review_id}/literature/{lit_rel_id}/extract-pico", response_model=dict, summary="AI 提取 PICO")
async def extract_literature_pico(
    review_id: str,
    lit_rel_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """调用 AI 从摘要+全文抽取 PICO 要素，存入评价级 PICO"""
    from app.services.ai_summary import extract_pico

    review = await _get_review_owned(db, review_id, user)
    rid = review.id
    try:
        lrid = uuid.UUID(lit_rel_id)
    except ValueError:
        raise HTTPException(400, "Invalid ID")

    rl = await db.get(ReviewLiterature, lrid)
    if not rl or rl.review_id != rid:
        raise HTTPException(404, "Review literature not found")

    lit = await db.get(GlobalLiterature, rl.literature_id)
    if not lit:
        raise HTTPException(404, "Literature not found")

    pico = await extract_pico(
        title=lit.title or "",
        abstract=lit.abstract,
        full_text_sections=await cached_get_full_text(lit.pmid, lit),
    )
    if not pico:
        raise HTTPException(400, "AI 未能提取 PICO，请确认文献有摘要或全文")

    rl.pico = pico
    await db.commit()
    return {"status": "extracted", "pico": pico}


@router.get("/{review_id}/literature/{lit_rel_id}/extracted-data", response_model=dict, summary="提取数据详情")
async def get_extracted_data(
    review_id: str,
    lit_rel_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """查看文献的预提取数据（Table 1 基线特征 + Outcome 表 + 效应量）"""
    review = await _get_review_owned(db, review_id, user)
    rid = review.id
    try:
        lrid = uuid.UUID(lit_rel_id)
    except ValueError:
        raise HTTPException(400, "Invalid ID")

    rl = await db.get(ReviewLiterature, lrid)
    if not rl or rl.review_id != rid:
        raise HTTPException(404, "Review literature not found")

    lit = await db.get(GlobalLiterature, rl.literature_id)
    if not lit:
        raise HTTPException(404, "Literature not found")

    result: dict = {
        "pmid": lit.pmid,
        "title": lit.title,
        "pico": rl.pico if rl.pico is not None else lit.pico,
    }

    # 基线特征数据
    pre_data = lit.pre_extracted_data or {}
    if pre_data:
        result["baseline"] = {
            "table1_caption": pre_data.get("table1_caption"),
            "arms": pre_data.get("arms", []),
            "extracted_fields": pre_data.get("extracted_fields", {}),
            "parsed_values": pre_data.get("parsed_values", {}),
            "header_sample_sizes": pre_data.get("header_sample_sizes"),
        }
        result["outcome_tables"] = pre_data.get("outcome_tables", [])

    # 全文段落（用于查阅）
    full_text = await cached_get_full_text(lit.pmid, lit) or {}
    if full_text:
        sections = full_text.get("sections") or []
        tables = full_text.get("tables") or []
        result["sections"] = [
            {"heading": s.get("heading"), "text": s.get("text", "")[:500]}
            for s in sections[:10]
        ]
        # 带有 outcome 解析结果的表格
        parsed_tables = []
        for tbl in tables:
            if tbl.get("is_outcome_table"):
                entry = {
                    "caption": tbl.get("caption"),
                    "headers": tbl.get("headers", []),
                    "rows": tbl.get("rows", [])[:20],
                }
                parsed_tables.append(entry)
        if parsed_tables:
            result["tables"] = parsed_tables

        # 效应量数值解析
        from app.services.jats_parser import parse_all_outcome_effects
        effects = parse_all_outcome_effects(full_text)
        if effects:
            result["parsed_effects"] = effects

    result["_note"] = "预提取数据仅供参考，请人工核对原始文献"
    return result


class AdoptEffectInput(BaseModel):
    endpoint: str | None = None
    effect_type: str | None = None
    value: float | None = None
    ci_lower: float | None = None
    ci_upper: float | None = None
    p_value: float | None = None


@router.post("/{review_id}/literature/{lit_rel_id}/adopt-effect", response_model=dict, summary="采用效应量")
async def adopt_parsed_effect(
    review_id: str,
    lit_rel_id: str,
    data: AdoptEffectInput,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """将解析出的效应量写入文献 PICO（从 Outcome 表提取结果中选用）"""
    review = await _get_review_owned(db, review_id, user)
    rid = review.id
    try:
        lrid = uuid.UUID(lit_rel_id)
    except ValueError:
        raise HTTPException(400, "Invalid ID")

    rl = await db.get(ReviewLiterature, lrid)
    if not rl or rl.review_id != rid:
        raise HTTPException(404, "Review literature not found")

    if not data.effect_type and not data.value and not data.p_value:
        raise HTTPException(400, "至少需要提供一项效应量数据")

    current = rl.pico or {}
    es = dict(current.get("effect_size") or {})
    if data.effect_type:
        es[data.effect_type.lower()] = data.value
    if data.ci_lower is not None:
        es["ci_lower"] = data.ci_lower
    if data.ci_upper is not None:
        es["ci_upper"] = data.ci_upper
    if data.p_value is not None:
        es["p_value"] = data.p_value
    es["_source"] = "outcome_table"
    if data.endpoint:
        es["_endpoint"] = data.endpoint
    current["effect_size"] = es
    rl.pico = current
    await db.commit()
    return {"status": "adopted", "pico": current}


# ─── 导出 / PRISMA / 方法学小结 ───

@router.get("/{review_id}/export/csv", response_class=PlainTextResponse, summary="导出 CSV")
async def export_review_csv(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    _plan_ok: bool = Depends(require_feature("review_export")),
):
    """导出评价文献为富 CSV（含研究设计、PICO、质量评分、撤稿状态）"""
    from app.services.review_export import export_review_csv as _export_csv

    review = await _get_review_owned(db, review_id, user)
    rid = review.id

    result = await db.execute(
        select(ReviewLiterature, GlobalLiterature)
        .join(GlobalLiterature, ReviewLiterature.literature_id == GlobalLiterature.id)
        .where(ReviewLiterature.review_id == rid)
    )
    lits = []
    for rl, lit in result:
        lits.append({
            "pmid": lit.pmid,
            "title": lit.title,
            "authors": lit.authors,
            "journal": lit.journal,
            "pub_year": lit.pub_year,
            "doi": lit.doi,
            "study_design": lit.study_design,
            "pico": rl.pico if rl.pico is not None else lit.pico,
            "retracted": lit.retracted,
            "trial_reg": lit.trial_reg,
            "stage": rl.stage,
            "exclusion_reason": rl.exclusion_reason,
            "notes": rl.notes,
            "quality_score": rl.quality_score,
        })

    csv_content = _export_csv({}, lits)
    return PlainTextResponse(
        content=csv_content,
        headers={"Content-Disposition": f'attachment; filename="review_{review_id[:8]}.csv"'},
    )


@router.get("/{review_id}/export/ris", response_class=PlainTextResponse, summary="导出 RIS")
async def export_review_ris(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    _plan_ok: bool = Depends(require_feature("review_export")),
):
    """导出 RevMan-compatible RIS"""
    from app.services.review_export import export_review_ris as _export_ris

    review = await _get_review_owned(db, review_id, user)
    rid = review.id

    result = await db.execute(
        select(ReviewLiterature, GlobalLiterature)
        .join(GlobalLiterature, ReviewLiterature.literature_id == GlobalLiterature.id)
        .where(ReviewLiterature.review_id == rid)
    )
    lits = []
    for rl, lit in result:
        lits.append({
            "pmid": lit.pmid,
            "title": lit.title,
            "authors": lit.authors,
            "journal": lit.journal,
            "pub_year": lit.pub_year,
            "doi": lit.doi,
            "volume": lit.volume,
            "issue": lit.issue,
            "pages": lit.pages,
            "study_design": lit.study_design,
            "retracted": lit.retracted,
            "trial_reg": lit.trial_reg,
            "quality_score": rl.quality_score,
            "exclusion_reason": rl.exclusion_reason,
        })

    ris_content = _export_ris({}, lits)
    return PlainTextResponse(
        content=ris_content,
        headers={"Content-Disposition": f'attachment; filename="review_{review_id[:8]}.ris"'},
    )


@router.get("/{review_id}/export/rm5", response_class=PlainTextResponse, summary="导出 RevMan .rm5")
async def export_review_rm5(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    _plan_ok: bool = Depends(require_feature("review_export")),
):
    """导出评价为 RevMan .rm5 格式（Cochrane 系统评价原生格式，含 PICO + 效应量）"""
    from app.services.review_rm5 import export_review_rm5 as _export_rm5

    review = await _get_review_owned(db, review_id, user)
    rid = review.id

    result = await db.execute(
        select(ReviewLiterature, GlobalLiterature)
        .join(GlobalLiterature, ReviewLiterature.literature_id == GlobalLiterature.id)
        .where(ReviewLiterature.review_id == rid)
    )
    lits = []
    for rl, lit in result:
        lits.append({
            "pmid": lit.pmid,
            "title": lit.title,
            "authors": lit.authors,
            "journal": lit.journal,
            "pub_year": lit.pub_year,
            "doi": lit.doi,
            "study_design": lit.study_design,
            "pico": rl.pico if rl.pico is not None else lit.pico,
            "retracted": lit.retracted,
            "stage": rl.stage,
            "exclusion_reason": rl.exclusion_reason,
            "quality_score": rl.quality_score,
        })

    rm5_content = _export_rm5(review=review, literatures=lits)
    return PlainTextResponse(
        content=rm5_content,
        media_type="application/xml",
        headers={"Content-Disposition": f'attachment; filename="review_{review_id[:8]}.rm5"'},
    )


@router.get("/{review_id}/prisma", summary="PRISMA 流程数据")
async def get_prisma_flow(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
):
    """获取 PRISMA 流程计数"""
    from app.services.prisma_diagram import compute_prisma_flow

    review = await _get_review_owned(db, review_id, user)
    rid = review.id

    result = await db.execute(
        select(ReviewLiterature).where(ReviewLiterature.review_id == rid)
    )
    literatures = result.scalars().all()
    flow = compute_prisma_flow(review, literatures)
    return flow


@router.get("/{review_id}/prisma/svg", response_class=PlainTextResponse, summary="PRISMA 流程图 SVG")
async def get_prisma_svg(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    language: str = Query("zh", pattern="^(zh|en)$"),
):
    """获取 PRISMA 流程图 SVG（可下载/嵌入）"""
    from app.services.prisma_diagram import compute_prisma_flow, generate_prisma_svg

    review = await _get_review_owned(db, review_id, user)
    rid = review.id

    result = await db.execute(
        select(ReviewLiterature).where(ReviewLiterature.review_id == rid)
    )
    literatures = result.scalars().all()
    flow = compute_prisma_flow(review, literatures)
    svg = generate_prisma_svg(flow, language)
    return PlainTextResponse(content=svg, media_type="image/svg+xml")


@router.get("/{review_id}/methods-summary", summary="方法学小结")
async def get_methods_summary(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    language: str = Query("zh", pattern="^(zh|en)$"),
):
    """生成方法学小结文本"""
    from app.services.methods_summary import generate_methods_summary as _gen_summary
    from app.services.prisma_diagram import compute_prisma_flow

    review = await _get_review_owned(db, review_id, user)
    rid = review.id

    result = await db.execute(
        select(ReviewLiterature).where(ReviewLiterature.review_id == rid)
    )
    literatures = result.scalars().all()
    flow = compute_prisma_flow(review, literatures)

    review_dict = _review_to_dict(review)
    summary = _gen_summary(review_dict, flow, language)
    return {"summary": summary, "language": language}


@router.get("/{review_id}/export/search-strategy", response_class=PlainTextResponse, summary="导出检索策略（PRISMA 附录）")
async def export_search_strategy(
    review_id: str,
    db: AsyncSession = Depends(get_db),
    user: dict = Depends(get_current_user),
    language: str = Query("zh", pattern="^(zh|en)$"),
    target_syntax: str = Query("pubmed", pattern="^(pubmed|europepmc)$"),
):
    """导出 PRISMA 兼容的检索策略文本。

    将 review.search_strategy 中的结构化查询数据格式化为可粘贴的 PRISMA 附录文本。
    target_syntax=pubmed 时自动将 Europe PMC 语法转换为 PubMed 语法。
    """
    from app.services.search_strategy import format_search_strategy, pubmed_syntax

    review = await _get_review_owned(db, review_id, user)

    strategy = review.search_strategy or {}
    if not strategy:
        return PlainTextResponse(
            content="No search strategy recorded." if language == "en" else "未记录检索策略。"
        )

    # 如果请求 PubMed 语法，标记 queries 做转换
    if target_syntax == "pubmed":
        for q in strategy.get("queries", []):
            q["target"] = "pubmed"

    formatted = format_search_strategy(strategy, language=language)
    fname = f"search_strategy_{review_id[:8]}.txt"
    return PlainTextResponse(
        content=formatted or "No search strategy data.",
        headers={"Content-Disposition": f'attachment; filename="{fname}"'},
    )
