from article_common_strict import SAMPLE_HTML
from dataclasses import dataclass
from datetime import date
from typing import Literal
from pydantic import BaseModel, Field
from pydantic_ai import Agent, RunContext


class ArticleInfo(BaseModel):
    """記事のメタデータ（カテゴリ・タグ付き）"""

    title: str = Field(min_length=1, description="記事のタイトル")
    author: str = Field(min_length=1, description="著者名")
    published_date: date = Field(description="公開日")
    url: str = Field(description="記事のURL（相対パス）")
    # カテゴリは以下の選択肢のいずれかとする
    category: Literal[
        "Web開発",
        "型・ツール",
        "AI・機械学習",
        "パッケージ管理",
        "Python新機能",
        "その他",
    ] = Field(description="記事のカテゴリ")
    # タグは1～5個のリストとする
    tags: list[str] = Field(
        min_length=1,
        max_length=5,
        description="技術タグのリスト",
    )


class ArticleList(BaseModel):
    """記事一覧"""

    articles: list[ArticleInfo]


@dataclass
class ArticleDeps:
    # エージェントが必要とする依存リソースをまとめたdataclass
    article_bodies: dict[str, str]


agent = Agent(
    "openai:gpt-5.2",
    output_type=ArticleList,
    deps_type=ArticleDeps,  # ← 依存リソースの型を宣言
    instructions=(
        "与えられたHTMLから記事の一覧情報を抽出してください。"
        "各記事のカテゴリとタグを判定するために、"
        "fetch_article_bodyツールで記事本文を参照してください。"
    ),
    retries=3,
)


@agent.tool
def fetch_article_body(ctx: RunContext[ArticleDeps], url: str) -> str:
    """記事のURLを受け取り、記事本文の冒頭部分を返す。

    Args:
        ctx: 実行コンテキスト（依存リソースへのアクセス手段）
        url: 記事の相対パス（例: /article/2026/01/monthly-python-2601）
    """
    body = ctx.deps.article_bodies.get(url)
    if body:
        return body
    return f"{url}: 本文が見つかりません"


# 外部依存データをArticleDepsのインスタンスとして用意
prod_deps = ArticleDeps(
    article_bodies={  # 本番用データの例（実際にはDBやAPIから取得）
        "/article/2026/01/monthly-python-2601": "CrewAIは複数のAIエージェントを協調させるフレームワークです...",
        "/article/2025/12/monthly-python-2512": "PyreflyはMeta社が開発したRust製のPython型チェッカーです...",
        "/article/2025/11/monthly-python-2511": "t-stringはPython 3.14で導入されたテンプレート文字列リテラルです...",
        "/article/2025/10/monthly-python-2510": "Pydanticはデータバリデーションと設定管理のためのライブラリです...",
        "/article/2025/09/monthly-python-2509": "Python 3.14ではasyncioにタスク可視化機能が追加されました...",
        "/article/2025/08/monthly-python-2508": "PrefectはPythonベースのワークフロー管理フレームワークです...",
    }
)
# run_syncの第1引数は、モデルに解析させる対象データ（SAMPLE_HTML）
# deps引数は、ツール内で参照する外部依存データ（prod_deps）
res = agent.run_sync(SAMPLE_HTML, deps=prod_deps)
for article in res.output.articles:
    print(article)
