"""
01_data_acquisition_wdi.py
OECD-38 资源重配置效率（RE）指数 — World Bank WDI 数据获取模块
Resource Reallocation Efficiency (RE) Index — World Bank WDI Data Acquisition

用途 / Purpose:
    通过 wbgapi 包从 World Bank World Development Indicators (WDI) 批量下载
    构建 RE 指数所需的宏观经济、财政结构与技术创新变量，覆盖 OECD 全部
    38 个正式成员国，时间跨度 2000-2023 年（24 年）。

    Downloads macro-fiscal and technology/innovation variables required to
    construct the RE Index, via the wbgapi package, for all 38 OECD member
    states over 2000-2023 (24 years).

依赖 / Dependencies: wbgapi, pandas, numpy
执行环境 / Environment: Python 3.13.x
随机种子 / Random seed: 42（本模块无随机过程，仅为流水线一致性声明）

注意 / Note: 本脚本为研究工作流的存档版本，直接执行需要网络访问
World Bank API；如离线复现，请使用随附的 oecd38_re_index_full.csv。
"""

import time
import json
import logging
from pathlib import Path

import numpy as np
import pandas as pd

try:
    import wbgapi as wb
except ImportError:  # pragma: no cover
    wb = None

logging.basicConfig(level=logging.INFO, format="%(asctime)s  %(message)s")
log = logging.getLogger("01_data_acquisition_wdi")

OUTPUT_DIR = Path("./data")
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

# ---------------------------------------------------------------------------
# OECD-38 成员国 ISO3 代码清单（不含中国，因研究对象即为 OECD 官方成员）
# OECD-38 member ISO3 codes (no China; OECD membership itself excludes it)
# ---------------------------------------------------------------------------
OECD38 = {
    "AUS": "Australia", "AUT": "Austria", "BEL": "Belgium", "CAN": "Canada",
    "CHE": "Switzerland", "CHL": "Chile", "COL": "Colombia", "CRI": "Costa Rica",
    "CZE": "Czechia", "DEU": "Germany", "DNK": "Denmark", "ESP": "Spain",
    "EST": "Estonia", "FIN": "Finland", "FRA": "France", "GBR": "United Kingdom",
    "GRC": "Greece", "HUN": "Hungary", "IRL": "Ireland", "ISL": "Iceland",
    "ISR": "Israel", "ITA": "Italy", "JPN": "Japan", "KOR": "Korea, Rep.",
    "LTU": "Lithuania", "LUX": "Luxembourg", "LVA": "Latvia", "MEX": "Mexico",
    "NLD": "Netherlands", "NOR": "Norway", "NZL": "New Zealand", "POL": "Poland",
    "PRT": "Portugal", "SVK": "Slovak Republic", "SVN": "Slovenia",
    "SWE": "Sweden", "TUR": "Turkiye", "USA": "United States",
}

YEARS = list(range(2000, 2024))  # 2000-2023, 24 years

