# -*- coding: utf-8 -*-
"""각 candidate 행의 본문 콘텐츠이미지(필터통과)만 모아 행라벨과 함께 큰 타일 montage 생성."""
import sys,io,os,re,json,warnings
sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
warnings.filterwarnings('ignore')
from playwright.sync_api import sync_playwright
from PIL import Image,ImageDraw,ImageFont
import openpyxl
TEMP=r'D:\01.프로젝트\DB수집\_temp\imgtiles_kead'
os.makedirs(TEMP,exist_ok=True)
plan=json.load(open(r'D:\01.프로젝트\DB수집\_temp\nshot_한국장애인고용공단\plan_한국장애인고용공단.json',encoding='utf-8'))
cands=[p for p in plan if p['auto']=='candidate']
NOISE=re.compile(r'(ico[_\-/]|/icon|logo|btn|bul[_\-]|bg[_\-]|banner|sns|blank|spacer|loading|arrow|/dot|line[_\.]|top_|foot|header|common|_icon|symbol|copyright|qr_|no_img|noimage|share|facebook|insta|twitter|naver|kakao|/skin/|/template/|/resources/|/images/common)',re.I)
JS="""()=>{const out=[];const scope=document.querySelector('#contents,#content,#container,.contents,.content,#sub_content,.sub_content,main')||document.body;
for(const i of scope.querySelectorAll('img')){const r=i.getBoundingClientRect();out.push({src:i.currentSrc||i.src||'',nw:i.naturalWidth,nh:i.naturalHeight,rw:Math.round(r.width),rh:Math.round(r.height),x:Math.round(r.x),y:Math.round(r.y)});}return out;}"""
def good(it):
    s=it['src']
    if not s or NOISE.search(s): return False
    return it['nw']>=170 and it['nh']>=110 and it['rw']>=100 and it['rh']>=80
try:
    fnt=ImageFont.truetype('malgun.ttf',20); fnt2=ImageFont.truetype('malgun.ttf',16)
except: fnt=ImageFont.load_default(); fnt2=fnt
results={}
with sync_playwright() as pw:
    b=pw.chromium.launch()
    pg=b.new_page(viewport={'width':1280,'height':2000})
    for p in cands:
        r=p['row']; url=p['url']
        try:
            pg.goto(url,wait_until='networkidle',timeout=25000)
            imgs=pg.evaluate(JS)
        except Exception as e:
            results[r]={'err':str(e)[:30],'imgs':[]}; continue
        gi=[it for it in imgs if good(it)]
        # screenshot each good image region by element via clip
        crops=[]
        for j,it in enumerate(gi[:4]):
            try:
                if it['rw']<10 or it['rh']<10 or it['y']<0: continue
                clip={'x':max(0,it['x']),'y':max(0,it['y']),'width':min(it['rw'],1200),'height':min(it['rh'],700)}
                path=os.path.join(TEMP,f'r{r}_{j}.png')
                pg.screenshot(path=path,clip=clip)
                crops.append(path)
            except Exception: pass
        results[r]={'n':len(gi),'crops':crops,'N':p['N']}
    b.close()
json.dump({str(k):v for k,v in results.items()},open(os.path.join(TEMP,'_map.json'),'w',encoding='utf-8'),ensure_ascii=False)
# build tiled montages: each row = label + up to 4 crops side by side
rows_sorted=sorted(results.items())
CW,CH=300,200; LBLW=70; GAP=6
def load_thumb(pth):
    try:
        im=Image.open(pth).convert('RGB'); im.thumbnail((CW,CH)); return im
    except: return None
# group 10 rows per montage
import math
page=0
batch=[]
def flush(batch,page):
    if not batch: return
    H=sum(CH+GAP for _ in batch)+GAP
    W=LBLW+(CW+GAP)*4+GAP
    canvas=Image.new('RGB',(W,H),'white'); d=ImageDraw.Draw(canvas)
    y=GAP
    for r,info in batch:
        d.text((4,y+4),f'r{r}',fill='red',font=fnt)
        d.text((4,y+30),f'#{info.get("n",0)}',fill='blue',font=fnt2)
        x=LBLW
        for c in info.get('crops',[]):
            t=load_thumb(c)
            if t: canvas.paste(t,(x,y))
            d.rectangle([x,y,x+CW,y+CH],outline='gray')
            x+=CW+GAP
        y+=CH+GAP
    out=os.path.join(TEMP,f'tiles_{page}.png'); canvas.save(out); print('TILE',out)
for r,info in rows_sorted:
    batch.append((r,info))
    if len(batch)==10:
        flush(batch,page); page+=1; batch=[]
flush(batch,page)
print('done. rows:',len(rows_sorted))
