#!/usr/bin/env python3
"""neta.py — ネタ出し係。いま騒がれている人・出来事を拾い、エイイチの経験とつなぎ、事実を確かめた候補を20本出す.

制作チーム（seisaku.py）で、題材を AI が考え出すと面白くならなかったため、題材は「考え出す」のをやめて
「いま騒がれているものを拾う」ことにした。3つの AI は持つ材料を分ける。

置き場所: 動画/_ネタ/{名前}/
  かける.txt          印。見回り（debate_runner.py）がこれを見て動かす。終わると かけた.txt
  止める.txt          置くと止まる
  依頼.md             （なくてよい）足したい注文

流れ:
  0_急上昇.md          YouTube の日本の急上昇50本（Data API の mostPopular）
  1_騒ぎ_Gemini.md     Gemini（Google 検索）：日本で直近7日に騒がれている人・出来事 15件（急上昇も材料にする）
  1_騒ぎ_codex.md      codex（Web 検索）：海外で直近7日に騒がれ、日本にも届きそうな AI・テック・ロボットの騒ぎ 10件
  2_候補_Claude.md     Claude：騒ぎの中から、エイイチにしか言えない角度があるものを選び、遊びの形にした候補 20本
                       （ここで止まり、Claudeの番.txt を置く）
  候補.md              codex（Web 検索）：候補ごとに事実を確かめ、判定と直しをつけた最終の表
  進み具合.md・エラー.txt・状態.json
"""
import json, os, time
from datetime import datetime, timedelta, timezone

import debate_runner as dr
cr = dr.cr

ROOT = "_ネタ"
MARK, DONE, STOP, RUNNING = "かける.txt", "かけた.txt", "止める.txt", "実行中.txt"

JIJI = """\
# 時事ネタとは（エイイチが決めたお手本）
楽待の動画「【超知能AI】2030年にも『人類絶滅』か、元OpenAI・Anthropic研究者の警告」（2026-11-14公開、当日約1.4万回）。
- 題材は、いま騒ぎの真ん中にいる人・出来事そのもの。少し古い発表を検索で見つけてきたものではない
- その人自身の言葉（発言・投稿・会見）がある
- 日本の人に身近な問いに引き寄せている（スカイネット、ドラえもん）
海外Yパパラジオの例：「炎を呼んだ男ファイアー鈴木の話」（2時間で2.4万回）、「どの企業トップの辞め方が一番恥ずかしいか？（恥ずかしい辞任コンテスト）」（15時間で19万回）。
いま騒がれている人を、本人の経験と遊びの形（コンテスト・ランキング・一言）で読む。
"""

GEMINI_TASK = JIJI + """
# あなたの仕事：日本で、いま騒がれている人・出来事を15件拾う
- 期間は今日から数えて直近7日。それより古いものは入れない（発表日・発生日を必ず確かめる）
- 分野は問わない（芸能・経済・事件・事故・企業・政治家の発言・SNSの炎上・スポーツ・AI）。ただし AI・テック・ロボットに関わるものを4件以上入れる
- 下の「YouTube の急上昇」も材料にしてよい（そこから拾ったら、そう書く）
- 考え出さない。実際に起きて、実際に騒がれているものだけ
- 1件ずつ、次の形で書く：
### {番号}. {人・出来事の名前}
- 何が起きた：1〜2行
- 本人の言葉：本人の発言・投稿の短い引用（なければ「なし」）
- なぜ騒がれている：1行
- 日付：YYYY-MM-DD
- 出典：URL（報道・公式。まとめサイトは不可）
"""

CODEX_COLLECT = JIJI + """
# あなたの仕事：海外で、いま騒がれている AI・テック・ロボットの人・出来事を10件拾う
- 期間は今日から数えて直近7日。それより古いものは入れない（日付を必ず確かめる）
- 日本でもこれから話題になりそうなもの（有名な CEO・研究者の発言、事故、訴訟、大きな発表、炎上、人型ロボットの映像など）
- 考え出さない。実際に起きて、実際に騒がれているものだけ。必ず Web で確かめる
- 1件ずつ、次の形で書く：
### {番号}. {人・出来事の名前}
- 何が起きた：1〜2行（日本語）
- 本人の言葉：本人の発言・投稿の短い引用（日本語訳と原文。なければ「なし」）
- なぜ騒がれている：1行
- 日付：YYYY-MM-DD
- 出典：URL
"""