# ---------------------------------------------------------------------------
# WDI 指标清单（33 项，覆盖财政响应、技术转化、监管适应性代理变量）
# WDI indicator inventory (33 indicators spanning fiscal / tech / regulatory
# proxy variables for the V / C dimensions of the RE Index)
# ---------------------------------------------------------------------------
WDI_INDICATORS = {
    # --- 财政响应 / Fiscal responsiveness (V dimension proxies) ---
    "NE.CON.GOVT.ZS": "gov_expenditure_pct_gdp",
    "GC.XPN.TOTL.GD.ZS": "gov_expenditure_total_pct_gdp",
    "GC.TAX.TOTL.GD.ZS": "tax_revenue_pct_gdp",
    "GC.DOD.TOTL.GD.ZS": "central_gov_debt_pct_gdp",
    "NY.GDP.MKTP.KD.ZG": "gdp_growth_pct",
    "FP.CPI.TOTL.ZG": "inflation_cpi",
    "SL.UEM.TOTL.ZS": "unemployment_pct",
    "GC.BAL.CASH.GD.ZS": "fiscal_balance_pct_gdp",
    # --- 技术转化 / Technology conversion (C dimension proxies) ---
    "GB.XPD.RSDV.GD.ZS": "rd_expenditure_pct_gdp",
    "IP.PAT.RESD": "patents_residents",
    "IP.PAT.NRES": "patents_nonresidents",
    "SE.TER.ENRR": "tertiary_enrollment",
    "TX.VAL.TECH.MF.ZS": "hightech_exports_pct",
    "IT.NET.USER.ZS": "internet_users_pct",
    "IT.CEL.SETS.P2": "mobile_subscriptions_per100",
    # --- 制度摩擦 / Institutional friction proxies (F dimension) ---
    "IC.REG.DURS": "days_to_start_business",       # known to fail; see log
    "IC.BUS.EASE.XQ": "ease_of_doing_business",
    "IQ.CPA.BREG.XQ": "business_regulatory_quality",
    # --- 其余覆盖性/对照指标 / additional coverage & control variables ---
    "NY.GDP.PCAP.KD": "gdp_per_capita_constant",
    "SP.POP.TOTL": "population_total",
    "NE.TRD.GNFS.ZS": "trade_pct_gdp",
    "BX.KLT.DINV.WD.GD.ZS": "fdi_inflows_pct_gdp",
    "GB.XPD.EDCT.TL.GD.ZS": "education_expenditure_pct_gdp",
    "SH.XPD.CHEX.GD.ZS": "health_expenditure_pct_gdp",
    "EG.USE.PCAP.KG.OE": "energy_use_per_capita",
    "EN.ATM.CO2E.PC": "co2_emissions_per_capita",
    "SL.TLF.CACT.ZS": "labor_force_participation",
    "SE.XPD.TOTL.GD.ZS": "public_education_expenditure_pct_gdp",
    "GB.XPD.RSDV.GD.ZS.2": "rd_expenditure_alt_pct_gdp",
    "IC.LGL.CRED.XQ": "legal_rights_index",
    "IC.REG.COST.PC.ZS": "cost_of_business_startup",
    "FS.AST.PRVT.GD.ZS": "domestic_credit_private_pct_gdp",
    "GC.REV.XGRT.GD.ZS": "gov_revenue_excl_grants_pct_gdp",
    "MS.MIL.XPND.GD.ZS": "military_expenditure_pct_gdp",
    "SI.POV.GINI": "gini_index",
}


def fetch_indicator(code: str, countries: list, years: list) -> pd.DataFrame:
    """Fetch one WDI indicator for the given countries/years via wbgapi."""
    if wb is None:
        raise RuntimeError(
            "wbgapi is not installed in this environment; "
            "install with `pip install wbgapi` to re-run live acquisition."
        )
    log.info("Fetching %s ...", code)
    df = wb.data.DataFrame(code, economy=countries, time=range(years[0], years[-1] + 1))
    df = df.reset_index().melt(id_vars="economy", var_name="year_raw", value_name="value")
    df["year"] = df["year_raw"].str.replace("YR", "", regex=False).astype(int)
    df = df.drop(columns=["year_raw"]).rename(columns={"economy": "iso3"})
    df["indicator_code"] = code
    return df


def main():
    countries = list(OECD38.keys())
    all_frames = []
    success, failed = [], []

    for code, name in WDI_INDICATORS.items():
        try:
            frame = fetch_indicator(code, countries, YEARS)
            frame["indicator_name"] = name
            all_frames.append(frame)
            success.append(code)
            time.sleep(0.2)  # be polite to the API
        except Exception as exc:  # noqa: BLE001
            log.warning("FAILED %s (%s): %s", code, name, exc)
            failed.append((code, name, str(exc)))

    if all_frames:
        panel = pd.concat(all_frames, ignore_index=True)
        wide = panel.pivot_table(
            index=["iso3", "year"], columns="indicator_name", values="value"
        ).reset_index()
        wide.to_csv(OUTPUT_DIR / "wb_wdi_raw.csv", index=False)
        log.info(
            "Saved WDI panel: %d rows x %d columns -> data/wb_wdi_raw.csv",
            wide.shape[0], wide.shape[1],
        )

    with open(OUTPUT_DIR / "wdi_acquisition_summary.json", "w", encoding="utf-8") as fh:
        json.dump(
            {
                "requested_indicators": len(WDI_INDICATORS),
                "succeeded": success,
                "failed": failed,
                "countries": countries,
                "years": [YEARS[0], YEARS[-1]],
            },
            fh, ensure_ascii=False, indent=2,
        )

    log.info(
        "WDI acquisition complete: %d/%d indicators succeeded.",
        len(success), len(WDI_INDICATORS),
    )


if __name__ == "__main__":
    main()
