# -*- coding: utf-8 -*-
"""Full rebuild of 한국의료분쟁조정중재원 with tab-expanded authoritative tree."""
import openpyxl, copy, re, sys
sys.stdout.reconfigure(encoding='utf-8')
from openpyxl.utils import get_column_letter

SRC='2.한국의료분쟁조정중재원/한국의료분쟁조정중재원.xlsx'
BASE='https://www.k-medi.or.kr'
def U(p): return p if p.startswith('http') else BASE+p

wbo=openpyxl.load_workbook(SRC); wso=wbo.active
exist={}
for r in range(3,80):
    k=wso.cell(r,11).value
    if not k: continue
    key=k.replace(BASE,'').split('#')[0].rstrip('?')
    exist[key]={'L':wso.cell(r,12).value,'M':wso.cell(r,13).value,'N':wso.cell(r,14).value,
                'O':wso.cell(r,15).value,'P':wso.cell(r,16).value,'Q':wso.cell(r,17).value,'url':k}

NEW='__NEW__'
T=[
 (1,'의료분쟁상담','/web/lay1/S1T1C8/sublink.do'),
 (2,'상담안내','/web/lay1/S1T8C17/contents.do'),
 (2,'자주묻는질문','/web/lay1/bbs/S1T8C69/E/21/list.do'),
 (1,'의료분쟁 조정/중재','/web/lay1/S1T1C9/sublink.do'),
 (2,'제도안내','/web/lay1/S1T9C130/sublink.do'),
 (3,'제도소개','/web/lay1/S1T130C154/contents.do'),
 (3,'감정 절차 안내','/web/lay1/S1T130C909/contents.do'),
 (3,'조정 절차 안내','/web/lay1/S1T155C243/contents.do'),
 (3,'중재 절차 안내','/web/lay1/S1T155C244/contents.do'),
 (2,'조정신청','/web/lay1/S1T9C132/sublink.do'),
 (3,'조정신청 방법','/web/lay1/S1T132C158/contents.do',NEW,'페이지',1),
 (3,'필수제출 서류(환자)','/web/lay1/S1T132C156/contents.do',NEW,'페이지',1),
 (3,'필수제출 서류(의료기관)','/web/lay1/S1T130C989/contents.do',NEW,'페이지',1),
 (3,'수수료','/web/lay1/S1T132C157/contents.do',NEW,'페이지',1),
 (3,'신청내역 조회','/web/lay1/program/S1T132C159/adjustment/list.do',NEW,'페이지',1),
 (2,'신청서식','/web/lay1/S1T9C133/sublink.do'),
 (3,'조정신청 서식','/web/lay1/S1T133C878/contents.do'),
 (3,'중재신청 서식','/web/lay1/S1T133C879/contents.do'),
 (3,'이의신청 서식','/web/lay1/S1T133C880/contents.do'),
 (3,'기타 서식','/web/lay1/S1T133C881/contents.do'),
 (2,'나의사건조회','/web/lay1/program/S1T132C160/incident/index.do'),
 (1,'수탁감정','/web/lay1/S1T1C12/sublink.do'),
 (2,'제도 소개','/web/lay1/S1T12C229/contents.do'),
 (2,'수탁감정 의뢰(서식)','/web/lay1/S1T12C1128/contents.do'),
 (2,'수탁감정 처리 흐름도','/web/lay1/S1T228C230/contents.do'),
 (2,'수탁감정 시행','/web/lay1/S1T228C231/contents.do'),
 (2,'수탁사건 조회','/web/lay1/program/S1T12C628/trust/index.do'),
 (2,'수탁감정제도 이용 안내서','/web/lay1/bbs/S1T27C1148/A/26/view.do?article_seq=12582&cpage=1&rows=10'),
 (1,'손해배상금 대불','/web/lay1/S1T1C867/sublink.do'),
 (2,'손해배상금 대불제도란?','/web/lay1/S1T867C868/contents.do'),
 (2,'대불 청구 및 심사','/web/lay1/S1T867C869/sublink.do'),
 (3,'대불청구 방법','/web/lay1/S1T869C873/contents.do',NEW,'페이지',1),
 (3,'대불청구 심사절차','/web/lay1/S1T869C874/contents.do',NEW,'페이지',1),
 (2,'대불비용 부담액','/web/lay1/S1T867C870/sublink.do'),
 (3,'부담액 부과·징수','/web/lay1/S1T870C875/contents.do',NEW,'페이지',1),
 (3,'부담액 조회','/web/lay1/program/S1T870C876/burden/index.do',NEW,'페이지',1),
 (3,'부담액 반환','/web/lay1/S1T870C877/contents.do',NEW,'페이지',1),
 (2,'대불금의 상환','/web/lay1/S1T867C871/contents.do'),
 (2,'관련 법령 및 서식','/web/lay1/S1T867C872/contents.do'),
 (1,'불가항력 의료사고 보상','/web/lay1/S1T1C856/sublink.do'),
 (2,'불가항력 의료사고 보상제도란?','/web/lay1/S1T856C857/contents.do'),
 (2,'보상 청구 및 심사','/web/lay1/S1T856C858/sublink.do'),
 (3,'보상청구 방법','/web/lay1/S1T858C863/contents.do',NEW,'페이지',1),
 (3,'보상청구 심사절차','/web/lay1/S1T858C864/contents.do',NEW,'페이지',1),
 (2,'보상 심의기준','/web/lay1/S1T856C1168/contents.do'),
 (2,'불가항력 의료사고 보상 사례','/web/lay1/program/S1T856C860/indemnification/list.do'),
 (2,'자주 묻는 질문','/web/lay1/bbs/S1T856C861/E/190/list.do'),
 (2,'관련 법령 및 서식','/web/lay1/bbs/S1T856C862/E/183/list.do'),
 (1,'의료사고예방','/web/lay1/S1T1C114/sublink.do'),
 (2,'업무소개','/web/lay1/S1T114C115/contents.do'),
 (2,'의료사고예방위원회','/web/lay1/S1T114C116/contents.do'),
 (2,'의료사고예방 소식지','/web/lay1/S1T114C119/sublink.do'),
 (3,'정기간행물(MAP)','/web/lay1/bbs/S1T119C689/B/189/list.do',NEW,'게시판',32),
 (3,'정기간행물(MAP_EBOOK)','/web/lay1/bbs/S1T119C850/A/184/list.do',NEW,'게시판',4),
 (3,'비 정기간행물','/web/lay1/bbs/S1T119C708/A/123/list.do',NEW,'게시판',29),
 (2,'교육/세미나 신청','/web/lay1/S1T114C248/sublink.do'),
 (3,'교육 신청','/web/lay1/program/S1T248C648/education/index.do',NEW,'페이지',1),
 (3,'정기 온라인 동영상 교육','/web/lay1/program/S1T248C31/seminar/list.do',NEW,'게시판',0),
 (1,'알림마당','/web/lay1/S1T1C13/sublink.do'),
 (2,'공지사항','/web/lay1/bbs/S1T13C18/A/1/list.do'),
 (2,'보도자료','/web/lay1/bbs/S1T13C24/A/2/list.do'),
 (2,'신고센터','/web/lay1/S1T13C29/sublink.do'),
 (3,'국민신문고','/web/lay1/S1T29C422/sublink.do'),
 (4,'민원신청','/web/lay1/program/S1T422C423/epeople/write.do',NEW,'페이지',1),
 (4,'나의민원확인','/web/lay1/program/S1T422C424/epeople/list.do',NEW,'페이지',1),
 (3,'부조리신고','/web/lay1/program/S1T29C149/irrationality/index.do'),
 (3,'청탁금지법 위반 신고','/web/lay1/S1T29C150/contents.do'),
 (2,'입찰공고','/web/lay1/bbs/S1T13C26/A/23/list.do'),
 (2,'칭찬합시다','/web/lay1/program/S1T13C30/compliment/list.do'),
 (2,'채용정보','/web/lay1/bbs/S1T13C148/A/47/list.do'),
 (2,'자료실','/web/lay1/S1T13C27/sublink.do'),
 (3,'정기간행물','/web/lay1/bbs/S1T27C96/A/25/list.do'),
 (3,'의료분쟁 사례','/web/lay1/S1T27C118/sublink.do'),
 (4,'조정중재사례','/web/lay1/program/S1T118C291/dispute/list.do',NEW,'게시판',630),
 (4,'감정사례와 예방 TIP','/web/lay1/bbs/S1T118C124/A/89/list.do',NEW,'게시판',269),
 (4,'상담사례','/web/lay1/program/S1T118C1048/advice/list.do',NEW,'게시판',443),
 (3,'일반 자료실','/web/lay1/bbs/S1T27C1148/A/26/list.do'),
 (2,'정보공개','/web/lay1/S1T13C14/sublink.do'),
 (3,'정보공개제도안내','/web/lay1/S1T14C87/contents.do'),
 (3,'업무흐름도','/web/lay1/S1T14C88/contents.do'),
 (3,'정보공개 수수료','/web/lay1/S1T14C89/contents.do'),
 (3,'비공개대상정보','/web/lay1/S1T14C92/contents.do'),
 (3,'정보공개청구','/web/lay1/S1T14C93/contents.do'),
 (3,'공공데이터 개방 및 수요조사 채널','/web/lay1/bbs/S1T14C949/C/221/list.do'),
 (3,'경영공시','/web/lay1/S1T14C95/sublink.do'),
 (4,'사업실명제','/web/lay1/bbs/S1T95C91/A/45/list.do',NEW,'게시판',183),
 (4,'기관장 업무추진비','/web/lay1/bbs/S1T95C452/A/102/list.do',NEW,'게시판',150),
 (4,'친인척 신규채용인원 공개','/web/lay1/bbs/S1T95C768/A/141/list.do',NEW,'게시판',25),
 (4,'상품권 구매 및 사용내역','/web/lay1/bbs/S1T95C852/A/185/list.do',NEW,'게시판',22),
 (1,'의료중재원 소개','/web/lay1/S1T1C15/sublink.do'),
 (2,'기관소개','/web/lay1/S1T15C98/sublink.do'),
 (3,'미션 및 비전','/web/lay1/S1T98C170/contents.do',NEW,'페이지',1),
 (3,'CI','/web/lay1/S1T98C173/contents.do',NEW,'페이지',1),
 (3,'캐릭터','/web/lay1/S1T98C174/contents.do',NEW,'페이지',1),
 (3,'원훈','/web/lay1/S1T98C172/contents.do',NEW,'페이지',1),
 (2,'윤리경영','/web/lay1/S1T15C103/sublink.do'),
 (3,'윤리경영 개요','/web/lay1/S1T103C234/sublink.do'),
 (4,'기관장 청렴·윤리경영 메시지','/web/lay1/S1T234C490/contents.do',NEW,'페이지',1),
 (4,'윤리경영 개요','/web/lay1/S1T234C489/contents.do',NEW,'페이지',1),
 (3,'윤리헌장','/web/lay1/S1T103C175/sublink.do'),
 (4,'윤리헌장','/web/lay1/S1T175C235/contents.do',NEW,'페이지',1),
 (4,'윤리규범','/web/lay1/S1T175C233/contents.do',NEW,'페이지',1),
 (4,'청탁금지법 준수ㆍ청렴서약서','/web/lay1/S1T175C176/contents.do',NEW,'페이지',1),
 (3,'윤리경영 실천','/web/lay1/S1T103C236/sublink.do'),
 (4,'윤리경영 실천','/web/lay1/S1T236C237/contents.do',NEW,'페이지',1),
 (4,'윤리경영 소식','/web/lay1/bbs/S1T236C488/A/121/list.do',NEW,'게시판',141),
 (4,'신고센터','/web/lay1/S1T236C238/contents.do',NEW,'페이지',1),
 (2,'인사말','/web/lay1/S1T15C99/contents.do'),
 (2,'인권경영','/web/lay1/S1T15C588/sublink.do'),
 (3,'인권경영 헌장','/web/lay1/bbs/S1T588C788/A/161/list.do',NEW,'게시판',1),
 (3,'인권경영 주요활동','/web/lay1/bbs/S1T588C789/A/162/list.do',NEW,'게시판',5),
 (2,'연혁','/web/lay1/S1T15C100/contents.do'),
 (2,'조직도','/web/lay1/program/S1T15C101/staff/org_chart/list.do'),
 (2,'업무소개','/web/lay1/S1T15C102/contents.do'),
 (2,'고객헌장','/web/lay1/S1T15C104/contents.do'),
 (2,'홍보관','/web/lay1/S1T15C105/sublink.do'),
 (3,'홍보영상','/web/lay1/bbs/S1T105C853/G/186/list.do',NEW,'게시판',24),
 (3,'카드뉴스','/web/lay1/bbs/S1T105C854/G/187/list.do',NEW,'게시판',10),
 (3,'웹툰','/web/lay1/bbs/S1T105C855/B/188/list.do',NEW,'게시판',3),
 (3,'공모전 수상작','/web/lay1/bbs/S1T105C129/B/101/list.do',NEW,'게시판',19),
 (2,'찾아오시는길','/web/lay1/S1T15C106/sublink.do'),
 (3,'서울본원','/web/lay1/S1T106C508/contents.do',NEW,'페이지',1),
 (3,'부산지원','/web/lay1/S1T106C509/contents.do',NEW,'페이지',1),
]

