#!/usr/bin/env python3
"""分析 Twitter archive 資料"""

import json
import os
import re
import sys
from collections import Counter
from datetime import datetime
from pathlib import Path

BOOKMARKS_PATH = Path(__file__).parent / "output" / "bookmarks.json"
OUTPUT_PATH = Path(__file__).parent / "output" / "analysis.md"


def find_archive_dir() -> Path:
    docs = Path.home() / "Documents"
    matches = list(docs.glob("twitter-*"))
    if not matches:
        print("ERROR: 找不到 Twitter archive，請放在 ~/Documents/twitter-*")
        sys.exit(1)
    return matches[0] / "data"


def load_js(archive_dir: Path, filename: str) -> list:
    path = archive_dir / filename
    text = path.read_text(encoding="utf-8")
    json_start = text.index("[")
    return json.loads(text[json_start:])


def load_bookmarks() -> set[str]:
    if not BOOKMARKS_PATH.exists():
        return set()
    data = json.loads(BOOKMARKS_PATH.read_text(encoding="utf-8"))
    return {t["tweet_id"] for t in data if t.get("tweet_id")}


def analyze_tweets(tweets_raw: list) -> str:
    lines = [f"## Your Tweets ({len(tweets_raw)})\n"]

    tweets = []
    for item in tweets_raw:
        t = item["tweet"]
        created = datetime.strptime(t["created_at"], "%a %b %d %H:%M:%S %z %Y")
        tweets.append({
            "text": t["full_text"],
            "likes": int(t.get("favorite_count", 0)),
            "rts": int(t.get("retweet_count", 0)),
            "lang": t.get("lang", ""),
            "created_at": created,
            "hour": created.hour,
            "weekday": created.strftime("%A"),
            "is_rt": t["full_text"].startswith("RT @"),
            "is_reply": t["full_text"].startswith("@"),
            "mentions": [m["screen_name"] for m in t.get("entities", {}).get("user_mentions", [])],
            "hashtags": [h["text"] for h in t.get("entities", {}).get("hashtags", [])],
            "source": re.sub(r"<[^>]+>", "", t.get("source", "")),
        })

    original = [t for t in tweets if not t["is_rt"]]
    rts = [t for t in tweets if t["is_rt"]]

    lines.append(f"- Original: {len(original)} | RT: {len(rts)}")
    lines.append(f"- Date range: {min(t['created_at'] for t in tweets).strftime('%Y-%m-%d')} ~ {max(t['created_at'] for t in tweets).strftime('%Y-%m-%d')}")

    lang_counter = Counter(t["lang"] for t in original)
    lines.append(f"- Languages: {', '.join(f'{lang}({cnt})' for lang, cnt in lang_counter.most_common(5))}")

    source_counter = Counter(t["source"] for t in tweets)
    lines.append(f"- Devices: {', '.join(f'{s}({c})' for s, c in source_counter.most_common(3))}")

    lines.append("\n### Top Engagement (Original Tweets)\n")
    lines.append("| Likes | RTs | Text |")
    lines.append("|-------|-----|------|")
    top = sorted(original, key=lambda t: t["likes"] + t["rts"], reverse=True)[:15]
    for t in top:
        text = t["text"][:80].replace("\n", " ").replace("|", "\\|")
        lines.append(f"| {t['likes']} | {t['rts']} | {text} |")

    lines.append("\n### Posting Time (UTC)\n")
    hour_counter = Counter(t["hour"] for t in tweets)
    max_count = max(hour_counter.values()) if hour_counter else 1
    for hour in range(24):
        cnt = hour_counter.get(hour, 0)
        bar = "█" * int(cnt / max_count * 20) if cnt else ""
        lines.append(f"  {hour:02d}:00  {bar} {cnt}")

    lines.append("\n### Day of Week\n")
    day_order = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
    day_counter = Counter(t["weekday"] for t in tweets)
    for day in day_order:
        cnt = day_counter.get(day, 0)
        lines.append(f"  {day:<10} {'█' * int(cnt / max(day_counter.values()) * 15)} {cnt}")

    lines.append("\n### Most Mentioned Users\n")
    mention_counter = Counter()
    for t in tweets:
        mention_counter.update(t["mentions"])
    for user, cnt in mention_counter.most_common(15):
        lines.append(f"  @{user} — {cnt} times")

    lines.append("\n### Top Hashtags\n")
    hashtag_counter = Counter()
    for t in tweets:
        hashtag_counter.update(t["hashtags"])
    if hashtag_counter:
        for tag, cnt in hashtag_counter.most_common(15):
            lines.append(f"  #{tag} — {cnt}")
    else:
        lines.append("  (none)")

    return "\n".join(lines)


