import sys, io, os, shutil
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
import openpyxl
from openpyxl.styles import Border, Side
from openpyxl.utils import get_column_letter

PKG = r'D:\01.프로젝트\DB수집\작업파일\_제출패키지_2026-06-03\프리랜서1\충청남도_부여군.xlsx'
WRK = r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵\충청남도\7.부여군\충청남도_부여군.xlsx'

THIN = Side(style='thin'); MED = Side(style='medium'); HAIR = Side(style='hair'); NON = Side(style=None)

# per-column base: (left, right, top_default, bottom_default). cols skipped: 4(D),5(E),24(X), 1(A)
COLBASE = {
    2:  (THIN, THIN, THIN, THIN),   # B
    3:  (THIN, THIN, THIN, NON),    # C (bottom None per 233/observed)
    8:  (THIN, THIN, THIN, THIN),   # H
    9:  (THIN, THIN, THIN, THIN),   # I
    10: (THIN, THIN, THIN, THIN),   # J
    11: (THIN, THIN, THIN, THIN),   # K
    12: (THIN, THIN, THIN, THIN),   # L
    13: (THIN, THIN, THIN, THIN),   # M
    14: (THIN, THIN, THIN, THIN),   # N
    15: (THIN, THIN, THIN, THIN),   # O
    16: (THIN, THIN, THIN, THIN),   # P
    17: (THIN, THIN, THIN, THIN),   # Q
    18: (THIN, NON,  THIN, THIN),   # R (right None)
    19: (MED,  THIN, THIN, THIN),   # S (left medium)
    20: (THIN, THIN, THIN, THIN),   # T
    21: (THIN, THIN, THIN, THIN),   # U
    22: (THIN, THIN, THIN, THIN),   # V
    23: (THIN, MED,  THIN, THIN),   # W (right medium)
    25: (MED,  THIN, HAIR, HAIR),   # Y (left medium, hair T/B)
    26: (NON,  NON,  HAIR, HAIR),   # Z (no L/R, hair T/B)
    27: (THIN, MED,  HAIR, HAIR),   # AA (right medium, hair T/B)
}
BOXED = {6, 7}  # F, G : left/right thin, top/bottom only on merge edges

def apply(path):
    BK = path.replace('.xlsx', '_backup_테두리보정전.xlsx')
    # restore pristine pre-border baseline (heights already normalized in this backup)
    shutil.copy2(BK, path)
    wb = openpyxl.load_workbook(path); ws = wb.active
    maxr = ws.max_row

    # snapshot F,G vertical merges, then unmerge so we can border interior cells
    fg_merges = [(m.min_col, m.min_row, m.max_row) for m in ws.merged_cells.ranges
                 if m.min_col in BOXED and m.min_col == m.max_col and m.min_row >= 3]
    for col, a, z in fg_merges:
        ws.unmerge_cells(start_row=a, start_column=col, end_row=z, end_column=col)
    # membership lookup: (col,row) -> (a,z)
    span = {}
    for col, a, z in fg_merges:
        for r in range(a, z + 1):
            span[(col, r)] = (a, z)

    for r in range(3, maxr + 1):
        # grid columns
        for c, (L, R, T, B) in COLBASE.items():
            ws.cell(r, c).border = Border(left=L, right=R, top=T, bottom=B)
        # boxed F,G
        for c in (6, 7):
            if (c, r) in span:
                a, z = span[(c, r)]
                T = THIN if r == a else NON
                B = THIN if r == z else NON
            else:
                T = THIN; B = THIN
            ws.cell(r, c).border = Border(left=THIN, right=THIN, top=T, bottom=B)

    # re-merge F,G
    for col, a, z in fg_merges:
        ws.merge_cells(start_row=a, start_column=col, end_row=z, end_column=col)

    wb.save(path)
    print(f'{os.path.basename(path)}: 그리드 재적용 rows 3-{maxr}, F/G박스 {len(fg_merges)}개 재병합')

for p in (PKG, WRK):
    apply(p)

# ---- verify ----
ws = openpyxl.load_workbook(PKG).active
def s(cell):
    b=cell.border; f=lambda x:(x.style or '-')[:4]
    return f'{f(b.left)}/{f(b.right)}/{f(b.top)}/{f(b.bottom)}'
print('\n=== verify rows 551/552/568 F,G,K,W ===')
for r in (551,552,568):
    print(f'  r{r}: F={s(ws.cell(r,6))} G={s(ws.cell(r,7))} K={s(ws.cell(r,11))} W={s(ws.cell(r,23))}')
print('\n=== previously-broken F merges now boxed? ===')
for (a,z,nm) in [(449,457,'여성/다문화'),(504,510,'상수도안내'),(537,547,'자연재난'),(565,567,'찾아가는정보화')]:
    print(f'  F{a}(anchor)={s(ws.cell(a,6))}  F{z}(last)={s(ws.cell(z,6))}  [{nm}]')
print('\nE/D untouched sample: D551=',s(ws.cell(551,4)),' E551=',s(ws.cell(551,5)))