# N override for new rows, keyed by path (S-code identifies node)
NOVR={
 'S1T132C158':'어문',        # 조정신청 방법 (흐름도)
 'S1T132C156':'어문',        # 필수제출(환자)
 'S1T130C989':'어문',        # 필수제출(의료기관)
 'S1T132C157':'어문',        # 수수료
 'S1T132C159':'어문',        # 신청내역 조회
 'S1T869C873':'어문',        # 대불청구 방법
 'S1T869C874':'어문',        # 대불청구 심사절차
 'S1T870C875':'어문',        # 부담액 부과·징수 (절차도)
 'S1T870C876':'어문',        # 부담액 조회
 'S1T870C877':'어문',        # 부담액 반환 (절차도)
 'S1T858C863':'어문',        # 보상청구 방법
 'S1T858C864':'어문',        # 보상청구 심사절차
 'S1T119C689':'어문,이미지',  # 정기간행물(MAP) 표지썸네일
 'S1T119C850':'어문,이미지',  # 정기간행물(MAP_EBOOK)
 'S1T119C708':'어문,이미지',  # 비 정기간행물
 'S1T248C648':'어문,이미지',  # 교육 신청 (실사진)
 'S1T248C31':'어문,영상',     # 정기 온라인 동영상 교육
 'S1T422C423':'어문',        # 민원신청
 'S1T422C424':'어문',        # 나의민원확인
 'S1T118C291':'어문',        # 조정중재사례
 'S1T118C124':'어문',        # 감정사례와 예방 TIP
 'S1T118C1048':'어문',       # 상담사례
 'S1T95C91':'어문',          # 사업실명제
 'S1T95C452':'어문',         # 기관장 업무추진비
 'S1T95C768':'어문',         # 친인척 신규채용
 'S1T95C852':'어문',         # 상품권 구매
 'S1T98C170':'어문',         # 미션 및 비전 (아이콘)
 'S1T98C173':'어문,이미지',   # CI (심벌)
 'S1T98C174':'어문,이미지',   # 캐릭터 (마스코트)
 'S1T98C172':'어문',         # 원훈 (글자이미지)
 'S1T234C490':'어문',        # 기관장 청렴·윤리경영 메시지
 'S1T234C489':'어문',        # 윤리경영 개요 (인포그래픽)
 'S1T175C235':'어문',        # 윤리헌장
 'S1T175C233':'어문',        # 윤리규범
 'S1T175C176':'어문',        # 청탁금지법 서약서
 'S1T236C237':'어문,이미지',  # 윤리경영 실천 (실사진)
 'S1T236C488':'어문',        # 윤리경영 소식
 'S1T236C238':'어문,이미지',  # 신고센터 (실사진)
 'S1T588C788':'어문',        # 인권경영 헌장
 'S1T588C789':'어문',        # 인권경영 주요활동
 'S1T105C853':'어문,영상',    # 홍보영상 (youtube)
 'S1T105C854':'어문,이미지',  # 카드뉴스
 'S1T105C855':'어문,이미지',  # 웹툰
 'S1T105C129':'어문,이미지',  # 공모전 수상작
 'S1T106C508':'어문',        # 서울본원 (지도위젯)
 'S1T106C509':'어문',        # 부산지원 (지도위젯)
}
def scode(path):
    m=re.search(r'(S1T\d+C\d+)',path); return m.group(1) if m else None