def analyze_likes(likes_raw: list, bookmark_ids: set[str]) -> str:
    lines = [f"## Likes ({len(likes_raw)})\n"]

    likes = []
    for item in likes_raw:
        li = item["like"]
        likes.append({
            "tweet_id": li["tweetId"],
            "text": li.get("fullText", ""),
        })

    liked_ids = {l["tweet_id"] for l in likes}
    overlap = liked_ids & bookmark_ids
    liked_only = liked_ids - bookmark_ids
    bookmarked_only = bookmark_ids - liked_ids

    lines.append(f"- Total likes: {len(likes)}")
    lines.append(f"- Total bookmarks: {len(bookmark_ids)}")
    lines.append(f"- Liked AND bookmarked: {len(overlap)}")
    lines.append(f"- Liked but NOT bookmarked: {len(liked_only)}")
    lines.append(f"- Bookmarked but NOT liked: {len(bookmarked_only)}")

    lines.append("\n### Keyword Frequency in Liked Tweets\n")
    word_counter = Counter()
    stop_words = {"the", "a", "an", "is", "are", "was", "were", "be", "to", "of", "and", "in",
                  "that", "it", "for", "on", "with", "as", "at", "by", "this", "from", "or",
                  "not", "but", "you", "your", "i", "my", "me", "we", "they", "he", "she",
                  "do", "does", "did", "will", "would", "can", "could", "have", "has", "had",
                  "rt", "https", "co", "t", "s", "amp", "just", "like", "so", "if", "all",
                  "about", "what", "when", "how", "who", "which", "no", "more", "than",
                  "been", "also", "其", "的", "了", "在", "是", "我", "不", "有", "這",
                  "就", "都", "也", "人", "他", "她", "們", "要", "會", "很", "你",
                  "一", "個", "上", "嗎", "吧", "啊", "呢", "把", "被", "讓", "給",
                  "而", "但", "又", "還", "到", "去", "來", "著", "過", "得", "能",
                  "可以", "因為", "所以", "如果", "那", "什麼", "沒有", "自己"}

    for li in likes:
        text = li["text"].lower()
        text = re.sub(r"https?://\S+", "", text)
        text = re.sub(r"@\w+", "", text)
        words = re.findall(r"[a-z]{3,}|[\u4e00-\u9fff]{2,}", text)
        word_counter.update(w for w in words if w not in stop_words)

    for word, cnt in word_counter.most_common(30):
        lines.append(f"  {word} — {cnt}")

    return "\n".join(lines)


def analyze_following(following_raw: list, follower_raw: list) -> str:
    lines = ["## Social Graph\n"]

    following_ids = {f["following"]["accountId"] for f in following_raw}
    follower_ids = {f["follower"]["accountId"] for f in follower_raw}

    mutual = following_ids & follower_ids
    following_only = following_ids - follower_ids
    follower_only = follower_ids - following_ids

    lines.append(f"- Following: {len(following_ids)}")
    lines.append(f"- Followers: {len(follower_ids)}")
    lines.append(f"- Mutual: {len(mutual)}")
    lines.append(f"- You follow but they don't follow back: {len(following_only)}")
    lines.append(f"- They follow you but you don't follow back: {len(follower_only)}")
    lines.append(f"- Follow-back ratio: {len(mutual) / len(following_ids) * 100:.1f}%")

    return "\n".join(lines)


def main():
    archive_dir = find_archive_dir()
    print(f"→ Loading archive from {archive_dir.parent.name}...")

    tweets_raw = load_js(archive_dir, "tweets.js")
    likes_raw = load_js(archive_dir, "like.js")
    following_raw = load_js(archive_dir, "following.js")
    follower_raw = load_js(archive_dir, "follower.js")
    bookmark_ids = load_bookmarks()

    print(f"  Tweets: {len(tweets_raw)}, Likes: {len(likes_raw)}, Following: {len(following_raw)}, Followers: {len(follower_raw)}, Bookmarks: {len(bookmark_ids)}")

    sections = [
        f"# Twitter Archive Analysis\n\nGenerated: {datetime.now().strftime('%Y-%m-%d %H:%M')}\n",
        analyze_tweets(tweets_raw),
        analyze_likes(likes_raw, bookmark_ids),
        analyze_following(following_raw, follower_raw),
    ]

    report = "\n\n---\n\n".join(sections)
    OUTPUT_PATH.write_text(report, encoding="utf-8")
    print(f"\n→ Report saved: {OUTPUT_PATH}")
    print(report)


if __name__ == "__main__":
    main()
