# -*- coding: utf-8 -*-
"""
전체 사이트 탭 재스캔 배치 (읽기전용).
- 현황판(_작업현황.md)에서 기관/상태 파싱
- 각 폴더 대표 xlsx 찾아 _tab_scan.scan_xlsx 실행
- 신규탐지 결과 vs 기존 '탭없음0'/'탭확장' 비교 리포트 생성
출력: _temp/_tab_rescan_report.md, _tab_rescan_report.json
"""
import os, sys, re, json, glob, time
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from _tab_scan import scan_xlsx
sys.stdout.reconfigure(encoding='utf-8')

ROOT = r'D:\01.프로젝트\DB수집\작업파일\광역_사이트맵'
EXCLUDE = {'서천군'}  # 사용자 작업중

# 검수완료(수정금지·읽기만) 목록
INSPECTED = {'계룡시','공주시','금산군','논산시','보령시','당진시','부여군',
             '고창군','김제시','남원시','군산시','무주군'}

def pick_xlsx(folder):
    cand = [f for f in glob.glob(os.path.join(folder,'*.xlsx'))
            if 'backup' not in os.path.basename(f).lower()
            and not os.path.basename(f).startswith('_')
            and not os.path.basename(f).startswith('~$')]
    # 광역_기관.xlsx 우선
    cand.sort(key=lambda f: (0 if re.match(r'^[가-힣]+도?_', os.path.basename(f)) else 1, len(f)))
    return cand[0] if cand else None

def site_name(folder):
    return re.sub(r'^\d+\.', '', os.path.basename(folder))

jobs = []
for prov in sorted(os.listdir(ROOT)):
    pdir = os.path.join(ROOT, prov)
    if not os.path.isdir(pdir) or prov.startswith('__'): continue
    for d in sorted(os.listdir(pdir), key=lambda s:(int(re.match(r'(\d+)',s).group(1)) if re.match(r'(\d+)',s) else 999)):
        sdir = os.path.join(pdir, d)
        if not os.path.isdir(sdir): continue
        nm = site_name(sdir)
        if nm in EXCLUDE: continue
        xl = pick_xlsx(sdir)
        if not xl: continue
        jobs.append({'prov': prov, 'name': nm, 'xlsx': xl,
                     'inspected': nm in INSPECTED})

print(f'총 {len(jobs)}개 사이트 스캔 시작', flush=True)
results = []
for i, j in enumerate(jobs, 1):
    t0 = time.time()
    try:
        out = scan_xlsx(j['xlsx'], workers=16)
        j2 = {**j, 'ok': True, 'groups': out['tab_groups'], 'est_new': out['est_new_rows'],
              'rows': out['data_rows'], 'pages': out['scanned_pages'],
              'classes': list(out['container_classes'].keys())[:3],
              'top': [(g['F'], g['missing']) for g in out['groups'][:5]]}
    except Exception as e:
        j2 = {**j, 'ok': False, 'err': str(e)[:80]}
    j2['sec'] = round(time.time()-t0, 1)
    results.append(j2)
    tag = '읽기만' if j['inspected'] else '전개대상'
    g = j2.get('groups','-'); en = j2.get('est_new','-')
    print(f"[{i:>2}/{len(jobs)}] {j['prov'][:2]} {j['name']:6} ({tag}) groups={g} est_new={en} {'ERR '+j2.get('err','') if not j2['ok'] else ''} {j2['sec']}s", flush=True)

# report
TEMP = r'D:\01.프로젝트\DB수집\작업파일\_temp'
os.makedirs(TEMP, exist_ok=True)
json.dump(results, open(os.path.join(TEMP,'_tab_rescan_report.json'),'w',encoding='utf-8'), ensure_ascii=False, indent=1)

lines = ['# 탭 재스캔 리포트 (읽기전용)\n',
         '> 새 구조기반 탐지기 결과. est_new=누락 탭(예상 추가행). 검수완료=읽기만(참고), 전개대상=실제 작업 후보.\n',
         '| 광역 | 기관 | 분류 | 데이터행 | 탭그룹 | 예상+행 | 비고 |',
         '|---|---|---|---|---|---|---|']
for r in sorted(results, key=lambda x:(x['prov'], x['name'])):
    if not r['ok']:
        lines.append(f"| {r['prov'][:2]} | {r['name']} | {'읽기만' if r['inspected'] else '전개대상'} | - | ERR | - | {r.get('err','')} |")
        continue
    cls = r['classes'][0] if r.get('classes') else ''
    note = f"cls={cls}" if r['groups'] else "탭 0"
    flag = ' ⚠️재확인' if (r['groups'] and not r['inspected']) else ''
    lines.append(f"| {r['prov'][:2]} | {r['name']} | {'읽기만' if r['inspected'] else '전개대상'} | {r['rows']} | {r['groups']} | {r['est_new']}{flag} | {note} |")
# summary
act = [r for r in results if r['ok'] and not r['inspected']]
tot_new = sum(r['est_new'] for r in act)
lines.append('')
lines.append(f"**전개대상 합계**: {len([r for r in act if r['groups']])}곳에서 탭 발견 / 예상 +{tot_new}행")
open(os.path.join(TEMP,'_tab_rescan_report.md'),'w',encoding='utf-8').write('\n'.join(lines))
print('\nDONE. report:', os.path.join(TEMP,'_tab_rescan_report.md'))
