# ---------- LinkedIn の柱と枠（2026-11-09 エイイチが採用） ----------
# LinkedIn は平日 17:00 に1日1本。曜日ごとに柱（投稿の種類）を決める。
# 月・木＝課題地図、火＝研究の記録、水＝業界の読み解き、金＝ひとりとAI（なければ業界の読み解き）。
# マンガ・英語・研究の外側の作業の記録は LinkedIn に出さない（X だけ）。docs/sns_autopost.md「LinkedIn の柱と枠」
LINKEDIN_RULE_FROM = dt.datetime(2026, 11, 10, tzinfo=JST)
LINKEDIN_SLOT = (17, 0)
LINKEDIN_PILLARS = {"issue": (0, 3), "research": (1,), "reading": (2, 4), "ai": (4,)}


def next_linkedin_slot(schedule, pillar, after, exclude_id=None):
    """after より後で、その柱の曜日の 17:00 のうち、LinkedIn の予約がまだない最初の日時（JST の ISO 文字列）。"""
    days = LINKEDIN_PILLARS[pillar]
    used = {parse_time(e["post_at"]).astimezone(JST).date() for e in schedule.get("posts", [])
            if e.get("platform") == "linkedin" and e.get("id") != exclude_id}
    start = max(after, LINKEDIN_RULE_FROM).astimezone(JST)
    d = start.date()
    for _ in range(800):
        t = dt.datetime(d.year, d.month, d.day, *LINKEDIN_SLOT, tzinfo=JST)
        if t > start and d.weekday() in days and d not in used:
            return t.isoformat()
        d += dt.timedelta(days=1)
    raise RuntimeError("LinkedIn の空いている枠が見つかりません")


def linkedin_rule_errors(schedule):
    errs, per_day = [], {}
    for e in schedule.get("posts", []):
        if e.get("platform") != "linkedin":
            continue
        try:
            t = parse_time(e["post_at"]).astimezone(JST)
        except (KeyError, ValueError):
            continue
        if t < LINKEDIN_RULE_FROM:
            continue
        where = f"{e['id']}（LinkedIn の決まり）"
        per_day.setdefault(t.date(), []).append(e["id"])
        if lang_of(e) != "ja":
            errs.append(f"{where}: LinkedIn は日本語だけです")
        if os.path.basename(e.get("source", "")).startswith(("MANGA_", "SHORT_")):
            errs.append(f"{where}: マンガとショートは LinkedIn に出しません")
        p = e.get("pillar")
        if p not in LINKEDIN_PILLARS:
            errs.append(f"{where}: pillar（issue・research・reading・ai のどれか）がありません")
            continue
        if (t.hour, t.minute) != LINKEDIN_SLOT or t.weekday() not in LINKEDIN_PILLARS[p]:
            errs.append(f"{where}: {p} の枠（{'・'.join('月火水木金土日'[w] for w in LINKEDIN_PILLARS[p])}曜 17:00）ではありません: {e['post_at']}")
    for d, ids in sorted(per_day.items()):
        if len(ids) > 1:
            errs.append(f"{d}: LinkedIn が1日に{len(ids)}本あります（1日1本まで）: {', '.join(ids)}")
    return errs


def check_schedule(schedule):
    errs = linkedin_rule_errors(schedule)
    ids = set()
    for i, e in enumerate(schedule.get("posts", [])):
        where = f"posts[{i}] {e.get('id', '(id なし)')}"
        for k in ("id", "source", "platform", "post_at"):
            if k not in e:
                errs.append(f"{where}: {k} がありません")
        if any(k not in e for k in ("id", "source", "platform", "post_at")):
            continue
        if e["id"] in ids:
            errs.append(f"{where}: id が重複しています")
        ids.add(e["id"])
        try:
            parse_time(e["post_at"])
        except ValueError as ex:
            errs.append(f"{where}: {ex}")
        if lang_of(e) not in LANGS:
            errs.append(f"{where}: lang は ja か en です")
            continue
        if e["platform"] not in PLATFORMS:
            errs.append(f"{where}: platform は x か linkedin です")
            continue
        try:
            src = load_source(e)
        except (OSError, json.JSONDecodeError) as ex:
            errs.append(f"{where}: 投稿文のファイルが読めません（{ex}）")
            continue
        errs += [f"{where}: {m}" for m in validate(e, src)]
    return errs
