#!/usr/bin/env python3
"""
research67/run_pipeline.py — 科研论文生成管线

多轮迭代：每轮执行一个阶段，评审不通过则回退修改，直到论文完成。

用法:
    python3 agentexample/research67/run_pipeline.py --idea "你的研究想法"
    python3 agentexample/research67/run_pipeline.py --idea-file path/to/IDEA.md
    python3 agentexample/research67/run_pipeline.py --claude   # 强制 Claude Code
    python3 agentexample/research67/run_pipeline.py --ollama   # 用本地 Ollama
"""
from __future__ import annotations

import argparse
import json
import os
import sys
import time
from pathlib import Path

PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent
sys.path.insert(0, str(PROJECT_ROOT))

from lambdagent.fromconfig import from_config
from lambdagent.core import Context


# ══════════════════════════════════════════════════════
# 管线阶段定义
# ══════════════════════════════════════════════════════

PHASES = [
    {
        "name": "文献调研",
        "prompt": (
            "第一步：文献调研。\n"
            "1. 用 WebSearch 搜索与该研究主题相关的论文（至少搜索 3 次不同关键词）\n"
            "2. 整理搜索结果，提取每篇论文的标题、作者、年份、核心方法、主要结论\n"
            "3. 用 WriteFile 将文献综述写入 {workspace}/01_literature_review.md\n"
            "4. 总结研究现状和 gap"
        ),
    },
    {
        "name": "实验方案",
        "prompt": (
            "第二步：制定实验方案。\n"
            "1. 先用 ReadFile 读取 {workspace}/01_literature_review.md 了解前期调研\n"
            "2. 基于研究想法和文献综述，设计实验方案\n"
            "3. 包含：数据集选择、baseline 对比、评价指标、实验步骤\n"
            "4. 用 WriteFile 写入 {workspace}/02_experiment_plan.md"
        ),
    },
    {
        "name": "实验执行",
        "prompt": (
            "第三步：执行实验。\n"
            "1. 先读取 {workspace}/02_experiment_plan.md 了解实验方案\n"
            "2. 用 WriteFile 编写 Python 实验代码到 {workspace}/code/\n"
            "3. 用 Bash 运行实验代码\n"
            "4. 将实验结果（数据/图表）保存到 {workspace}/results/\n"
            "5. 用 WriteFile 写实验报告到 {workspace}/03_experiment_results.md"
        ),
    },
    {
        "name": "论文撰写",
        "prompt": (
            "第四步：撰写论文。\n"
            "1. 读取前几个阶段的文件：01_literature_review.md, 02_experiment_plan.md, 03_experiment_results.md\n"
            "2. 撰写完整的学术论文，包含：\n"
            "   - Abstract（200字以内）\n"
            "   - 1. Introduction（研究背景、问题、贡献）\n"
            "   - 2. Related Work（基于文献调研）\n"
            "   - 3. Method（提出的方法详细描述）\n"
            "   - 4. Experiments（实验设置、结果、分析）\n"
            "   - 5. Conclusion（总结和未来工作）\n"
            "   - References\n"
            "3. 用 WriteFile 写入 {workspace}/04_paper.md"
        ),
    },
    {
        "name": "论文评审",
        "prompt": (
            "第五步：模拟评审。\n"
            "1. 读取 {workspace}/04_paper.md\n"
            "2. 以**该领域世界最顶级期刊/会议**的资深审稿人视角评审论文。\n"
            "   根据论文所属学科自动匹配对标标准，例如：\n"
            "   - 计算机: NeurIPS / ICML / CVPR / ACL / SIGMOD / OSDI / SOSP\n"
            "   - 物理: Nature Physics / Physical Review Letters\n"
            "   - 生物医学: Nature / Science / Cell / The Lancet\n"
            "   - 数学: Annals of Mathematics / Inventiones Mathematicae\n"
            "   - 经济学: AER / Econometrica / QJE\n"
            "   - 材料/化学: Nature Materials / JACS / Angewandte Chemie\n"
            "   - 综合/交叉: Nature / Science / PNAS\n"
            "3. 从以下维度评分（1-5分）：\n"
            "   - novelty（新颖性）：相比 state-of-the-art 的创新程度\n"
            "   - soundness（技术正确性）：方法论、实验设计、统计分析是否严谨\n"
            "   - clarity（表述清晰度）：逻辑结构、语言质量、图表规范\n"
            "   - significance（研究意义）：对领域的潜在影响\n"
            "   - reproducibility（可复现性）：数据/代码/实验描述是否充分\n"
            "4. 计算综合评分（加权平均），给出 acceptance_probability (0-1)\n"
            "5. 指出论文匹配的最佳目标期刊/会议（及其投稿截止日期如果知道）\n"
            "6. 列出具体的修改建议（至少 3 条，按优先级排序）\n"
            "7. 用 WriteFile 将评审结果写入 {workspace}/05_review.json，格式：\n"
            '   {{"target_venue":"期刊/会议名","novelty":X,"soundness":X,"clarity":X,'
            '"significance":X,"reproducibility":X,"acceptance_probability":X,'
            '"suggestions":["..."],"strengths":["..."],"weaknesses":["..."],"summary":"..."}}'
        ),
    },
]

REVISION_PROMPT = (
    "论文评审未通过（acceptance_probability < {threshold}）。\n"
    "评审意见：{suggestions}\n\n"
    "请根据评审意见修改论文：\n"
    "1. 读取 {workspace}/04_paper.md 和 {workspace}/05_review.json\n"
    "2. 针对每条修改建议逐一改进\n"
    "3. 用 WriteFile 将修改后的论文覆盖写入 {workspace}/04_paper.md\n"
    "4. 简要说明你做了哪些修改"
)


