#!/usr/bin/env python3
# GPS из EXIF всех фото Hram — exifread + ThreadPool (6 потоков) + кэш
import json, io, os, time, urllib.request, urllib.parse
from concurrent.futures import ThreadPoolExecutor, as_completed

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_range(url, maxbytes):
    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 to_deg(val):
    try:
        d, m, s = float(val[0]), float(val[1]), float(val[2])
        return d + m/60 + s/3600
    except Exception:
        return None

def parse_gps_exifread(data):
    try:
        import exifread
        tags = exifread.process_file(io.BytesIO(data), details=False)
        lat = tags.get("GPS GPSLatitude"); lon = tags.get("GPS Longitude") or tags.get("GPS GPSLongitude")
        lat_ref = tags.get("GPS GPSLatitudeRef"); lon_ref = tags.get("GPS GPSLongitudeRef")
        if not lat or not lon:
            return None
        lat_d = to_deg(lat.values) * (-1 if lat_ref and str(lat_ref) == "S" else 1)
        lon_d = to_deg(lon.values) * (-1 if lon_ref and str(lon_ref) == "W" else 1)
        if lat_d is None or lon_d is None:
            return None
        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_cache2.json"
results = {}
if os.path.exists(CACHE):
    results = json.load(open(CACHE, encoding="utf-8"))
print("Уже обработано:", len(results))

pending = [p for p in photos if p["path"] not in results]
print("Осталось обработать:", len(pending))

# префетч download URL (в потоках)
def prep(p):
    try:
        p["href"] = get_download_url(p["path"])
        return p
    except Exception as e:
        p["href"] = None
        p["err"] = str(e)[:80]
        return p

t0 = time.time()
with ThreadPoolExecutor(max_workers=6) as ex:
    pending = list(ex.map(prep, pending))

def work(p):
    if not p.get("href"):
        return p["path"], {"gps": None, "name": p["name"], "folder": p["folder"], "err": p.get("err", "")}
    # heic: качаем до 2.5 МБ (EXIF-бокс может быть глубже), jpg/png: 400 КБ
    maxb = 2_500_000 if p["ext"] == ".heic" else 400_000
    try:
        data = fetch_range(p["href"], maxb)
    except Exception as e:
        return p["path"], {"gps": None, "name": p["name"], "folder": p["folder"], "err": str(e)[:80]}
    gps = parse_gps_exifread(data)
    return p["path"], {"gps": gps, "name": p["name"], "folder": p["folder"], "size": p["size"]}

ok_gps = sum(1 for v in results.values() if v.get("gps"))
no_gps = sum(1 for v in results.values() if not v.get("gps"))
err = sum(1 for v in results.values() if v.get("err"))

done_count = 0
with ThreadPoolExecutor(max_workers=6) as ex:
    futs = [ex.submit(work, p) for p in pending]
    for fut in as_completed(futs):
        try:
            key, val = fut.result()
            results[key] = val
            if val.get("gps"): ok_gps += 1
            elif val.get("err"): err += 1
            else: no_gps += 1
            done_count += 1
            if done_count % 100 == 0:
                json.dump(results, open(CACHE, "w", encoding="utf-8"), ensure_ascii=False)
                print(f"  {done_count}/{len(pending)} | GPS: {ok_gps}, нет: {no_gps}, ошибок: {err} | {time.time()-t0:.0f}с")
        except Exception as e:
            err += 1

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