INST='한국의료분쟁조정중재원'
recs=[]
for t in T:
    depth,label,path=t[0],t[1],t[2]
    isnew=len(t)>3 and t[3]==NEW
    key=path.split('#')[0].rstrip('?')
    if not isnew and key in exist:
        e=exist[key]; L,M,N,O,P,Q=e['L'],e['M'],e['N'],e['O'],e['P'],e['Q']; url=e['url']
    else:
        url=U(path)
        if isnew:
            L=t[4]; M=t[5]
            sc=scode(path); N=NOVR.get(sc,'어문')
            O='미부착'; P=('게시물' if L=='페이지' else '게시판'); Q=''
        else:
            L='페이지'; M=1; N='TBD'; O='미부착'; P='게시물'; Q=''
    recs.append({'d':depth,'label':label,'url':url,'L':L,'M':M,'N':N,'O':O,'P':P,'Q':Q,'new':isnew})

if __name__=='__main__' and '--check' in sys.argv:
    print('total recs',len(recs),'new',sum(1 for r in recs if r['new']))
    used=set(r['url'].replace(BASE,'').split('#')[0].rstrip('?') for r in recs if not r['new'])
    missing=[k for k in exist if k not in used]
    print('existing urls NOT placed:',len(missing))
    for k in missing: print('  MISSING',k)
    sys.exit(0)

