#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Doğu Akdeniz, Ege ve Küresel Deniz Darboğazlarında Yüksek Frekanslı Met-Ocean Telemetrisi: Gumbel 100-Yıllık Ekstrem Dalga, OU Termal Hafıza ve Sabit Etkiler Paneli
High-Frequency Met-Ocean Telemetry Across Mediterranean Basins & Global Chokepoints: Gumbel Return Levels, Ornstein–Uhlenbeck Thermal Memory & Fixed-Effects Panel
==============================================================================
GOMD Python SDK v2.0.0 — Official 100% Real-Data Reproducible Case Study
Google Colab Install: !pip install -q --force-reinstall --no-cache-dir https://gomd.pirireis.edu.tr/sdk/dist/gomd-2.0.0-py3-none-any.whl
"""

# ==============================================================================
# ADIM 0: GOMD Python SDK v2.0.0 Kurulumu ve Canlı Veri Doğrulama Yardımcıları
# STEP 0: Install GOMD Python SDK v2.0.0 & Live GOMD Data Verification 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

# Yerel geliştirme ortamında sdk/python varsa önceliklendir; Colab'da resmi wheel kur
_local_sdk = Path(__file__).resolve().parent.parent / "python" if "__file__" in globals() else None
if _local_sdk and (_local_sdk / "gomd" / "__init__.py").is_file():
    if str(_local_sdk) not in sys.path:
        sys.path.insert(0, str(_local_sdk))

_IN_COLAB = "google.colab" in sys.modules
_GOMD_WHEEL_URL = "https://gomd.pirireis.edu.tr/sdk/dist/gomd-2.0.0-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_annual_series(
    indicator: str,
    entity: str = "TUR",
    period_from: int = 1950,
    period_to: int = 2026,
) -> dict:
    """
    GOMD sunucusundan (https://gomd.pirireis.edu.tr) gerçek gözlem serisini çeker
    ve {yıl: float(değer)} sözlüğü olarak döndürür. Sentetik veri üretmez.
    """
    rows = client.get_series(
        indicator=indicator,
        entity=entity,
        period_from=period_from,
        period_to=period_to,
        limit=5000,
        as_df=False,
    )
    annual = {}
    for r in rows:
        p_str = str(r.get("period") or "").strip()
        val = r.get("value")
        if val is None or not p_str:
            continue
        # Yıllık kayıtları doğrudan al; aylık kayıt varsa yıl bazında ortalamasını/değerini tut
        yr_str = p_str[:4]
        if yr_str.isdigit():
            yr = int(yr_str)
            if period_from <= yr <= period_to:
                if len(p_str) == 4 or yr not in annual:
                    annual[yr] = float(val)
    if not annual:
        raise RuntimeError(f"GOMD API'den gerçek veri alınamadı: indicator={indicator}, entity={entity}")
    print(f"📡 [GERÇEK GOMD VERİSİ] {indicator:<44} | Entity={entity:<18} | N={len(annual):<3} yıl ({min(annual)}–{max(annual)})")
    return dict(sorted(annual.items()))


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 — GOMD Bilimsel Veri Konsorsiyumu (COP31 Türkiye)")
print(f"📚 Akademik Atıf / Citation          : {gomd.cite('apa')[:115]}...")

# ==============================================================================
# ADIM 1: 10 Havza ve Darboğaz İçin Gerçek Günlük Met-Ocean Serilerinin Çekimi
# STEP 1: Live Retrieval of Daily Met-Ocean Telemetry Across 10 Basins/Chokepoints
# ==============================================================================
from gomd.ocean import ectotherm_thermal_shock_index, stochastic_sst_memory_ou
from gomd.stats import (
    extreme_return_levels,
    panel_fixed_effects,
)

basins = [
    "OCN_MED_LEVANTINE",
    "OCN_MED_AEGEAN",
    "OCN_MARMARA_STRAITS",
    "OCN_BLACKSEA_CENTRAL",
    "OCN_MED_IONIAN",
    "OCN_MED_WEST",
    "OCN_CHOKE_SUEZ_REDSEA",
    "OCN_CHOKE_GIBRALTAR",
    "OCN_CHOKE_HORMUZ",
    "OCN_CHOKE_BABELMANDEB",
]

met_summary = []
all_daily_rows = []
lev_daily_df = None

for b_code in basins:
    sst_r  = client.get_series("metocean_global_basin_sst_mean_c", entity=b_code, as_df=False)
    hs_r   = client.get_series("metocean_global_basin_wave_height_max_m", entity=b_code, as_df=False)
    tp_r   = client.get_series("metocean_global_basin_wave_period_max_s", entity=b_code, as_df=False)
    sw_r   = client.get_series("metocean_global_basin_swell_height_max_m", entity=b_code, as_df=False)
    ww_r   = client.get_series("metocean_global_basin_wind_wave_height_max_m", entity=b_code, as_df=False)
    cur_r  = client.get_series("metocean_global_basin_current_velocity_max_ms", entity=b_code, as_df=False)

    by_date = {}
    for label, rows in [("sst", sst_r), ("hs", hs_r), ("tp", tp_r), ("swell", sw_r), ("ww", ww_r), ("cur", cur_r)]:
        for r in rows:
            d = str(r.get("period") or "")
            if d and r.get("value") is not None:
                by_date.setdefault(d, {})[label] = float(r["value"])

    valid_dates = sorted([d for d, vals in by_date.items() if len(vals) == 6])
    print(f"📡 [GERÇEK MET-OCEAN TELEMETRİSİ] {b_code:<22} | N={len(valid_dates)} gün ({valid_dates[0]} -> {valid_dates[-1]})")

    b_rows = [{"basin": b_code, "date": d, **by_date[d]} for d in valid_dates]
    all_daily_rows.extend(b_rows)
    if b_code == "OCN_MED_LEVANTINE":
        lev_daily_df = pd.DataFrame(b_rows)

    sst_vals = [by_date[d]["sst"] for d in valid_dates]
    hs_vals  = [by_date[d]["hs"] for d in valid_dates]
    cur_vals = [by_date[d]["cur"] for d in valid_dates]

    ev_hs = extreme_return_levels(hs_vals, return_periods=(10, 50, 100))
    ou_sst = stochastic_sst_memory_ou(sst_vals, dt_days=1.0)
    ect = ectotherm_thermal_shock_index(sst_series=sst_vals, dt_days=1.0)

    met_summary.append({
        "Basin": b_code.replace("OCN_", ""),
        "Days": len(valid_dates),
        "Mean_SST_C": round(float(np.mean(sst_vals)), 2),
        "OU_Memory_Days": round(ou_sst["thermal_memory_tau_days"], 2),
        "Max_Hs_Obs_m": round(float(np.max(hs_vals)), 2),
        "Gumbel_Hs_100yr_m": ev_hs["return_levels"]["return_level_100yr"],
        "Max_Current_ms": round(float(np.max(cur_vals)), 3),
        "Max_Q10_Surge": ect["max_q10_metabolic_demand_multiplier"],
    })

df_met = pd.DataFrame(met_summary)
print("\n🌊 10 Küresel Havza ve Darboğazda Gerçek Met-Ocean Ekstrem Dalga & Termal Hafıza Tablosu:")
print(df_met.to_string(index=False))

fe_wave = panel_fixed_effects(all_daily_rows, entity_col="basin", y_col="hs", x_col="swell")
print(f"\n📐 Havza Sabit Etkiler (FE) Panel Regresyonu (N={fe_wave['n_obs']} günlük gözlem, 10 havza): β_FE(Swell -> Hs) = {fe_wave['beta_fe']:+.4f} (t = {fe_wave['t_stat']:.2f}, Within R² = {fe_wave['r_squared_within']:.4f})")

# ==============================================================================
# ADIM 2: Doğu Akdeniz Günlük Dalga/SST Telemetrisi ve 10 Havza Gumbel Tasarım Dalgası
# STEP 2: Visualization of Eastern Med Daily Telemetry & 10-Basin Gumbel Return Waves
# ==============================================================================
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(13.5, 5.0), dpi=120)
fig.patch.set_facecolor("#071324")
for ax in (ax1, ax2):
    ax.set_facecolor("#0b1d36")
    ax.tick_params(colors="#cbd5e1")
    for s in ax.spines.values():
        s.set_color("#1e3a5f")

# Panel A: Doğu Akdeniz (OCN_MED_LEVANTINE) Gerçek Günlük Dalga Boyu (Hs), Swell ve Rüzgar Dalgası
x_days = np.arange(len(lev_daily_df))
ax1.plot(x_days, lev_daily_df["hs"], color="#38bdf8", lw=2.0, label="Toplam Belirgin Dalga Hs (m)")
ax1.plot(x_days, lev_daily_df["swell"], color="#22c55e", lw=1.6, ls="--", label="Solugan (Swell) Yüksekliği (m)")
ax1.plot(x_days, lev_daily_df["ww"], color="#f59e0b", lw=1.5, ls=":", label="Rüzgar Dalgası Yüksekliği (m)")
ax1.set_title("A) Doğu Akdeniz (OCN_MED_LEVANTINE) Günlük Dalga Telemetrisi", color="#f8fafc", fontweight="bold")
ax1.set_xlabel("Gün İndeksi (2025–2026 Gözlem Penceresi)", color="#cbd5e1")
ax1.set_ylabel("Dalga Yüksekliği (m)", color="#cbd5e1")
ax1.legend(facecolor="#0f172a", edgecolor="#334155", labelcolor="#f8fafc", fontsize=8)
ax1.grid(alpha=0.18, color="#64748b")

# Panel B: 10 Havza/Darboğazda Gözlenen Maksimum Hs vs Gumbel T=100 Dönüş Seviyesi
x_b = np.arange(len(df_met))
ax2.bar(x_b - 0.18, df_met["Max_Hs_Obs_m"], width=0.35, color="#38bdf8", label="Gözlenen Maksimum Hs (m)")
ax2.bar(x_b + 0.18, df_met["Gumbel_Hs_100yr_m"], width=0.35, color="#f43f5e", label="Gumbel T=100 Tasarım Dalgası (m)")
ax2.set_xticks(x_b)
ax2.set_xticklabels(df_met["Basin"], rotation=28, ha="right", fontsize=8)
ax2.set_title("B) 10 Havza & Darboğazda Gumbel Ekstrem Dalga Yüksekliği", color="#f8fafc", fontweight="bold")
ax2.set_ylabel("Belirgin Dalga Yüksekliği Hs (m)", color="#cbd5e1")
ax2.legend(facecolor="#0f172a", edgecolor="#334155", labelcolor="#f8fafc", fontsize=8)
ax2.grid(alpha=0.18, color="#64748b")

fig.suptitle("GOMD Python SDK v2.0.0 — Vaka Çalışması 8: Yüksek Frekanslı Met-Ocean & Gumbel Ekstrem Dalga Analizi", color="#ffffff", fontsize=12.5, fontweight="bold", y=1.01)
plt.tight_layout()
fig.savefig("cs08_high_frequency_metocean_wave_extremes_chokepoints.png", dpi=140, bbox_inches="tight", facecolor=fig.get_facecolor())
plt.show()
