# -*- coding: utf-8 -*-
import openpyxl, copy, sys, os, shutil, datetime
sys.stdout.reconfigure(encoding='utf-8')
FN='한국청소년활동진흥원.xlsx'
BASE='https://www.kywa.or.kr'
BLUE='FFBDD7EE'
INST='한국청소년활동진흥원'

wb=openpyxl.load_workbook(FN); ws=wb.active
MAXR=ws.max_row; NCOL=27
merged=list(ws.merged_cells.ranges)
def eff(r,c):
    v=ws.cell(r,c).value
    if v is not None: return v
    for rng in merged:
        if rng.min_row<=r<=rng.max_row and rng.min_col<=c<=rng.max_col:
            return ws.cell(rng.min_row,rng.min_col).value
    return None
def snap(r): return [copy.copy(ws.cell(r,c)._style) for c in range(1,NCOL+1)]
TPL=snap(9)  # a simple page data row

def u(p): return p if p.startswith('http') else BASE+p

# ---- board L/M/N fixes (current row -> (L,M,N)) ; O stays 미부착 ----
BOARD={
 44:('게시판',3683,'어문,이미지'), 45:('게시판',1493,'어문,이미지'), 46:('게시판',286,'어문,이미지'),
 47:('게시판',0,'없음'), 48:('게시판',1080,'어문,이미지'), 49:('게시판',155,'어문,이미지'),
 51:('게시판',3,'어문'), 52:('게시판',5080,'어문,이미지'), 53:('게시판',9,'어문'),
 54:('게시판',10,'어문'), 55:('게시판',24,'어문'), 56:('게시판',3143,'어문'),
 57:('게시판',973,'어문'), 58:('게시판',129,'어문'), 69:('게시판',43,'어문'), 76:('게시판',523,'어문'),
}
# ---- content-tab expansion ----
# r5: fill existing rows 6,7,8 ; set self on r5 at F
R5_FILL={6:('비공개 기준','/management/public_02_002.jsp'),7:('불복구제 제도','/management/public_02_003.jsp'),8:('수수료 안내','/management/public_02_004.jsp')}
R5_SELF=('F','정보공개제도 및 절차')
# parent_row -> (self_label, [(child_label, url), ...])  child col = parent_leaf+1
EXP={
 5: ('정보공개제도 및 절차', []),           # children handled via R5_FILL (existing rows)
 38:('전문연수', [('컨소시엄','/leader/leader1_1_1.jsp')]),
 71:('이사장', [('상임이사','/about/about04_2.jsp'),('청렴감사실','/about/about04_3.jsp'),('기획조정본부','/about/about04_4.jsp'),('경영지원본부','/about/about04_5.jsp'),('활동진흥본부','/about/about04_6.jsp'),('활동안전본부','/about/about04_7.jsp')]),
 79:('부패방지경영시스템', [('부패방지지침','/about/about11_01.jsp'),('반부패·청렴문화 다짐','/about/about11_02.jsp')]),
}

def leafcol(r):
    lc=4
    for c in range(4,11):
        if eff(r,c) not in (None,''): lc=c
    return lc

def base_record(r):
    vals={}
    for c in range(1,NCOL+1):
        vals[c]= eff(r,c) if 4<=c<=10 else ws.cell(r,c).value
    return {'vals':vals,'style':snap(r),'blue':set(),'new':False}

def new_child(path_vals, childcol, label, url, L='페이지', M=1, N='어문', O='미부착'):
    vals={c:None for c in range(1,NCOL+1)}
    vals[3]=INST
    for c in range(4,11): vals[c]=path_vals.get(c)
    vals[childcol]=label; vals[11]=u(url); vals[12]=L; vals[13]=M; vals[14]=N; vals[15]=O
    return {'vals':vals,'style':[copy.copy(s) for s in TPL],'blue':set(range(2,16)),'new':True}

records=[]
for r in range(3,MAXR+1):
    rec=base_record(r)
    # board fix
    if r in BOARD:
        L,M,N=BOARD[r]
        for c,v in ((12,L),(13,M),(14,N)):
            if rec['vals'][c]!=v: rec['vals'][c]=v; rec['blue'].add(c)
    # r5 self + r6/7/8 fill
    if r==5:
        rec['vals'][6]=R5_SELF[1]; rec['blue'].add(6)
    if r in R5_FILL:
        lbl,url=R5_FILL[r]
        rec['vals'][6]=lbl; rec['vals'][11]=u(url); rec['vals'][12]='페이지'; rec['vals'][13]=1; rec['vals'][14]='어문'; rec['vals'][15]='미부착'
        for c in (6,11,12,13,14,15): rec['blue'].add(c)
    records.append(rec)
    # content-tab children (insert after parent)
    if r in EXP and r!=5:
        self_label, children=EXP[r]
        lc=leafcol(r); childcol=lc+1
        rec['vals'][childcol]=self_label; rec['blue'].add(childcol)
        path={c:rec['vals'][c] for c in range(4,11)}; path[childcol]=None
        for (lbl,url) in children:
            pv={c:path.get(c) for c in range(4,11)}
            records.append(new_child(pv,childcol,lbl,url))

print('records:',len(records),'(was',MAXR-2,'data rows)')

# ---- rewrite ----
title=ws.title
hdr={}
for rr in (1,2):
    for c in range(1,NCOL+1):
        cell=ws.cell(rr,c); hdr[(rr,c)]=(cell.value,copy.copy(cell._style))
hdr_merges=[str(m) for m in merged if m.min_row<=2]
colw={k:v.width for k,v in ws.column_dimensions.items()}
del wb[title]; ns=wb.create_sheet(title)
for (rr,c),(v,st) in hdr.items():
    cc=ns.cell(rr,c); cc.value=v; cc._style=st
for m in hdr_merges: ns.merge_cells(m)
for col,w in colw.items():
    if w: ns.column_dimensions[col].width=w
from openpyxl.styles import PatternFill, Font
bluefill=PatternFill(fill_type='solid',fgColor=BLUE,bgColor=BLUE)
linkfont=Font(name='맑은 고딕',size=10,color='0000FF',underline='single')
for i,rec in enumerate(records):
    R=3+i
    for c in range(1,NCOL+1):
        cell=ns.cell(R,c); cell._style=rec['style'][c-1]; cell.value=rec['vals'][c]
    ns.cell(R,2).value=i+1
    kv=rec['vals'][11]
    if kv and isinstance(kv,str) and kv.startswith('http'):
        kc=ns.cell(R,11); kc.hyperlink=kv; kc.font=linkfont
    for c in rec['blue']: ns.cell(R,c).fill=bluefill
# re-merge D..J boundary-aware
D0=3; DN=3+len(records)-1
def val(R,c): return ns.cell(R,c).value
for c in range(4,11):
    R=D0
    while R<=DN:
        v=val(R,c)
        if v in (None,''): R+=1; continue
        r2=R
        while r2+1<=DN and val(r2+1,c)==v and all(val(r2+1,pc)==val(R,pc) for pc in range(4,c)):
            r2+=1
        if r2>R:
            for rr in range(R+1,r2+1): ns.cell(rr,c).value=None
            ns.merge_cells(start_row=R,start_column=c,end_row=r2,end_column=c)
        R=r2+1
ns.freeze_panes='A3'
os.makedirs('_backup',exist_ok=True)
ts=datetime.datetime.fromtimestamp(os.path.getmtime(FN)).strftime('%Y%m%d_%H%M%S')
shutil.copy2(FN,os.path.join('_backup',f'_게시판탭재판정전_{ts}.xlsx'))
wb.save(FN)
print('SAVED rows',DN)