if __name__=='__main__' and '--write' in sys.argv:
    from openpyxl.styles import Font, Alignment, Border, Side
    import shutil, datetime
    OUT=SRC
    # backup
    bk=OUT.replace('.xlsx',f'_backup_탭전개전.xlsx')
    shutil.copy(OUT,bk); print('backup',bk)
    wb=openpyxl.load_workbook(OUT); ws=wb.active
    # capture style template from row3
    tpl_align=copy.copy(ws.cell(3,2).alignment)
    tpl_font=copy.copy(ws.cell(3,2).font)
    klink_font=copy.copy(ws.cell(3,11).font)
    thin=Side(style='thin',color='FFBFBFBF')
    border=Border(left=thin,right=thin,top=thin,bottom=thin)
    # clear all data rows (3..max) values+merges+hyperlinks
    for m in list(ws.merged_cells.ranges):
        if m.min_row>=3: ws.unmerge_cells(str(m))
    maxr=ws.max_row
    for r in range(3,maxr+1):
        for c in range(2,28):
            cell=ws.cell(r,c); cell.value=None; cell.hyperlink=None
    # write records
    r0=3
    for i,rec in enumerate(recs):
        r=r0+i
        ws.cell(r,2,i+1)                 # B 순번
        ws.cell(r,3,INST)                # C
        # D..J : place label at depth col (4=D)
        col=4+rec['d']-1
        ws.cell(r,col,rec['label'])
        kc=ws.cell(r,11,rec['url']); kc.hyperlink=rec['url']; kc.font=copy.copy(klink_font)
        ws.cell(r,12,rec['L'])
        ws.cell(r,13,rec['M'])
        ws.cell(r,14,rec['N'])
        ws.cell(r,15,rec['O'])
        ws.cell(r,16,rec['P'] if rec['P'] else None)
        ws.cell(r,17,rec['Q'] if rec['Q'] else None)
        for c in range(2,28):
            cell=ws.cell(r,c)
            if c!=11: cell.font=copy.copy(tpl_font)
            cell.alignment=copy.copy(tpl_align)
            cell.border=border
        ws.row_dimensions[r].height=15
    last=r0+len(recs)-1
    # determine for each row which column holds its own label (depth col)
    depthcol=[None]*(last+2)
    for i,rec in enumerate(recs):
        depthcol[r0+i]=4+rec['d']-1
    # merge D..J: a parent cell at (R,ci) spans down to just before the next row whose depthcol<=ci
    for ci in range(4,11):  # D(4)..J(10)
        r=r0
        while r<=last:
            if depthcol[r]==ci:
                # this row owns a label at column ci; span until next row with depthcol<=ci
                end=r
                rr=r+1
                while rr<=last and depthcol[rr]>ci:
                    end=rr; rr+=1
                if end>r:
                    ws.merge_cells(start_row=r,start_column=ci,end_row=end,end_column=ci)
                r=rr
            else:
                r+=1
    wb.save(OUT); print('saved',OUT,'rows',len(recs),'last',last)
