# -*- coding: utf-8 -*-
import openpyxl, copy, sys, shutil, os, datetime
from openpyxl.utils import get_column_letter
sys.stdout.reconfigure(encoding='utf-8')

FN = '한국청소년상담복지개발원.xlsx'
BASE = 'https://www.kyci.or.kr'
BLUE = 'FFBDD7EE'

wb = openpyxl.load_workbook(FN)
ws = wb.active
MAXR = ws.max_row
NCOL = 27  # up to AA

# ---- resolve merged effective values ----
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

# capture style snapshots for original rows
def snap(r):
    return [copy.copy(ws.cell(r, c)._style) for c in range(1, NCOL+1)]

# template data-row style = row 3
TPL = snap(3)

# ---- build flat records for rows 3..MAXR ----
# record = dict: vals[1..27] (1-indexed col -> value), style list, blue set (cols to paint blue), is_new
def base_record(r):
    vals = {}
    for c in range(1, NCOL+1):
        if 4 <= c <= 10:           # D..J use effective (merge-resolved)
            vals[c] = eff(r, c)
        else:
            vals[c] = ws.cell(r, c).value
    return {'vals': vals, 'style': snap(r), 'blue': set(), 'new': False}

def new_record(path_vals, leafcol, label, url, L, M, N, O, ext=False):
    vals = {c: None for c in range(1, NCOL+1)}
    vals[3] = '한국청소년상담복지개발원'      # C
    for c in range(4, 11):
        vals[c] = path_vals.get(c)            # inherit D..J path
    vals[leafcol] = label
    vals[11] = url                            # K
    vals[12] = L
    vals[13] = M
    vals[14] = N
    vals[15] = O
    rec = {'vals': vals, 'style': [copy.copy(s) for s in TPL], 'blue': set(), 'new': True}
    rec['blue'] = set(range(2, 16))           # B..O painted blue for new rows
    return rec

# ---- expansion definitions (keyed by original sheet row) ----
def u(p):
    if p.startswith('http'): return p
    return BASE + p

# children: (label, url, L, M, N, O)
EXP = {
 14: ('E', '사업소개', [('사업개요','/userSite/sub02_1_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_1_cont.asp','페이지',1,'어문','미부착')]),
 15: ('E', '사업소개', [('사업개요','/userSite/sub02_14_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_14_cont.asp','페이지',1,'어문','미부착')]),
 16: ('E', '사업소개', [('사업개요','/userSite/sub02_2_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_2_cont.asp','페이지',1,'어문','미부착'),
                        ('홍보자료','/userSite/sub02_2_gallery.asp','페이지',1,'어문,이미지','미부착')]),
 17: ('E', '사업소개', [('사업개요','/userSite/sub02_3_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_3_cont.asp','페이지',1,'어문','미부착'),
                        ('홍보자료','/userSite/sub02_3_gallery.asp','페이지',1,'어문,이미지','미부착'),
                        ('자료실','/userSite/sub02_3_file.asp','페이지',1,'어문','미부착')]),
 18: ('E', '사업소개', [('사업개요','/userSite/sub02_4_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_4_cont.asp','페이지',1,'어문','미부착'),
                        ('자료실','/userSite/sub02_4_file.asp','페이지',1,'어문','미부착')]),
 19: ('E', '사업소개', [('사업개요','/userSite/sub02_6_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_6_cont.asp','페이지',1,'어문','미부착'),
                        ('심리검사','/userSite/sub02_6_test.asp','페이지',1,'어문','미부착'),
                        ('홍보자료','/userSite/sub02_6_gallery.asp','페이지',1,'어문,이미지','미부착')]),
 20: ('E', '사업소개', [('사업개요','/userSite/sub02_7_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_7_cont.asp','페이지',1,'어문','미부착')]),
 21: ('E', '사업소개', [('사업개요','/userSite/sub02_8_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_8_cont.asp','페이지',1,'어문','미부착')]),
 22: ('E', '사업소개', [('사업개요','/userSite/sub02_10_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_10_cont.asp','페이지',1,'어문,이미지','미부착')]),
 23: ('E', '사업소개', [('사업개요','/userSite/sub02_11_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_11_cont.asp','페이지',1,'어문','미부착'),
                        ('권리교육 관련 자료','https://edu.kyci.or.kr/community/edu_files.asp','사이트',None,None,None)]),
 24: ('E', '사업소개', [('사업개요','/userSite/sub02_13_info.asp','페이지',1,'어문','미부착'),
                        ('주요내용','/userSite/sub02_13_cont.asp','페이지',1,'어문','미부착'),
                        ('홍보자료','/userSite/sub02_13_gallery.asp','페이지',1,'어문,이미지','미부착')]),
 45: ('E', '정보공개 제도란?', [
        ('제도의 필요성','/userSite/sub06_1_2.asp','페이지',1,'어문','미부착'),
        ('정보공개제도 도입배경','/userSite/sub06_1_3.asp','페이지',1,'어문','미부착'),
        ('정보공개 청구권자','/userSite/sub06_1_4.asp','페이지',1,'어문','미부착'),
        ('공공기관과 청구인의 의무','/userSite/sub06_1_5.asp','페이지',1,'어문','미부착'),
        ('정보공개 처리절차','/userSite/sub06_1_6.asp','페이지',1,'어문','미부착'),
        ('정보공개 방법','/userSite/sub06_1_7.asp','페이지',1,'어문','미부착'),
        ('정보공개 수수료','/userSite/sub06_1_8.asp','페이지',1,'어문','미부착'),
        ('불복구제 절차','/userSite/sub06_1_9.asp','페이지',1,'어문','미부착'),
        ('정보공개 대상 정보와 비공개 정보','/userSite/sub06_1_10.asp','페이지',1,'어문','미부착'),
        ('관련 법령','/boardManagement/Board.asp?bid=bid_35','게시판',3,'어문','미부착'),
        ('청구 서식','/boardManagement/Board.asp?bid=bid_36','게시판',6,'어문','미부착')]),
 52: ('E', '입찰정보', [('계약현황','/boardManagement/board.asp?bid=bid_6&menuCategory=6','게시판',580,'어문','미부착')]),
 77: ('F', '상담직', [('행정직','/userSite/sub060304-2.asp','페이지',1,'어문','미부착'),
                      ('운전직','/userSite/sub060304-3.asp','페이지',1,'어문','미부착')]),
}
COLIDX = {'D':4,'E':5,'F':6,'G':7,'H':8,'I':9,'J':10}
# self-row L/M corrections (입찰정보 is a board, existing was 페이지/1)
SELF_FIX = {52: {12:'게시판', 13:175}}