# ══════════════════════════════════════════════════════
# 管线执行器
# ══════════════════════════════════════════════════════

def run_pipeline(idea: str, max_rounds: int = 3, threshold: float = 0.5,
                 config_path: str = None):
    """执行科研管线，多轮迭代直到论文通过或达到最大轮次。"""

    config_path = config_path or str(Path(__file__).parent / "agent-config.yml")

    # 创建工作区
    timestamp = time.strftime("%Y%m%d_%H%M%S")
    workspace = str(Path(__file__).parent / "workspace" / f"run_{timestamp}")
    os.makedirs(workspace, exist_ok=True)
    os.makedirs(f"{workspace}/code", exist_ok=True)
    os.makedirs(f"{workspace}/results", exist_ok=True)

    # 保存 IDEA
    with open(f"{workspace}/IDEA.md", "w") as f:
        f.write(idea)

    print(f"\n{'═' * 60}")
    print(f"  📚 research67 — 科研论文生成管线")
    print(f"  工作区: {workspace}")
    print(f"  最大轮次: {max_rounds}")
    print(f"  通过阈值: {threshold}")
    print(f"{'═' * 60}\n")

    for round_num in range(1, max_rounds + 1):
        print(f"\n{'─' * 40}")
        print(f"  🔄 第 {round_num} 轮")
        print(f"{'─' * 40}")

        # 每轮创建新的 agent 实例（新会话）
        term = from_config(config_path)
        ctx = Context()

        # 首次输入包含研究想法
        initial_context = (
            f"研究主题：\n{idea}\n\n"
            f"工作区路径: {workspace}\n"
            f"当前轮次: {round_num}/{max_rounds}\n"
        )

        # 执行每个阶段
        for phase in PHASES:
            phase_name = phase["name"]
            phase_prompt = phase["prompt"].format(workspace=workspace)

            print(f"\n  📌 阶段: {phase_name}")
            t0 = time.time()

            if phase == PHASES[0]:
                # 首阶段：带完整上下文
                result = term.apply(initial_context + "\n" + phase_prompt, ctx)
            else:
                # 后续阶段：agent 已有记忆
                result = term.apply(phase_prompt, ctx)

            elapsed = time.time() - t0
            print(f"  ✅ {phase_name} 完成 ({elapsed:.0f}s, {len(ctx.trace)} 步)")

        # 检查评审结果
        review_path = f"{workspace}/05_review.json"
        if os.path.exists(review_path):
            try:
                with open(review_path) as f:
                    review = json.loads(f.read())
                score = review.get("acceptance_probability", 0)
                print(f"\n  📊 评审结果: acceptance_probability = {score:.2f}")
                print(f"     novelty={review.get('novelty')}, soundness={review.get('soundness')}, "
                      f"clarity={review.get('clarity')}, significance={review.get('significance')}")

                if score >= threshold:
                    print(f"\n  🎉 论文通过！(score={score:.2f} ≥ {threshold})")
                    break

                if round_num < max_rounds:
                    suggestions = review.get("suggestions", [])
                    print(f"  ⚠️  未通过 (score={score:.2f} < {threshold})，开始修改...")

                    # 修改论文
                    revision_prompt = REVISION_PROMPT.format(
                        threshold=threshold,
                        suggestions=json.dumps(suggestions, ensure_ascii=False),
                        workspace=workspace,
                    )
                    result = term.apply(revision_prompt, ctx)
                    print(f"  ✅ 修改完成")
            except (json.JSONDecodeError, KeyError) as e:
                print(f"  ⚠️  评审结果解析失败: {e}")
        else:
            print(f"  ⚠️  未生成评审文件: {review_path}")

    # 最终输出
    paper_path = f"{workspace}/04_paper.md"
    print(f"\n{'═' * 60}")
    print(f"  📚 管线结束")
    print(f"  论文路径: {paper_path}")
    print(f"  工作区: {workspace}")
    if os.path.exists(paper_path):
        with open(paper_path) as f:
            content = f.read()
        print(f"  论文长度: {len(content)} 字符, {content.count(chr(10))} 行")
    print(f"{'═' * 60}")


# ══════════════════════════════════════════════════════
# CLI 入口
# ══════════════════════════════════════════════════════

def main():
    parser = argparse.ArgumentParser(description="📚 research67 科研论文生成管线")
    parser.add_argument("--idea", type=str, help="研究想法（直接文本）")
    parser.add_argument("--idea-file", type=str, help="研究想法文件路径")
    parser.add_argument("--max-rounds", type=int, default=3, help="最大迭代轮次（默认 3）")
    parser.add_argument("--threshold", type=float, default=0.5, help="通过阈值（默认 0.5）")
    parser.add_argument("--config", type=str, default=None, help="agent-config.yml 路径")
    args = parser.parse_args()

    if args.idea_file:
        with open(args.idea_file) as f:
            idea = f.read()
    elif args.idea:
        idea = args.idea
    else:
        print("请提供研究想法：")
        print("  --idea '研究主题描述'")
        print("  --idea-file path/to/IDEA.md")
        return

    run_pipeline(
        idea=idea,
        max_rounds=args.max_rounds,
        threshold=args.threshold,
        config_path=args.config,
    )


if __name__ == "__main__":
    main()
