# -*- coding: utf-8 -*-
import csv, os, re, subprocess, urllib.request, shutil
from concurrent.futures import ThreadPoolExecutor, as_completed
from collections import Counter

BASE = "."
DL = os.path.join(BASE, "_download")
UNZ = os.path.join(BASE, "_unz")
GRADE = os.path.join(BASE, "graded")
CATALOG = os.path.join(BASE, "catalog.csv")
os.makedirs(DL, exist_ok=True); os.makedirs(UNZ, exist_ok=True)
for g in range(1,6): os.makedirs(os.path.join(GRADE,f"grade{g}"), exist_ok=True)

rows=list(csv.reader(open("manifest.csv",encoding="utf-8")))
H=rows[0]; idx={n:i for i,n in enumerate(H)}
allb=rows[1:]

# 只取 aozora 內部 URL，去重(同作品ID取第一)，取前1000
seen=set(); books=[]
for r in allb:
    wid=r[idx["作品ID"]]
    if wid in seen: continue
    if "aozora.gr.jp" not in r[idx["テキストファイルURL"]]: continue
    seen.add(wid); books.append(r)
books=books[:1000]
print("目標 1000 本，實際:", len(books))

# 清空 grade
for g in range(1,6):
    d=os.path.join(GRADE,f"grade{g}")
    for f in os.listdir(d): os.remove(os.path.join(d,f))

def sanitize(s):
    return re.sub(r'[\/:*?"<>|]',"_",s)[:150]

def count_body(txt):
    lines=txt.split("\n"); start=0
    for i,ln in enumerate(lines):
        if ln.strip()=="" or "記号" in ln or "【" in ln:
            if set(ln.strip())<=set("-") or "記号" in ln or "【" in ln: continue
        start=i; break
    body="\n".join(lines[start:])
    body=re.sub(r'《[^》]*》','',body)
    body=re.sub(r'｜','',body)
    body=re.sub(r'［＃[^］]*］','',body)
    body=re.sub(r'\s','',body)
    return len(body)

def classify(n,is_child,kana):
    old = kana in ("旧字旧仮名","旧字新仮名")
    if is_child:
        return 1 if n<8000 else 2 if n<25000 else 3
    if old:
        return 4 if n<20000 else 5
    return 2 if n<10000 else 3 if n<30000 else 4 if n<80000 else 5

def do_one(b):
    wid=b[idx["作品ID"]]; title=b[idx["作品名"]].strip()
    author=(b[idx["姓"]].strip()+" "+b[idx["名"]].strip()).strip()
    url=b[idx["テキストファイルURL"]]; kana=b[idx["文字遣い種別"]].strip()
    is_child="K913" in b[idx["分類番号"]]
    zpath=os.path.join(DL,f"{wid}.zip")
    try:
        if not os.path.exists(zpath) or os.path.getsize(zpath)<100:
            req=urllib.request.Request(url,headers={"User-Agent":"Mozilla/5.0"})
            with urllib.request.urlopen(req,timeout=60) as resp:
                open(zpath,"wb").write(resp.read())
        # 用系統 unzip
        udd=os.path.join(UNZ,wid)
        os.makedirs(udd,exist_ok=True)
        subprocess.run(["unzip","-o",zpath,"-d",udd],capture_output=True,check=False)
        # 找解出的 txt
        txts=[f for f in os.listdir(udd) if f.endswith(".txt")]
        if not txts: return (wid,title,author,None,"no-txt")
        tp=os.path.join(udd,txts[0])
        txt=open(tp,encoding="shift_jis",errors="replace").read()
        shutil.rmtree(udd,ignore_errors=True)
        n=count_body(txt); tier=classify(n,is_child,kana)
        on=sanitize(f"{wid}_{author}_{title}.txt")
        open(os.path.join(GRADE,f"grade{tier}",on),"w",encoding="utf-8").write(txt)
        return (wid,title,author,tier,n,kana,is_child,url)
    except Exception as e:
        return (wid,title,author,None,0,kana,is_child,url,f"err:{e}")

res=[]
with ThreadPoolExecutor(max_workers=5) as ex:
    futs=[ex.submit(do_one,b) for b in books]
    for i,f in enumerate(as_completed(futs)):
        res.append(f.result())
        if (i+1)%100==0: print(f"  {i+1}/{len(books)}",flush=True)

ok=[r for r in res if r[3] is not None]; bad=[r for r in res if r[3] is None]
print("成功:",len(ok),"失敗:",len(bad))
for r in bad: print("  FAIL",r[0],r[1],r[-1])

tier=Counter(r[3] for r in ok); print("各級:",dict(sorted(tier.items())))

# catalog
with open(CATALOG,"w",encoding="utf-8",newline="") as f:
    w=csv.writer(f)
    w.writerow(["級別","作品ID","作品名","作者","字數","假名種別","児童","URL"])
    for r in sorted(ok,key=lambda x:(x[3],x[1])):
        w.writerow([f"grade{r[3]}",r[0],r[1],r[2],r[4],r[5],"Y" if r[6] else "N",r[7]])
print("catalog:",CATALOG)
# 各 grade 實際檔案數
for g in range(1,6):
    print(f"  grade{g}: {len(os.listdir(os.path.join(GRADE,f'grade{g}')))} files")
print("DONE")
