"""Refetch OSM POIs adding social/lifestyle categories.

New categories:
  cafe          amenity=cafe
  restaurant    amenity=restaurant | fast_food
  fuel          amenity=fuel
  atm           amenity=atm
  post          amenity=post_office
  worship       amenity=place_of_worship
  trolley_stop  highway=bus_stop + bus=yes; OR amenity=bus_station
  police        amenity=police
  fire          amenity=fire_station
  library       amenity=library

Existing 15 stay; only fetch new and append.
Recompute distances + features.
"""
import sqlite3, pathlib, requests, time, json, math, urllib3
urllib3.disable_warnings()

DB = pathlib.Path(__file__).parent / "analysis.db"
CACHE = pathlib.Path(__file__).parent / "cache" / "overpass_raw.json"

NEW_QUERIES = [
    ("cafe",        '["amenity"="cafe"]'),
    ("restaurant",  '["amenity"~"^(restaurant|fast_food)$"]'),
    ("fuel",        '["amenity"="fuel"]'),
    ("atm",         '["amenity"="atm"]'),
    ("post",        '["amenity"="post_office"]'),
    ("worship",     '["amenity"="place_of_worship"]'),
    ("library",     '["amenity"="library"]'),
    ("police",      '["amenity"="police"]'),
    ("fire",        '["amenity"="fire_station"]'),
    ("bank",        '["amenity"="bank"]'),
]
ENDPOINTS = [
    "https://overpass-api.de/api/interpreter",
    "https://overpass.kumi.systems/api/interpreter",
    "https://overpass.openstreetmap.ru/api/interpreter",
]

def hav(la1,lo1,la2,lo2):
    R=6371000;p1,p2=math.radians(la1),math.radians(la2)
    dp=math.radians(la2-la1);dl=math.radians(lo2-lo1)
    a=math.sin(dp/2)**2+math.cos(p1)*math.cos(p2)*math.sin(dl/2)**2
    return 2*R*math.asin(math.sqrt(a))

def overpass(filt, b):
    q = f"[out:json][timeout:120];(node{filt}({b[0]},{b[1]},{b[2]},{b[3]});way{filt}({b[0]},{b[1]},{b[2]},{b[3]}););out center tags;"
    last = None
    for ep in ENDPOINTS:
        try:
            r = requests.post(ep, data={"data": q}, timeout=180, verify=False,
                              headers={"User-Agent":"gendesign/0.5"})
            if r.ok: return r.json().get("elements", [])
            last = f"{ep} {r.status_code}"
            time.sleep(2)
        except Exception as e:
            last = f"{ep} {e}"; time.sleep(2)
    raise RuntimeError(last)

def main():
    cache = json.loads(CACHE.read_text()) if CACHE.exists() else {}
    conn = sqlite3.connect(DB)
    sites = conn.execute("SELECT site_id, lat, lon FROM sites").fetchall()
    lats=[s[1] for s in sites]; lons=[s[2] for s in sites]
    b = (min(lats)-0.05, min(lons)-0.05, max(lats)+0.05, max(lons)+0.05)
    print(f"BBox: {b}")

    for cat, filt in NEW_QUERIES:
        if cat in cache:
            print(f"  {cat:<12} cached: {len(cache[cat])}")
            continue
        print(f"  {cat:<12} fetching ...", end=" ", flush=True)
        try:
            elems = overpass(filt, b)
            cache[cat] = elems
            print(f"{len(elems)}")
        except Exception as e:
            print(f"FAIL {e}")
            cache[cat] = []
        time.sleep(2)

    CACHE.write_text(json.dumps(cache, ensure_ascii=False))
    print(f"\nCache saved: {CACHE.stat().st_size/1024:.0f} KB ({len(cache)} categories)")

    # Recompute pois table from full cache
    conn.execute("DELETE FROM pois")
    n=0
    for cat, elems in cache.items():
        for el in elems:
            if el["type"]=="node":
                la,lo=el.get("lat"),el.get("lon")
            else:
                c=el.get("center") or {}; la,lo=c.get("lat"),c.get("lon")
            if la is None: continue
            tags=el.get("tags") or {}
            name = tags.get("name") or tags.get("operator") or ""
            for sid,sla,slo in sites:
                d = hav(sla,slo,la,lo)
                if d <= 2000:
                    conn.execute("""INSERT INTO pois(site_id,category,osm_type,osm_id,name,lat,lon,distance_m,raw_tags)
                                    VALUES (?,?,?,?,?,?,?,?,?)""",
                                 (sid,cat,el["type"],str(el["id"]),name,la,lo,d,json.dumps(tags,ensure_ascii=False)))
                    n+=1
    conn.commit()
    print(f"\nrecomputed {n} site-poi pairs")
    print("\nPOI counts per category:")
    for cat,c in conn.execute("SELECT category,count(*) FROM pois GROUP BY 1 ORDER BY 2 DESC").fetchall():
        print(f"  {cat:<14} {c}")
    conn.close()

if __name__ == "__main__":
    main()
