#!/usr/bin/env python3
"""
통합 GPU 시리얼 수집 스크립트
hwinventory에서 Video.Slot 정보 수집
"""
import sys
import os
import re
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor
import logging

sys.path.insert(0, str(Path(__file__).parent.parent))
from core.idrac_client import IDRACClient
from core.parsers import InfoParser

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [INFO] root: %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

def collect_gpu_for_ip(ip: str, output_dir: Path) -> tuple:
    """단일 IP에 대한 GPU Serial 정보 수집"""
    try:
        logging.info(f"[{ip}] GPU 정보 수집 시작")
        
        client = IDRACClient(ip)
        
        # 1. Get Service Tag
        sysinfo = client.get_sysinfo()
        svc_tag = InfoParser.extract_service_tag(sysinfo)
        
        if not svc_tag:
            return ip, False, "서비스 태그 추출 실패"

        # 2. Get Hardware Inventory
        hwinventory = client.get_hwinventory()
        
        # 3. Parse GPU Serials
        gpu_map = InfoParser.extract_gpu_serials(hwinventory)
        
        # 4. Write File
        output_file = output_dir / f"{svc_tag}.txt"
        
        # 정렬 로직 (Legacy GPU_Serial_v1.py 유지)
        def slot_key(k: str):
            m = re.search(r"Video\.Slot\.(\d+)-(\d+)", k)
            if m:
                return (int(m.group(1)), int(m.group(2)))
            return (1_000_000, 1_000_000, k)

        with output_file.open('w', encoding='utf-8', newline='\n') as f:
            f.write(f"{svc_tag}\n")
            
            if not gpu_map:
                f.write("No GPU(Video) inventory found or SerialNumber not present.\n")
                return ip, True, f"저장: {output_file.name} (GPU 없음)"

            # Write individual slots
            sorted_keys = sorted(gpu_map.keys(), key=slot_key)
            for fqdd in sorted_keys:
                serial = gpu_map[fqdd]
                f.write(f"{fqdd}: {serial}\n")
            
            # Write summary line
            serials_only = [gpu_map[k] for k in sorted_keys if gpu_map[k] != "Not Found"]
            if serials_only:
                f.write(f"SERIALS: {';'.join(serials_only)}\n")
        
        return ip, True, f"저장: {output_file.name} ({len(serials_only)}개 발견)"

    except Exception as e:
        logging.error(f"[{ip}] 오류: {e}")
        return ip, False, f"오류: {e}"


def main():
    if len(sys.argv) < 2:
        print("Usage: python collect_gpu.py <ip_file>")
        sys.exit(1)
    
    ip_file = Path(sys.argv[1])
    
    if not ip_file.exists():
        logging.error(f"IP 파일 없음: {ip_file}")
        sys.exit(1)
    
    # 출력 디렉토리
    # 출력 디렉토리 (스크립트 위치 기준)
    script_dir = Path(__file__).resolve().parent
    data_root = script_dir.parent.parent
    output_dir = data_root / "temp" / "staging"
    output_dir.mkdir(parents=True, exist_ok=True)
    
    # IP 목록 읽기
    ips = [line.strip() for line in ip_file.read_text(encoding='utf-8').splitlines() if line.strip()]
    
    if not ips:
        logging.error("IP 목록이 비어 있습니다.")
        sys.exit(1)
    
    logging.info(f"총 {len(ips)}대 GPU 정보 수집 시작")
    
    # 병렬 처리
    ok, fail = 0, 0
    with ThreadPoolExecutor(max_workers=20) as executor:
        futures = {executor.submit(collect_gpu_for_ip, ip, output_dir): ip for ip in ips}
        
        for future in futures:
            ip, success, msg = future.result()
            if success:
                logging.info(f"[OK] {ip} - {msg}")
                ok += 1
            else:
                logging.error(f"[FAIL] {ip} - {msg}")
                fail += 1
    
    logging.info(f"완료: 성공 {ok}대 / 실패 {fail}대")


if __name__ == "__main__":
    main()
