#!/usr/bin/env python3
"""
Site Grid — Faz 3: SoilGrids'i WCS ile TEK SEFERDE indir.

NEDEN WCS, REST DEĞİL
---------------------
Mevcut motor her analiz için ISRIC REST ucuna gidiyor ve bu ÜRETİM İÇİN UYGUN
DEĞİL: tek istek 6-20 sn sürüyor, altın küme koşusunda 112 noktanın 86'sında
(%77) toprak hiç gelmedi. WCS ile tüm bölgeyi TEK GeoTIFF olarak indirip kendi
ızgaramıza koyunca çalışma zamanında üçüncü-parti çağrı KALMIYOR.

Ölçüldü (2026-09-04): pilot bbox (3°x5°) tek istekte 1,5 sn / 864 KB /
1255x2212 piksel / %2,4 nodata. REST'in aynı bölgeyi nokta nokta vermesi
saatler sürerdi.

İNDİRİLEN KATMANLAR
-------------------
Motorun gerçekten kullandığı alanları üretmek için gereken minimum set:
  phh2o  -> soil.ph                     (skorlamada pH yamuk + alkali yumuşatma)
  sand   -> usdaTexture -> soil.texture (skorlamada doku + drenaj çarpanı)
  silt   -> aynı
  clay   -> aynı
  soc    -> somPct -> usdaTextureClass'ın "Organic" eşiği (>= %20)
Derinlikler: 0-5, 5-15, 15-30 cm (0-30 cm kalınlık ağırlıklı birleştirme için).

NODATA: SoilGrids WCS boş pikseli **0** olarak döndürüyor (doğrulandı: deniz
bbox'ında %70,9 sıfır). pH 0 fiziksel olarak imkânsız, 0 = veri yok.
"""

from __future__ import annotations

import argparse
import sys
import time
import urllib.parse
import urllib.request
from pathlib import Path

from config import PILOT_BBOX, RAW_DIR, TURKEY_BBOX, BBox

WCS_BASE = "https://maps.isric.org/mapserv"
CRS4326 = "http://www.opengis.net/def/crs/EPSG/0/4326"

# Motorun kullandığı özellikler. Fazlasını indirmiyoruz.
PROPERTIES = ["phh2o", "sand", "silt", "clay", "soc"]
DEPTHS = ["0-5cm", "5-15cm", "15-30cm"]

SOIL_DIR = RAW_DIR / "soil"


def wcs_url(prop: str, depth: str, bbox: BBox) -> str:
    q = {
        "map": f"/map/{prop}.map",
        "SERVICE": "WCS",
        "VERSION": "2.0.1",
        "REQUEST": "GetCoverage",
        "COVERAGEID": f"{prop}_{depth}_mean",
        "FORMAT": "image/tiff",
        "SUBSETTINGCRS": CRS4326,
        "OUTPUTCRS": CRS4326,
    }
    # SUBSET iki kez geçtiği için elle ekleniyor (urlencode tekrarlı anahtarı bozar).
    return (
        f"{WCS_BASE}?{urllib.parse.urlencode(q)}"
        f"&SUBSET=X({bbox.west},{bbox.east})&SUBSET=Y({bbox.south},{bbox.north})"
    )


def download(prop: str, depth: str, bbox: BBox, force: bool) -> tuple[Path, float, float]:
    out = SOIL_DIR / f"{prop}_{depth}_{bbox.name}.tif"
    if out.exists() and not force:
        return out, out.stat().st_size / 1024 / 1024, 0.0
    t0 = time.time()
    req = urllib.request.Request(wcs_url(prop, depth, bbox), headers={"User-Agent": "kolayimar-site-grid/1.0"})
    with urllib.request.urlopen(req, timeout=600) as r:  # noqa: S310 (sabit https host)
        data = r.read()
    if len(data) < 1024 or not data[:2] in (b"II", b"MM"):
        raise SystemExit(
            f"HATA: {prop} {depth} için GeoTIFF gelmedi ({len(data)} bayt). "
            f"İlk 200 bayt: {data[:200]!r}"
        )
    out.write_bytes(data)
    return out, len(data) / 1024 / 1024, time.time() - t0


def main() -> int:
    ap = argparse.ArgumentParser()
    ap.add_argument("--full", action="store_true", help="Türkiye'nin tamamı")
    ap.add_argument("--onayliyorum", action="store_true", help="--full için açık onay")
    ap.add_argument("--force", action="store_true")
    args = ap.parse_args()

    if args.full and not args.onayliyorum:
        print("HATA: Türkiye'nin tamamı için --onayliyorum bayrağı şart.", file=sys.stderr)
        return 2

    bbox = TURKEY_BBOX if args.full else PILOT_BBOX
    SOIL_DIR.mkdir(parents=True, exist_ok=True)

    print(f"Kapsam: {bbox.name}  [K{bbox.north} B{bbox.west} G{bbox.south} D{bbox.east}]")
    print(f"Katman: {len(PROPERTIES)} özellik x {len(DEPTHS)} derinlik = {len(PROPERTIES) * len(DEPTHS)}")

    total_mb = 0.0
    total_s = 0.0
    for prop in PROPERTIES:
        for depth in DEPTHS:
            path, mb, secs = download(prop, depth, bbox, args.force)
            total_mb += mb
            total_s += secs
            flag = "" if secs else " (zaten var)"
            print(f"  {prop:6s} {depth:8s} {mb:6.2f} MB {secs:5.1f} sn{flag}")

    print(f"\nTOPLAM: {total_mb:.1f} MB · {total_s:.0f} sn")
    print(f"Ham veri: {SOIL_DIR}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
