#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Ulusal Ticaret Filoları ve Denizcilik Emisyonları: UNCTAD Filo Tonajı, OECD Denizcilik CO₂ (SEEA İkamet İlkesi), Climate Watch Bunker Yakıtı Emisyonları ve IMO 2023 Kontrol Noktaları
National Merchant Fleets & Maritime Emissions: UNCTAD Fleet Tonnage, OECD Maritime CO₂ (SEEA Residence Principle), Climate Watch Bunker-Fuel Emissions & IMO 2023 Checkpoints
==============================================================================
GOMD Python SDK — Gerçek veriyle yeniden üretilebilir vaka çalışması / Reproducible real-data case study
Google Colab Install: !pip install -q --upgrade gomd

Veri kaynakları / Data sources (hepsi GOMD sunucusundan canlı çekilir / all fetched live from the GOMD server):
  - unctad_fleet_dwt_total, _bulk_carriers, _oil_tankers, _container, unctad_fleet_age_avg, unctad_fleet_owned_dwt — UNCTAD ticaret filosu istatistikleri
  - OECD_MARITIME_CO2_RESIDENCE_M — OECD aylık denizcilik CO₂ emisyonları (SEEA ikamet ilkesi, AIS tabanlı)
  - CW_GHG_BUNKER_FUELS_CO2 — Climate Watch, uluslararası bunker yakıtı CO₂ emisyonları
  - IMO 2023 Sera Gazı Stratejisi kontrol noktaları (MEPC.377(80)) — yalnız ölçek karşılaştırması

Not / Note: Bu betik sentetik veri üretmez. Bir seri sunucuda yoksa betik açık bir hata mesajıyla durur.
            This script never generates synthetic data. If a series is missing on the server, it stops with an explicit error.
