#!/usr/bin/env python3
"""
按规则分类归档 source_dirs 中的目录到 categories 定义的大类目录
读配置文件：与脚本同目录下的 config.json
"""
import os, json, shutil

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))

def load_config():
    cfg_path = os.path.join(SCRIPT_DIR, "..", "config.json")
    with open(cfg_path) as f:
        return json.load(f)

def classify(name, cfg):
    """返回目标目录路径，或 None（不移动）"""
    if name in cfg.get("keep_as_is", []):
        return None
    for cat in cfg["categories"]:
        keywords = cat["keywords"]
        if any(k in name for k in keywords):
            return cat["dir"]
    fallback = cfg.get("fallback_dir")
    if fallback:
        return fallback
    return None

def main():
    cfg = load_config()
    src_dirs = cfg["source_dirs"]
    
    moves = []
    for base in src_dirs:
        if not os.path.isdir(base):
            print(f"  [WARN] 目录不存在: {base}")
            continue
        for entry in sorted(os.listdir(base)):
            full = os.path.join(base, entry)
            if not os.path.isdir(full):
                continue
            dst_base = classify(entry, cfg)
            if dst_base is None:
                print(f"  ○ 不动: {entry}")
                continue
            dst = os.path.join(dst_base, entry)
            if os.path.exists(dst):
                i = 1
                while os.path.exists(f"{dst}_{i}"): i += 1
                dst = f"{dst}_{i}"
            moves.append((full, dst))
    
    # 创建目录
    for _, d in moves:
        os.makedirs(os.path.dirname(d), exist_ok=True)
    
    # 执行移动
    print(f"开始移动 {len(moves)} 个条目...")
    for src, dst in moves:
        try:
            shutil.move(src, dst)
            print(f"  ✓ {os.path.basename(src)}")
        except Exception as e:
            print(f"  ✗ {os.path.basename(src)} -> {e}")
    
    # 清理空源目录
    for d in src_dirs:
        if os.path.isdir(d) and not os.listdir(d):
            os.rmdir(d)
            print(f"  ✓ 已删空目录: {d}")
    
    # 报告
    base = os.path.commonpath([os.path.dirname(d) for _, d in moves])
    for _, d in moves:
        base = os.path.commonpath([base, os.path.dirname(d)])
    base = base or "/"
    
    print(f"\n=== 归档完成 ===")
    seen = set()
    for _, d in moves:
        parent = os.path.dirname(d)
        if parent not in seen:
            sz = 0
            cnt = 0
            for dp, dn, fn in os.walk(parent):
                for f in fn:
                    cnt += 1
                    try: sz += os.path.getsize(os.path.join(dp, f))
                    except: pass
            print(f"  {parent}/  ({cnt} 文件, {sz/1024**3:.1f}GB)")
            seen.add(parent)

if __name__ == "__main__":
    main()
