import openpyxl, json, sys, os, shutil, time
from copy import copy
from openpyxl.styles import PatternFill
from openpyxl.utils import get_column_letter
sys.stdout.reconfigure(encoding='utf-8')
P=r'작업파일/공공기관2/12.한국철도공사/한국철도공사.xlsx'
BASE='https://info.korail.com'
BLUE=PatternFill(fill_type='solid', fgColor='FFBDD7EE', bgColor='FFBDD7EE')
ts=json.load(open(r'작업파일/공공기관2/12.한국철도공사/_tabscan.json',encoding='utf-8'))

EXPAND=[6,8,15,30,33,34,37,38,39,40,45,46,47,74,78,79,80,82,86,92,93,94,102,104,105,106]
IMG=set('719 720 730 769 781 783 785 799 871 872 894 899 900 901 902 906 907 908 970 2950 2951 2952 2977 1461 1462 1463 1464 1641 1303 1541 1503 1504 2730 1505 2731 1507 1508 2732 1510 1511'.split())
def nfor(key):
    return '어문,이미지' if str(key) in IMG else '어문'

mt0=os.path.getmtime(P)
shutil.copy2(P, P.replace('.xlsx', f'_backup_{int(mt0)}.xlsx'))
wb=openpyxl.load_workbook(P)
ws=wb.active

# merge-fill map cols 4-10
fill={}
for m in list(ws.merged_cells.ranges):
    v=ws.cell(m.min_row,m.min_col).value
    for rr in range(m.min_row,m.max_row+1):
        for cc in range(m.min_col,m.max_col+1):
            fill[(rr,cc)]=v
def eff(r,c):
    return fill.get((r,c), ws.cell(r,c).value)

# capture template styles per column from a clean data row (row 4)
TPL={}
for c in range(2,28):
    cell=ws.cell(4,c)
    TPL[c]=(copy(cell.font),copy(cell.border),copy(cell.fill),copy(cell.alignment),copy(cell.number_format))
# K hyperlink template style (font/color)
KSTYLE=(copy(ws.cell(3,11).font),copy(ws.cell(3,11).border),copy(ws.cell(3,11).fill),copy(ws.cell(3,11).alignment))

Cval=ws.cell(3,3).value  # 사이트명

# Build records: list of dicts col->value, plus 'blue' set of cols, plus 'hl' url
records=[]
for r in range(3, ws.max_row+1):
    base={}
    for c in range(3,28):  # C..AA (B renumbered later)
        if 4<=c<=10:
            base[c]=eff(r,c)
        else:
            base[c]=ws.cell(r,c).value
    hl=ws.cell(r,11).hyperlink.target if ws.cell(r,11).hyperlink else (base[11] if base[11] else None)
    if r in EXPAND:
        leafcol=6  # F
        tabs=ts[str(r)]['tabs']
        # self tab = active (first); reuse this row but add G label + url stays
        for i,t in enumerate(tabs):
            rec=dict(base)
            key=t['href'].split('key=')[-1]
            url=BASE+t['href']
            rec[7]=t['label']  # G
            rec[11]=url        # K value
            rec['_hl']=url
            rec[12]='페이지'    # L
            rec[13]=1           # M
            rec[14]=nfor(key)   # N
            rec[15]='미부착'    # O
            rec['_blue']={7,11,12,13,14,15}
            if i>0:
                # new row: clear D,E,F values (merge covers) - keep for run-length; keep eff values
                rec[16]=None; rec[17]=None  # P,Q clear for new
                for cc in range(18,28): rec[cc]=None  # R-AA clear
            records.append(rec)
    else:
        rec=dict(base); rec['_hl']=hl; rec['_blue']=set()
        records.append(rec)

# Now rewrite sheet: clear merges + data region
for m in list(ws.merged_cells.ranges):
    ws.unmerge_cells(str(m))
maxr=ws.max_row
for r in range(3, maxr+1):
    for c in range(1,28):
        cell=ws.cell(r,c); cell.value=None; cell.hyperlink=None

# write records
import re
for idx,rec in enumerate(records):
    r=3+idx
    ws.cell(r,2).value=idx+1  # B renumber
    # apply template style to all cols
    for c in range(2,28):
        f,b,fl,al,nf=TPL[c]
        cell=ws.cell(r,c)
        cell.font=copy(f); cell.border=copy(b); cell.fill=copy(fl); cell.alignment=copy(al); cell.number_format=nf
    for c in range(3,28):
        ws.cell(r,c).value=rec.get(c)
    # K hyperlink
    url=rec.get('_hl')
    if url and isinstance(url,str) and url.startswith('http'):
        kc=ws.cell(r,11)
        kc.hyperlink=url
        kf,kb,kfl,kal=KSTYLE
        kc.font=copy(kf)
    # blue highlights
    for c in rec.get('_blue',()):
        ws.cell(r,c).fill=copy(BLUE)

nrows=len(records)
last=3+nrows-1

# snapshot of effective values BEFORE merging (merged cells read back as None)
SNAP={}
for idx,rec in enumerate(records):
    rr=3+idx
    for c in range(4,11):
        SNAP[(rr,c)]=rec.get(c)
# run-length merges for cols D(4)..J(10)
def val(r,c): return SNAP.get((r,c))
for c in range(4,11):
    r=3
    while r<=last:
        v=val(r,c)
        if v is None:
            r+=1; continue
        # ancestor tuple
        def anctup(rr):
            return tuple(val(rr,cc) for cc in range(4,c))
        a0=anctup(r)
        r2=r
        while r2+1<=last and val(r2+1,c)==v and anctup(r2+1)==a0:
            r2+=1
        if r2>r:
            ws.merge_cells(start_row=r,start_column=c,end_row=r2,end_column=c)
        r=r2+1

# mtime guard + save
if os.path.getmtime(P)!=mt0:
    print('ABORT mtime moved'); sys.exit(2)
try:
    wb.save(P)
except PermissionError as e:
    print('ABORT-PERM (close Excel)', e); sys.exit(3)
print('OK rows', nrows, '(was', maxr-2, ') new', nrows-(maxr-2))
