#!/usr/bin/env python3
# Чтение GPS из EXIF всех фото Hram (по индексу) — пакетно, с ретраями и кэшем результатов
import json, os, io, sys, time, urllib.request, urllib.parse

tok = None
for line in open("/root/site/yandex/.env_hram", encoding="utf-8"):
    if line.startswith("YANDEX2_ACCESS_TOKEN="):
        tok = line.split("=", 1)[1].strip()
H = {"Authorization": f"OAuth {tok}"}

def get_download_url(path):
    url = "https://cloud-api.yandex.net/v1/disk/resources/download?path=" + urllib.parse.quote(path)
    req = urllib.request.Request(url, headers=H)
    with urllib.request.urlopen(req, timeout=60) as r:
        return json.loads(r.read().decode())["href"]

def fetch_head(url, maxbytes=262144):
    req = urllib.request.Request(url, headers={"Range": f"bytes=0-{maxbytes-1}"})
    with urllib.request.urlopen(req, timeout=90) as r:
        return r.read()

def parse_gps(data, ext):
    """Извлекает GPS из EXIF через PIL (jpg/png/tiff) или pillow_heif (heic)."""
    try:
        if ext == ".heic":
            import pillow_heif
            pillow_heif.register_heif_opener()
        from PIL import Image
        from PIL.ExifTags import TAGS, GPSTAGS
        img = Image.open(io.BytesIO(data))
        exif = img.getexif()
        if not exif:
            return None
        gps_info = None
        for tag_id, value in exif.items():
            tag = TAGS.get(tag_id, tag_id)
            if tag == "GPSInfo":
                gps_info = value
                break
        if not gps_info:
            return None
        def get(tag_name):
            for k, v in gps_info.items():
                if GPSTAGS.get(k, k) == tag_name:
                    return v
            return None
        lat_ref = get("GPSLatitudeRef"); lat = get("GPSLatitude")
        lon_ref = get("GPSLongitudeRef"); lon = get("GPSLongitude")
        if not lat or not lon:
            return None
        def to_deg(val):
            d, m, s = float(val[0]), float(val[1]), float(val[2])
            return d + m/60 + s/3600
        lat_d = to_deg(lat) * (-1 if lat_ref == "S" else 1)
        lon_d = to_deg(lon) * (-1 if lon_ref == "W" else 1)
        return (round(lat_d, 6), round(lon_d, 6))
    except Exception:
        return None

# грузим индекс
idx = json.load(open("/root/site/video/hram_photos_index.json"))
photos = []
for folder, items in idx.items():
    for p in items:
        photos.append({"path": p[0], "name": p[1], "size": p[2], "ext": p[3], "folder": folder})

print("Всего фото:", len(photos))

# кэш уже обработанных
CACHE = "/root/site/video/gps_cache.json"
done = {}
if os.path.exists(CACHE):
    done = json.load(open(CACHE, encoding="utf-8"))
print("Уже обработано:", len(done))

results = dict(done)
t0 = time.time()
ok_gps = 0
no_gps = 0
err = 0

for i, ph in enumerate(photos):
    key = ph["path"]
    if key in results:
        if results[key] and results[key].get("gps"):
            ok_gps += 1
        else:
            no_gps += 1
        continue
    try:
        href = get_download_url(key)
        head = fetch_head(href)
        gps = parse_gps(head, ph["ext"])
        results[key] = {"gps": gps, "name": ph["name"], "folder": ph["folder"], "size": ph["size"]}
        if gps:
            ok_gps += 1
        else:
            no_gps += 1
    except Exception as e:
        results[key] = {"gps": None, "name": ph["name"], "folder": ph["folder"], "size": ph["size"], "err": str(e)[:80]}
        err += 1
    if (i + 1) % 50 == 0:
        json.dump(results, open(CACHE, "w", encoding="utf-8"), ensure_ascii=False)
        print(f"  {i+1}/{len(photos)} | GPS: {ok_gps}, без GPS: {no_gps}, ошибок: {err} | {time.time()-t0:.0f}с")

json.dump(results, open(CACHE, "w", encoding="utf-8"), ensure_ascii=False)
print(f"\nГОТОВО: всего {len(results)} | с GPS: {ok_gps} | без GPS: {no_gps} | ошибок: {err} | время {time.time()-t0:.0f}с")
