#!/usr/bin/env python3
"""Jellyfin 重复电影检测脚本
通过文件名、ProviderIds、文件大小和时长判断重复
"""

import requests
import sys
from collections import defaultdict

SERVER_URL = "http://172.25.208.1:8096"
API_KEY = "8cbcfe4d7d294c8aa00412ccc853459f"

HEADERS = {
    "X-Emby-Authorization": f'MediaBrowser Client="OpenClaw", Device="PC", DeviceId="openclaw", Version="1.0", Token="{API_KEY}"',
    "Accept": "application/json"
}


def get_all_movies():
    """获取所有电影"""
    movies = []
    start_index = 0
    limit = 100

    while True:
        response = requests.get(
            f"{SERVER_URL}/Items",
            params={
                "includeItemTypes": "Movie",
                "recursive": "true",
                "fields": "Path,ProviderIds,MediaSources,RunTimeTicks,Overview,ProductionYear",
                "limit": limit,
                "startIndex": start_index,
                "enableTotalRecordCount": "true"
            },
            headers=HEADERS
        )

        if response.status_code != 200:
            print(f"请求失败: {response.status_code} {response.text[:200]}")
            break

        data = response.json()
        items = data.get("Items", [])
        movies.extend(items)

        total = data.get("TotalRecordCount", 0)
        start_index += limit

        print(f"  已获取 {len(movies)}/{total} 部电影...", end="\r")
        if start_index >= total:
            break

    print(f"\n  共获取 {len(movies)} 部电影")
    return movies


def find_duplicates(movies):
    """查找重复电影"""
    duplicates = []

    # 1. 相同文件名（不同路径）
    name_map = defaultdict(list)
    for m in movies:
        name = (m.get("Name") or "").strip().lower()
        year = m.get("ProductionYear")
        key = (name, year)
        name_map[key].append(m)

    for key, items in name_map.items():
        if len(items) > 1:
            duplicates.append({
                "type": "相同名称+年份",
                "reason": f"电影名 '{items[0].get('Name')}' ({key[1]}) 存在 {len(items)} 个版本",
                "items": items
            })

    # 2. 相同 ProviderIds (IMDb/TMDb)
    provider_map = defaultdict(list)
    for m in movies:
        providers = m.get("ProviderIds") or {}
        for pid_type in ["Imdb", "Tmdb", "Tvdb"]:
            pid = providers.get(pid_type)
            if pid:
                provider_map[(pid_type, pid)].append(m)

    for key, items in provider_map.items():
        if len(items) > 1:
            duplicates.append({
                "type": "相同 ProviderId",
                "reason": f"{key[0]} = {key[1]} 存在 {len(items)} 个版本",
                "items": items
            })

    # 3. 相同文件大小和时长（不同路径 = 同文件被多次导入）
    size_map = defaultdict(list)
    for m in movies:
        sources = m.get("MediaSources") or []
        if sources:
            size = sources[0].get("Size")
            runtime = m.get("RunTimeTicks")
            if size and runtime:
                # 允许 1% 的误差
                size_key = (size // 1000000, runtime // 1000000)
                size_map[size_key].append((m, size, runtime))

    for (size_gb, runtime_key), items in size_map.items():
        if len(items) > 1:
            # 检查是否来自不同路径
            paths = set(item[0].get("MediaSources", [{}])[0].get("Path", "") for item in items)
            if len(paths) == 1:
                continue  # 同一文件，不重复标记
            duplicates.append({
                "type": "相同文件大小+时长",
                "reason": f"约 {size_gb/1000:.1f}GB / 约 {runtime_key//10000:.0f}分钟 存在 {len(items)} 个版本",
                "items": [item[0] for item in items]
            })

    return duplicates


def main():
    print("=" * 60)
    print("Jellyfin 重复电影检测")
    print("=" * 60)

    print("\n📦 获取所有电影...")
    movies = get_all_movies()

    if not movies:
        print("❌ 未获取到电影数据")
        return

    print(f"\n🔍 开始检测重复...")
    all_dups = find_duplicates(movies)

    if not all_dups:
        print("✅ 未发现重复电影")
        return

    print(f"\n⚠️  发现 {len(all_dups)} 组重复\n")
    print("=" * 60)

    for i, dup in enumerate(all_dups, 1):
        print(f"\n[{i}] {dup['type']}")
        print(f"  原因: {dup['reason']}")
        print(f"  {'─' * 50}")

        for j, item in enumerate(dup['items'], 1):
            name = item.get("Name", "未知")
            year = item.get("ProductionYear", "未知")
            sources = item.get("MediaSources") or []
            path = sources[0].get("Path", "未知路径") if sources else "未知路径"
            size = sources[0].get("Size", 0) if sources else 0
            size_str = f"{size / 1024**3:.2f} GB" if size else "未知大小"
            movie_id = item.get("Id", "未知")
            overview = (item.get("Overview") or "")[:100]

            print(f"    [{j}] {name}")
            print(f"        ID:   {movie_id}")
            print(f"        年份: {year}")
            print(f"        路径: {path}")
            print(f"        大小: {size_str}")
            if overview:
                print(f"        简介: {overview}")

        print()

    print("=" * 60)
    print(f"总计 {len(all_dups)} 组重复，涉及 {
        len(set(item.get('Id') for dup in all_dups for item in dup['items']))
    } 部电影")
    print("=" * 60)


if __name__ == "__main__":
    main()
