from __future__ import annotations
import os
from pathlib import Path
from collections import OrderedDict
import pandas as pd

# ------------------------------------------------------------
# Cross-platform root resolver (Windows / Linux / macOS)
# ------------------------------------------------------------
def resolve_data_root() -> Path:
    """
    Priority:
      1) Env var IDRAC_DATA_DIR (absolute/relative OK)
      2) nearest parent of this file that contains a 'data' folder
      3) ./data under current working directory
    """
    env = os.getenv("IDRAC_DATA_DIR")
    if env:
        return Path(env).expanduser().resolve()

    here = Path(__file__).resolve()
    for p in [here] + list(here.parents):
        if (p / "data").is_dir():
            return (p / "data").resolve()

    return (Path.cwd() / "data").resolve()


DATA_ROOT = resolve_data_root()

# ------------------------------------------------------------
# Paths (can be overridden with env vars if needed)
# ------------------------------------------------------------
SERVER_LIST_DIR = Path(os.getenv("GUID_SERVER_LIST_DIR", DATA_ROOT / "server_list"))
SERVER_LIST_FILE = Path(os.getenv("GUID_LIST_FILE", SERVER_LIST_DIR / "guid_list.txt"))

GUID_TXT_DIR = Path(os.getenv("GUID_TXT_DIR", DATA_ROOT / "repository" / "guid_file"))

OUTPUT_XLSX = Path(
    os.getenv("GUID_OUTPUT_XLSX", DATA_ROOT / "temp" / "staging" / "XE9680_GUID.xlsx")
)

# Make sure output directory exists
OUTPUT_XLSX.parent.mkdir(parents=True, exist_ok=True)

# ------------------------------------------------------------
# Utilities
# ------------------------------------------------------------
def read_lines_any_encoding(path: Path) -> list[str]:
    """Read text file trying common encodings (utf-8/utf-8-sig/cp949/euc-kr/latin-1)."""
    encodings = ["utf-8-sig", "utf-8", "cp949", "euc-kr", "latin-1"]
    for enc in encodings:
        try:
            with path.open("r", encoding=enc, errors="strict") as f:
                return f.read().splitlines()
        except Exception:
            continue
    # last resort with replacement
    with path.open("r", encoding="utf-8", errors="replace") as f:
        return f.read().splitlines()


def parse_txt_with_st(file_path: Path) -> dict:
    """
    Parse a GUID .txt file:
      - First line becomes 'S/T'
      - Remaining lines in 'Key: Value' form
    Keeps insertion order.
    """
    lines = read_lines_any_encoding(file_path)
    if not lines:
        return {}

    data = OrderedDict()
    data["S/T"] = lines[0].strip()

    for raw in lines[1:]:
        line = raw.strip()
        if not line or ":" not in line:
            continue
        key, value = line.split(":", 1)
        data[key.strip()] = value.strip()

    return dict(data)

# ------------------------------------------------------------
# 슬롯 우선순위 설정 
# ------------------------------------------------------------
# 환경변수에서 슬롯 우선순위 읽기 (예: "38,39,37,36,32,33,34,35,31,40")
slot_priority_str = os.getenv("GUID_SLOT_PRIORITY", "")
if slot_priority_str:
    SLOT_PRIORITY = [s.strip() for s in slot_priority_str.split(",") if s.strip()]
    print(f"[INFO] 사용자 지정 슬롯 우선순위: {SLOT_PRIORITY}")
else:
    # 기본 우선순위 (10개)
    SLOT_PRIORITY = ['38', '39', '37', '36', '32', '33', '34', '35', '31', '40']
    print(f"[INFO] 기본 슬롯 우선순위 사용: {SLOT_PRIORITY}")

# ------------------------------------------------------------
# Load list of file basenames from guid_list.txt
# ------------------------------------------------------------
if not SERVER_LIST_FILE.is_file():
    raise FileNotFoundError(f"guid_list.txt not found: {SERVER_LIST_FILE}")

file_names = [x.strip() for x in read_lines_any_encoding(SERVER_LIST_FILE) if x.strip()]

# ------------------------------------------------------------
# Collect rows
# ------------------------------------------------------------
rows: list[dict] = []
for name in file_names:
    txt_path = GUID_TXT_DIR / f"{name}.txt"
    if not txt_path.is_file():
        print(f"[WARN] 파일을 찾을 수 없습니다: {txt_path.name}")
        # still append at least S/T if you want a row placeholder
        # rows.append({"S/T": name})
        continue

    parsed_data = parse_txt_with_st(txt_path)
    
    # 슬롯 우선순위에 따라 데이터 재정렬
    reordered_data = OrderedDict()
    reordered_data["S/T"] = parsed_data.get("S/T", "")
    
    # 슬롯 데이터를 우선순위 순서대로 추가
    # 슬롯 데이터를 우선순위 순서대로 추가하며 GUID 문자열 재구성
    new_guid_list = []
    
    for slot_num in SLOT_PRIORITY:
        slot_key = f"Slot.{slot_num}"
        val = parsed_data.get(slot_key)
        
        # 데이터가 있으면 컬럼 추가
        if val:
            reordered_data[slot_key] = val
            
            # GUID 재구성을 위한 수집 (Not Found 제외, 포맷 확인)
            if val != "Not Found" and ":" in val:
                # 예: 3825:F303:0085:07A6 -> 0x3825F303008507A6
                clean_hex = val.replace(":", "").upper()
                new_guid_list.append(f"0x{clean_hex}")
    
    # 1순위: 재구성된 GUID (사용자가 지정한 슬롯 순서대로)
    # 2순위: 파일에 있던 원본 GUID
    if new_guid_list:
        reordered_data["GUID"] = ";".join(new_guid_list)
    elif "GUID" in parsed_data:
        reordered_data["GUID"] = parsed_data["GUID"]
    
    # 나머지 필드들 추가 (슬롯이 아닌 것들)
    for key, value in parsed_data.items():
        if key not in reordered_data:
            reordered_data[key] = value
    
    rows.append(dict(reordered_data))

# Build DataFrame (union of keys across all rows)
df = pd.DataFrame(rows)

# Prepend No column (1..N)
df.insert(0, "No", range(1, len(df) + 1))

# Save to Excel
df.to_excel(OUTPUT_XLSX, index=False)

print(f"엑셀 파일이 생성되었습니다: {OUTPUT_XLSX}")