records = []
for r in range(3, MAXR+1):
    rec = base_record(r)
    if r in EXP:
        leafletter, self_label, children = EXP[r]
        leafcol = COLIDX[leafletter]
        childcol = leafcol + 1
        # set self label on the existing row at leaf+1
        rec['vals'][childcol] = self_label
        rec['blue'].add(childcol)
        if r in SELF_FIX:
            for c, v in SELF_FIX[r].items():
                rec['vals'][c] = v
                rec['blue'].add(c)
        path = {c: rec['vals'][c] for c in range(4, 11)}   # D..J of parent
        path[childcol] = None   # children carry parent path up to leafcol only
        records.append(rec)
        for (label, url, L, M, N, O) in children:
            pv = {c: path.get(c) for c in range(4, 11)}
            records.append(new_record(pv, childcol, label, u(url), L, M, N, O))
    else:
        records.append(rec)

print('original data rows:', MAXR-2, '-> new total:', len(records))

# ---- write to fresh sheet ----
title = ws.title
# copy header rows 1..2 first
hdr = {}
for r in (1,2):
    for c in range(1, NCOL+1):
        cell = ws.cell(r, c)
        hdr[(r,c)] = (cell.value, copy.copy(cell._style))
hdr_merges = [str(rng) for rng in merged if rng.min_row <= 2]
colwidths = {k: v.width for k, v in ws.column_dimensions.items()}

del wb[title]
ns = wb.create_sheet(title)
wb.move_sheet(title, -(len(wb.sheetnames)-1))

# header
for (r,c),(v,st) in hdr.items():
    cc = ns.cell(r, c); cc.value = v; cc._style = st
for m in hdr_merges:
    ns.merge_cells(m)
for col, w in colwidths.items():
    if w: ns.column_dimensions[col].width = w

# data
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]
    # B renumber continuous
    ns.cell(R, 2).value = i + 1
    # K hyperlink
    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
    # blue paint
    for c in rec['blue']:
        ns.cell(R, c).fill = bluefill

# ---- re-merge D..J by boundary-aware equal runs ----
DATA0 = 3
DATAN = 3 + len(records) - 1
def val(R, c):
    return ns.cell(R, c).value
for c in range(4, 11):   # D..J
    R = DATA0
    while R <= DATAN:
        v = val(R, c)
        if v is None or v == '':
            R += 1; continue
        r2 = R
        while r2+1 <= DATAN 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

# freeze panes
ns.freeze_panes = 'A3'

# ---- save with backup ----
bdir = '_backup'
os.makedirs(bdir, exist_ok=True)
ts = datetime.datetime.fromtimestamp(os.path.getmtime(FN)).strftime('%Y%m%d_%H%M%S')
shutil.copy2(FN, os.path.join(bdir, f'_탭전개전_{ts}.xlsx'))
wb.save(FN)
print('SAVED', FN, 'rows', DATAN)