CLAUDE_TASK = JIJI + """
# あなたの仕事（Claude）：騒ぎの中から、エイイチにしか言えない角度があるものを選び、候補を20本作る
- 材料は下の 1_騒ぎ_Gemini.md と 1_騒ぎ_codex.md。新しい題材を考え出さない
- エイイチの経験：ファミレスのホール、ロボットの研究と開発（机のロボットアーム・π0.5の学習・配膳ロボットの試算）、29年のデザイナー、アパレルの量産で遠い工場に仕様を渡してきた、RCカーの会社、（地名）での暮らし、生成AIで仕事が減った
- 形は遊んでよい（コンテスト・ランキング・判定・ハコブくんの一言）。ただし釣り・誇張・中身と合わない題名はしない
- ロボット以外の AI・時事は全体の30%までという決まりは、ここでは数えない（最後に選ぶときに数える）
- 1本ずつ、次の形で書く（1本は5行以内）：
### {番号}. {題名}
- サムネイル：大きな文字2〜3行（／で区切る）＋ハコブくんの一言
- 騒ぎ：材料の番号と名前
- エイイチの角度：1行（どの経験から、何が言えるか）
- 見せるもの：1行（撮る・作るもの。2〜3時間で撮れるもの）
"""

CHECK_TASK = """\
# あなたの仕事：候補20本の事実を確かめ、最終の表を作る
- 候補ごとに、題名・サムネイル・騒ぎの事実が出典と合っているかを Web で確かめる
- 判定は4つのどれか：確認済／言い過ぎ（直せば使える）／間違い／未確認
- 直しは、事実を合わせるための最小限だけ。角度・形・面白さは変えない（面白くするのはあなたの仕事ではない）
- 出力は次の表1つと、表の下に「直した所」の箇条書きだけ：
| 番号 | 題名（直したならあとの文） | サムネイル | 判定 | 日付 | 出典 |
"""


def path(d, n):
    return os.path.join(d, n)


def exists(d, n):
    return os.path.isfile(path(d, n))


def read(d, n):
    return dr.read(path(d, n))


def now():
    return datetime.now(dr.JST).strftime("%Y-%m-%d %H:%M")


def doc(d, name, title, meta, body):
    dr.write(path(d, name), f"# {title}\n\n- 日時: {now()}（JST）\n- {meta}\n\n---\n\n{body}")


def load(d):
    p = path(d, "状態.json")
    if os.path.isfile(p):
        return json.load(open(p, encoding="utf-8"))
    return {"cost_in": 0, "cost_out": 0, "codex": 0, "start": now()}


def save(d, st):
    with open(path(d, "状態.json"), "w", encoding="utf-8") as f:
        json.dump(st, f, ensure_ascii=False, indent=1)


def progress(d, st, what):
    usd = st["cost_in"] / 1e6 * 2.0 + st["cost_out"] / 1e6 * 12.0
    steps = [("0_急上昇.md", "YouTube の急上昇"), ("1_騒ぎ_Gemini.md", "日本の騒ぎ（Gemini）"),
             ("1_騒ぎ_codex.md", "海外の騒ぎ（codex）"), ("2_候補_Claude.md", "候補20本（Claude）"),
             ("候補.md", "事実の確かめ（codex）")]
    L = [f"# 進み具合（ネタ出し：{os.path.basename(d)}）", "", f"- いま：**{what}**",
         f"- 始めた時刻 {st['start']}・最後に書いた時刻 {now()}",
         f"- Gemini の費用の目安 約{usd * 155:,.0f}円・codex {st['codex']} 回（ChatGPT Plus の枠）", ""]
    L += [f"- [{'x' if exists(d, f) else ' '}] {label}（{f}）" for f, label in steps]
    dr.write(path(d, "進み具合.md"), "\n".join(L))


def trending():
    import youtube_market as ym
    import youtube_schedule as ys
    tok = ys.access_token()
    r = ym.api("videos", tok, part="snippet,statistics", chart="mostPopular", regionCode="JP", maxResults=50)
    L = [f"YouTube 日本の急上昇（{now()} 取得）", ""]
    for i, v in enumerate(r.get("items", []), 1):
        s, st = v["snippet"], v.get("statistics", {})
        L.append(f"{i}. {s.get('title', '')}｜{s.get('channelTitle', '')}｜{int(st.get('viewCount', 0)):,}回｜{s.get('publishedAt', '')[:10]}")
    return "\n".join(L)


