# -*- coding: utf-8 -*-
"""작업파일명 앞에 광역(도) 접두 — {시}.xlsx → {도}_{시}.xlsx (2026-06-01).

1) 광역_사이트맵/{도}/{N.시}/{시}.xlsx 메인 파일 rename (백업·부수파일 제외).
2) 모든 .py(_스크립트/ + 광역_사이트맵/**)에서 리터럴 '{시}.xlsx' → '{도}_{시}.xlsx' 치환.
   (충남·충북 phase234 SITES 하드코딩 경로, 기관폴더 스크립트 등)
※ 동적 빌더(f'{name}.xlsx' 등 5곳)는 별도 수동 수정.

사용: python -X utf8 _rename_prefix.py dry|run
"""
import os, sys, io, re

ROOT = r'D:\01.프로젝트\DB수집'
MAP = os.path.join(ROOT, '작업파일', '광역_사이트맵')
PROVS = ['충청남도', '충청북도', '전북특별자치도', '제주특별자치도']


def build_map():
    """반환 [(도, 폴더명(N.시), 시, 기존xlsx경로, 새xlsx경로)]"""
    out = []
    for prov in PROVS:
        pdir = os.path.join(MAP, prov)
        if not os.path.isdir(pdir):
            continue
        for fold in sorted(os.listdir(pdir)):
            fdir = os.path.join(pdir, fold)
            if not os.path.isdir(fdir):
                continue
            si = fold.split('.', 1)[-1]  # 'N.시' → 시
            old = os.path.join(fdir, f'{si}.xlsx')
            if os.path.exists(old):
                new = os.path.join(fdir, f'{prov}_{si}.xlsx')
                out.append((prov, fold, si, old, new))
    return out


def py_files():
    fs = []
    sdir = os.path.join(ROOT, '_스크립트')
    for f in os.listdir(sdir):
        if f.endswith('.py'):
            fs.append(os.path.join(sdir, f))
    for dp, _, names in os.walk(MAP):
        for n in names:
            if n.endswith('.py'):
                fs.append(os.path.join(dp, n))
    return fs


def main():
    mode = sys.argv[1] if len(sys.argv) > 1 else 'dry'
    m = build_map()
    # 시→도 (리터럴 치환용). 시명 길이 내림차순(부분일치 방지)
    s2p = {si: prov for prov, fold, si, o, n in m}
    print(f'== rename 대상 {len(m)}개 ==')
    for prov, fold, si, o, n in m:
        print(f'  {prov}/{fold}/{si}.xlsx → {prov}_{si}.xlsx')
        if mode == 'run':
            if os.path.exists(n):
                print('    !! 이미 존재, 스킵'); continue
            os.rename(o, n)
    # 리터럴 치환
    print('\n== .py 리터럴 치환 ==')
    keys = sorted(s2p.keys(), key=len, reverse=True)
    total_files = 0; total_hits = 0
    for fp in py_files():
        try:
            txt = io.open(fp, encoding='utf-8').read()
        except Exception:
            continue
        orig = txt; hits = 0
        for si in keys:
            prov = s2p[si]
            pat = si + '.xlsx'
            rep = f'{prov}_{si}.xlsx'
            # 이미 접두된 경우 중복 방지: {prov}_{si}.xlsx 는 건드리지 않음
            # 음수 룩비하인드로 바로 앞이 '_'(도접두 직후)나 한글이면 스킵
            def _sub(mo):
                start = mo.start()
                before = txt[max(0, start - 1):start]
                # 직전이 '_' 또는 한글(다른 시명 꼬리)이면 치환 안 함
                if before and (before == '_' or '가' <= before <= '힣'):
                    return mo.group(0)
                return rep
            new = re.sub(re.escape(pat), _sub, txt)
            if new != txt:
                hits += new.count(rep) - orig.count(rep)
                txt = new
        if txt != orig:
            total_files += 1
            n_changed = sum(txt.count(f'{s2p[si]}_{si}.xlsx') for si in keys) - sum(orig.count(f'{s2p[si]}_{si}.xlsx') for si in keys)
            print(f'  {os.path.relpath(fp, ROOT)}  (+{n_changed})')
            total_hits += n_changed
            if mode == 'run':
                io.open(fp, 'w', encoding='utf-8').write(txt)
    print(f'\n치환 파일 {total_files}개, 경로 {total_hits}건 ({mode})')
    print('※ 동적 빌더 수동수정 필요: _dedup_all.py xpath, _tab_batch.py xlsx_path, _jeonbuk_phase234_all.py site(), phase1 3개')


if __name__ == '__main__':
    main()