"""

# ==============================================================================
# ADIM 0: GOMD Python SDK Kurulumu ve Canlı Veri Yardımcıları
# STEP 0: Install the GOMD Python SDK & Live Data Helpers
# ==============================================================================
import importlib
import os
import subprocess
import sys
import math
import json
from pathlib import Path
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

if hasattr(sys.stdout, "reconfigure"):
    try:
        sys.stdout.reconfigure(encoding="utf-8", errors="replace")
    except Exception:
        pass

_IN_COLAB = "google.colab" in sys.modules
_GOMD_WHEEL_URL = "https://gomd.pirireis.edu.tr/sdk/dist/gomd-2.0.1-py3-none-any.whl"
try:
    import gomd  # noqa: F401
    if _IN_COLAB:
        subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", "--force-reinstall", "--no-cache-dir", _GOMD_WHEEL_URL])
except ImportError:
    subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", "--force-reinstall", "--no-cache-dir", _GOMD_WHEEL_URL])

import gomd
for _mod_name in list(sys.modules.keys()):
    if _mod_name == "gomd" or _mod_name.startswith("gomd."):
        importlib.reload(sys.modules[_mod_name])
import gomd
from gomd import GOMDClient

client = GOMDClient("https://gomd.pirireis.edu.tr")


def fetch_gomd_records(indicator: str, entity: str, period_from=None, period_to=None, limit: int = 50000) -> pd.DataFrame:
    """
    GOMD sunucusundan bir göstergenin TEK bir varlık (ülke/havza) için ham kayıtlarını çeker.
    Yalnız istenen varlığın kayıtları tutulur; sunucu başka bir varlık döndürürse kullanılmaz.
    Returns a DataFrame with columns: period (str), value (float).
    """
    rows = client.get_series(indicator=indicator, entity=entity, period_from=period_from,
                             period_to=period_to, limit=limit, as_df=False)
    keep = [r for r in rows if str(r.get("entity_code") or "") == entity and r.get("value") is not None]
    if not keep:
        raise RuntimeError(f"GOMD sunucusunda veri yok: indicator={indicator}, entity={entity}")
    df = pd.DataFrame({"period": [str(r["period"]) for r in keep], "value": [float(r["value"]) for r in keep]})
    df = df.drop_duplicates("period").sort_values("period").reset_index(drop=True)
    print(f"📡 [GOMD] {indicator:<44} | {entity:<18} | N={len(df):<6} ({df['period'].iloc[0][:10]} – {df['period'].iloc[-1][:10]})")
    return df


def fetch_gomd_annual_series(indicator: str, entity: str, period_from: int = 1900, period_to: int = 2100,
                             how: str = "mean", min_count: int = 1) -> dict:
    """
    Yıllık seri döndürür: {yıl: değer}. Kayıtlar yıllık değilse (aylık/günlük) yıl içi ortalama alınır
    ve yalnız en az `min_count` kaydı olan yıllar tutulur. Returns {year: value}.
    """
    df = fetch_gomd_records(indicator, entity)
    df["year"] = df["period"].str[:4].astype(int)
    df = df[(df["year"] >= period_from) & (df["year"] <= period_to)]
    g = df.groupby("year")["value"]
    agg = g.mean() if how == "mean" else g.last()
    cnt = g.count()
    out = {int(y): float(v) for y, v in agg.items() if cnt[y] >= min_count}
    if not out:
        raise RuntimeError(f"Seçilen dönemde veri yok: indicator={indicator}, entity={entity}")
    return dict(sorted(out.items()))


def fmt_p(p: float) -> str:
    """p değerini okunur biçimde yazar / readable p-value."""
    return "<1e-6" if p < 1e-6 else f"{p:.4f}"


print(f"✅ GOMD Python SDK Sürümü / Version : v{gomd.__version__}")
print(f"🌐 Canlı Veri Sunucusu / Server     : {client.base_url}")
print(f"🏛️ Kurum / Institution              : Pîrî Reis Üniversitesi & T.C. Çevre, Şehircilik ve İklim Değişikliği Bakanlığı Çevre Yönetimi Genel Müdürlüğü — GOMD (COP31 Türkiye)")

# ==============================================================================
# ADIM 1: UNCTAD Ticaret Filosu Yapısı — 8 Denizci Ülke
# STEP 1: UNCTAD merchant fleet structure — 8 maritime nations
# ==============================================================================
from gomd.stats import mann_kendall_sen, pettitt_changepoint, panel_fixed_effects

countries = ["TUR", "GRC", "ITA", "ESP", "FRA", "DEU", "NOR", "CHN"]
fleet_rows = []
for iso in countries:
    tot = fetch_gomd_annual_series("unctad_fleet_dwt_total", iso)
    bulk = fetch_gomd_annual_series("unctad_fleet_dwt_bulk_carriers", iso)
    tank = fetch_gomd_annual_series("unctad_fleet_dwt_oil_tankers", iso)
    cont = fetch_gomd_annual_series("unctad_fleet_dwt_container", iso)
    age = fetch_gomd_annual_series("unctad_fleet_age_avg", iso)
    own = fetch_gomd_annual_series("unctad_fleet_owned_dwt", iso)
    y = max(set(tot) & set(bulk) & set(tank) & set(cont))
    fleet_rows.append({"ISO": iso, "Yıl": y, "Bayrak filosu (bin DWT)": round(tot[y]),
                       "Dökme %": round(100 * bulk[y] / tot[y], 1), "Tanker %": round(100 * tank[y] / tot[y], 1),
                       "Konteyner %": round(100 * cont[y] / tot[y], 1), "Ort. yaş (yıl)": round(age[max(age)], 1),
                       "Sahip olunan filo (bin DWT)": round(own[max(own)])})
df_fleet = pd.DataFrame(fleet_rows)
print("\n🚢 UNCTAD filo yapısı (son yıl):")
print(df_fleet.to_string(index=False))

# ==============================================================================
# ADIM 2: Denizcilik Emisyonları — OECD (SEEA ikamet ilkesi, aylık) ve Climate Watch (bunker yakıtı, yıllık)
# STEP 2: Maritime emissions — OECD (SEEA residence principle, monthly) & Climate Watch (bunker fuels, annual)
# ==============================================================================
oecd_month = {}
oecd_annual = {}
for iso in countries:
    m = fetch_gomd_records("OECD_MARITIME_CO2_RESIDENCE_M", iso)
    m["year"] = m["period"].str[:4].astype(int)
    oecd_month[iso] = m
    g = m.groupby("year")["value"]
    oecd_annual[iso] = {int(yy): float(v) for yy, v in g.sum().items() if g.count()[yy] == 12}  # yalnız 12 ayı tam yıllar

tur_bunker = fetch_gomd_annual_series("CW_GHG_BUNKER_FUELS_CO2", "TUR")    # MtCO2e, uluslararası bunker
mk_bunker = mann_kendall_sen(list(tur_bunker.values()), t=list(tur_bunker))
pt_bunker = pettitt_changepoint(list(tur_bunker.values()), labels=list(tur_bunker))

# IMO 2023 Sera Gazı Stratejisi kontrol noktaları (2008'e göre): 2030 −%20 (hedef −%30), 2040 −%70 (hedef −%80), ~2050 net sıfır.
# Bu hedefler KÜRESEL uluslararası denizcilik içindir; burada Türkiye bunker serisine yalnız ölçek karşılaştırması için uygulanır.
base_2008 = tur_bunker.get(2008)
imo_points = {2030: (0.80, 0.70), 2040: (0.30, 0.20), 2050: (0.0, 0.0)}

intensity_rows = []
for iso in countries:
    own = fetch_gomd_annual_series("unctad_fleet_owned_dwt", iso)
    common = sorted(set(own) & set(oecd_annual[iso]))
    if not common:
        continue
    y = common[-1]
    intensity_rows.append({"ISO": iso, "Yıl": y, "OECD denizcilik CO₂ (Mt)": round(oecd_annual[iso][y] / 1e6, 2),
                           "Sahip olunan filo (milyon DWT)": round(own[y] / 1e3, 1),
                           "t CO₂ / bin DWT": round(oecd_annual[iso][y] / own[y], 1)})
df_int = pd.DataFrame(intensity_rows).sort_values("t CO₂ / bin DWT")
print("\n🌫️ Kaba emisyon yoğunluğu göstergesi (OECD ikamet ilkeli CO₂ / ulusal sahipli filo DWT):")
print(df_int.to_string(index=False))
print("ℹ️  Bu oran IMO CII değildir; ikamet ilkesine göre ülkeye atanan tüm gemi emisyonlarının ulusal sahipli tonaja bölümüdür.")

panel = []
for iso in countries:
    own = fetch_gomd_annual_series("unctad_fleet_owned_dwt", iso)
    for yy in sorted(set(own) & set(oecd_annual[iso])):
        panel.append({"iso": iso, "co2_mt": oecd_annual[iso][yy] / 1e6, "owned_mdwt": own[yy] / 1e3})
fe = panel_fixed_effects(panel, "iso", "co2_mt", "owned_mdwt")
print(f"\n📐 Panel sabit etkiler (ülke içi): Δ CO₂ (Mt) / Δ sahipli filo (milyon DWT) = {fe['beta_fe']:+.3f} "
      f"(t = {fe['t_stat']:.2f}, ülke içi R² = {fe['r_squared_within']:.3f}, N = {fe['n_obs']})")
print(f"📈 Türkiye bunker CO₂ trendi ({min(tur_bunker)}–{max(tur_bunker)}): Sen eğimi {mk_bunker['theil_sen_slope']:+.3f} Mt/yıl, "
      f"p = {fmt_p(mk_bunker['p_value'])}; Pettitt kırılma yılı {pt_bunker['changepoint_label']}")

# ==============================================================================
# ADIM 3: 4 Panelli Görselleştirme / 4-panel figure
# ==============================================================================
fig, axes = plt.subplots(2, 2, figsize=(14, 9.5), dpi=120)
fig.patch.set_facecolor("#071324")
for ax in axes.flat:
    ax.set_facecolor("#0b1d36"); ax.tick_params(colors="#cbd5e1")
    for sp in ax.spines.values():
        sp.set_color("#1e3a5f")
    ax.grid(alpha=0.18, color="#64748b")
leg = dict(facecolor="#0f172a", edgecolor="#334155", labelcolor="#f8fafc", fontsize=8)

ax1 = axes[0, 0]
x = np.arange(len(df_fleet)); b = np.zeros(len(df_fleet))
for col, c in [("Dökme %", "#38bdf8"), ("Tanker %", "#f43f5e"), ("Konteyner %", "#22c55e")]:
    vals = df_fleet["Bayrak filosu (bin DWT)"] * df_fleet[col] / 100 / 1e3
    ax1.bar(x, vals, bottom=b, color=c, label=col.replace(" %", "")); b += vals.values
ax1.set_xticks(x); ax1.set_xticklabels(df_fleet["ISO"])
ax1.set_title("A) Bayrak filosu tipe göre (milyon DWT, UNCTAD)", color="#f8fafc", fontweight="bold"); ax1.legend(**leg)

ax2 = axes[0, 1]
yy = sorted(tur_bunker); ax2.plot(yy, [tur_bunker[k] for k in yy], color="#f59e0b", marker="o", lw=1.8, label="Türkiye uluslararası bunker CO₂ (Climate Watch)")
if base_2008:
    for yr, (req, strive) in imo_points.items():
        ax2.scatter([yr], [base_2008 * req], color="#38bdf8", marker="v", s=60)
        ax2.scatter([yr], [base_2008 * strive], color="#22c55e", marker="v", s=60)
    ax2.scatter([], [], color="#38bdf8", marker="v", label="IMO 2023 asgari kontrol noktası (2008'e göre)")
    ax2.scatter([], [], color="#22c55e", marker="v", label="IMO 2023 'çaba' kontrol noktası")
ax2.set_ylabel("MtCO₂e", color="#cbd5e1")
ax2.set_title("B) Bunker yakıtı CO₂ ve IMO 2023 kontrol noktaları (ölçek karşılaştırması)", color="#f8fafc", fontweight="bold"); ax2.legend(**leg)

ax3 = axes[1, 0]
for iso, c in [("TUR", "#f43f5e"), ("GRC", "#38bdf8"), ("ITA", "#22c55e"), ("NOR", "#f59e0b")]:
    m = oecd_month[iso]; ax3.plot(pd.to_datetime(m["period"].str[:7]), m["value"] / 1e6, color=c, lw=1.4, label=iso)
ax3.set_ylabel("Mt CO₂ / ay", color="#cbd5e1")
ax3.set_title("C) Aylık denizcilik CO₂ — OECD (SEEA ikamet ilkesi)", color="#f8fafc", fontweight="bold"); ax3.legend(**leg)

ax4 = axes[1, 1]
ax4.barh(df_int["ISO"], df_int["t CO₂ / bin DWT"], color=["#f43f5e" if i == "TUR" else "#38bdf8" for i in df_int["ISO"]])
ax4.set_xlabel("t CO₂ / bin DWT (sahipli filo)", color="#cbd5e1")
ax4.set_title("D) Kaba emisyon yoğunluğu göstergesi (IMO CII değildir)", color="#f8fafc", fontweight="bold")

fig.suptitle("GOMD — Vaka Çalışması 2: Ulusal ticaret filoları ve denizcilik emisyonları (gerçek veri)", color="#ffffff", fontsize=12.5, fontweight="bold")
plt.tight_layout()
fig.savefig("cs02_maritime_decarbonization_cii_ets_fueleu.png", dpi=140, bbox_inches="tight", facecolor=fig.get_facecolor())
plt.show()