def run(name, d, dry):
    st = load(d)
    save(d, st)
    if dry:
        return dr.log(f"［試し］ネタ出し {name}")
    dr.write(path(d, RUNNING), f"開始 {now()}\nPID {os.getpid()}\n")
    flag = path(d, "Claudeの番.txt")
    try:
        if os.path.exists(flag):
            if exists(d, "2_候補_Claude.md"):
                os.remove(flag)
            else:
                return dr.log("  ネタ出し：まだ Claude の番です")
        extra = ("\n\n# エイイチからの注文\n\n" + read(d, "依頼.md")) if exists(d, "依頼.md") else ""
        today = f"\n\n今日は {datetime.now(dr.JST).strftime('%Y-%m-%d')}（JST）。"
        if not exists(d, "0_急上昇.md"):
            progress(d, st, "YouTube の急上昇を取っています")
            try:
                body = trending()
            except Exception as e:
                body = f"（急上昇は取れませんでした: {e}）"
            doc(d, "0_急上昇.md", "YouTube の急上昇", "YouTube Data API（chart=mostPopular・regionCode=JP）", body)
        if not exists(d, "1_騒ぎ_Gemini.md"):
            progress(d, st, "Gemini が日本の騒ぎを拾っています")
            key = dr.gemini_key()
            model, _ = dr.pick_model(key)
            ans, meta = dr.gemini(key, model, GEMINI_TASK + today + extra, read(d, "0_急上昇.md"), search=True)
            st["cost_in"] += dr.LAST_USAGE["inp"]
            st["cost_out"] += dr.LAST_USAGE["out"]
            doc(d, "1_騒ぎ_Gemini.md", "日本で騒がれている人・出来事（Gemini）", meta, ans)
            save(d, st)
        if not exists(d, "1_騒ぎ_codex.md"):
            progress(d, st, "codex が海外の騒ぎを拾っています")
            ans, meta = dr.codex(d, CODEX_COLLECT + today + extra, web=True)
            st["codex"] += 1
            doc(d, "1_騒ぎ_codex.md", "海外で騒がれている AI・テック・ロボット（codex）", meta, ans)
            save(d, st)
        if not exists(d, "2_候補_Claude.md"):
            dr.write(path(d, "Claudeへ.md"), CLAUDE_TASK + today + extra + "\n\n# 材料\n\n" +
                     read(d, "1_騒ぎ_Gemini.md") + "\n\n" + read(d, "1_騒ぎ_codex.md"))
            progress(d, st, "Claude の番：候補20本（Claudeへ.md を読む・2_候補_Claude.md を待っています）")
            if not os.path.exists(flag):
                dr.write(flag, f"{now()}\n候補20本（Claudeへ.md を読む）\n2_候補_Claude.md を置けば続きます\n")
                dr.notify(f"ネタ出し {name}：Claude の番")
            return
        if not exists(d, "候補.md"):
            progress(d, st, "codex が候補の事実を確かめています")
            body = (CHECK_TASK + today + "\n\n# 候補\n\n" + read(d, "2_候補_Claude.md") + "\n\n# 材料\n\n" +
                    read(d, "1_騒ぎ_Gemini.md") + "\n\n" + read(d, "1_騒ぎ_codex.md"))
            ans, meta = dr.codex(d, body, web=True)
            st["codex"] += 1
            doc(d, "候補.md", "候補（事実を確かめた最終の表）", meta,
                "見たいものに ○ をつけてください（番号だけチャットで伝えるのでもよい）。\n\n" + ans)
            save(d, st)
        if os.path.exists(path(d, MARK)):
            os.rename(path(d, MARK), path(d, DONE))
        progress(d, st, "終わり。候補.md を見て、見たいものに ○ をつけてください")
        dr.notify(f"ネタ出しが終わりました：{name}")
        dr.log(f"✓ ネタ出し {name}")
    except Exception as e:
        dr.write(path(d, "エラー.txt"), f"{now()}\n\n{e}\n")
        progress(d, st, "エラーで止まりました（エラー.txt）。次の見回りで続きから試します")
        dr.log(f"× ネタ出し {name}: {e}")
    finally:
        save(d, st)
        if os.path.exists(path(d, RUNNING)):
            os.remove(path(d, RUNNING))


def sweep(dry):
    real = cr.listdir_nfc(dr.VIDEOS).get(dr.nfc(ROOT))
    if not real:
        return False
    root = os.path.join(dr.VIDEOS, real)
    for name, r in sorted(cr.listdir_nfc(root).items()):
        d = os.path.join(root, r)
        if not os.path.isdir(d):
            continue
        f = cr.listdir_nfc(d)
        if RUNNING in f:
            if time.time() - os.path.getmtime(path(d, f[RUNNING])) < 3 * 3600:
                dr.log(f"ネタ出し {name} が動いています")
                return True
            os.remove(path(d, f[RUNNING]))
        if MARK in f and STOP not in f:
            if "Claudeの番.txt" in f and "2_候補_Claude.md" not in f:
                continue                               # Claude を待っている間は、ほかの仕事を回す
            dr.log(f"▶ ネタ出し {ROOT}/{name}")
            run(name, d, dry)
            return True
    return False
