# -*- coding: utf-8 -*-
import openpyxl, io, os, glob, unicodedata
def norm(v):
    if v in (None,""): return ""
    s=unicodedata.normalize("NFKC",str(v))
    return "".join(s.split())  # 공백/전각 제거 정규화
COLS={3:'C',4:'D',5:'E',6:'F',7:'G',8:'H',9:'I',10:'J'}
out=io.open("_audit_out.txt","w",encoding="utf-8")
def w(*a): out.write(" ".join(str(x) for x in a)+"\n")
total_issues=0
for f in sorted(glob.glob("*.xlsx")):
    if f.startswith("~$"): continue
    wb=openpyxl.load_workbook(f); ws=wb.active; mx=ws.max_row
    # merged membership (single-col)
    mt={}
    for mr in ws.merged_cells.ranges:
        for r in range(mr.min_row,mr.max_row+1):
            for c in range(mr.min_col,mr.max_col+1):
                mt[(r,c)]=(mr.min_row,mr.max_row,mr.min_col,mr.max_col)
    # effective values (fill merges) for parent path
    eff={}
    for r in range(3,mx+1):
        for c in range(3,11): eff[(r,c)]=ws.cell(r,c).value
    for mr in ws.merged_cells.ranges:
        if mr.min_row>=3 and mr.min_col>=3 and mr.max_col<=10:
            v=ws.cell(mr.min_row,mr.min_col).value
            for r in range(mr.min_row,mr.max_row+1):
                for c in range(mr.min_col,mr.max_col+1): eff[(r,c)]=v
    def epar(r,c): return tuple(norm(eff.get((r,cc))) for cc in range(3,c))  # C..c-1
    issues=[]
    # 병합누락: 인접행 같은(정규화)값 + 같은부모 + 한 병합에 안 묶임 (D~J)
    for c in range(4,11):
        r=3
        while r<mx:
            v=norm(ws.cell(r,c).value)
            if v=="":
                r+=1; continue
            # extend run by normalized literal equality + same parent
            r2=r
            while r2+1<=mx and norm(ws.cell(r2+1,c).value)==v and epar(r2+1,c)==epar(r,c):
                r2+=1
            if r2>r:
                # check if [r..r2] is exactly one merge
                m=mt.get((r,c))
                covered = m and m[0]<=r and m[1]>=r2 and m[2]==m[3]==c
                if not covered:
                    issues.append((COLS[c],r,r2,str(ws.cell(r,c).value)))
            r=r2+1
    # 과병합: 한 병합 안에 부모가 서로 다른 행이 섞임 (D~J)
    over=[]
    for mr in ws.merged_cells.ranges:
        if mr.min_row>=3 and mr.min_col==mr.max_col and 4<=mr.min_col<=10:
            c=mr.min_col; pars={epar(r,c) for r in range(mr.min_row,mr.max_row+1)}
            if len(pars)>1: over.append((COLS[c],mr.min_row,mr.max_row))
    if issues or over:
        total_issues+=len(issues)+len(over)
        w("■ %s  병합누락 %d, 과병합 %d"%(f,len(issues),len(over)))
        for (col,r1,r2,val) in issues[:30]:
            w("   [누락] %s%d:%s%d  '%s'"%(col,r1,col,r2,val))
        for (col,r1,r2) in over[:10]:
            w("   [과병합] %s%d:%s%d (부모상이)"%(col,r1,col,r2))
    else:
        w("○ %s  이상없음"%f)
w("\n=== 총 이상 %d건 ==="%total_issues)
out.close(); print("총이상",total_issues)
