"""
Exploration v4: Using correct POST parameters discovered from GIPS JS.

Critical findings from gips.map.gisMapWrapper.js:

1. findGeom - POST with:
   - path: naviKey (layer name like "building_estate")
   - gid: geometry ID
   - proj: projection code

2. loadImageByApKey - POST with:
   - naviKey: layer name
   - apKey: AP identifier

3. searchByDistance - requires 'lon' param

4. dataTransmissionAPI - requires JSON in 'query' param with 'target' field

5. getCentroid - POST with naviKey

All calls use _olPostAsync (jQuery POST to the URL).
"""
import sys
import os
import json
import time
import re
import urllib3
import requests
from pathlib import Path
from datetime import datetime

sys.stdout.reconfigure(encoding='utf-8')
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

BASE_URL = "https://ymspace.ga.nycu.edu.tw/gisweb/public/route.htm"
GISWEB_BASE = "https://ymspace.ga.nycu.edu.tw/gisweb"
OUTPUT_DIR = Path(r"C:\Users\thc1006\Desktop\NQSD\新增資料夾\data\ymmap_archive\route_data\v4")
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

SESSION = requests.Session()
SESSION.verify = False
SESSION.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
    "Accept": "application/json, */*",
    "Referer": "https://ymspace.ga.nycu.edu.tw/gisweb/public/route.htm",
    "X-Requested-With": "XMLHttpRequest",
})

DELAY = 0.25
total_requests = 0
all_hits = []


def post_route(action, data, label=""):
    """POST to route.htm with action as query param and data as form body."""
    global total_requests
    total_requests += 1
    url = f"{BASE_URL}?action={action}"
    try:
        resp = SESSION.post(url, data=data, timeout=15)
        ct = resp.headers.get("Content-Type", "")
        result = {
            "status": resp.status_code,
            "content_type": ct,
            "length": len(resp.content),
            "label": label,
        }

        try:
            result["data"] = resp.json()
            result["is_json"] = True
        except (json.JSONDecodeError, ValueError):
            result["data"] = resp.text.strip()
            result["is_json"] = False

        # Check for errors
        is_error = False
        if result["is_json"] and isinstance(result["data"], dict):
            msg = str(result["data"].get("message", "")) + str(result["data"].get("msg", ""))
            if any(x in msg for x in ["Exception", "null", "error", "Error", "not present", "not met"]):
                is_error = True
            if result["data"].get("success") is False:
                is_error = True
        elif result["status"] >= 400:
            is_error = True

        result["is_error"] = is_error
        result["is_hit"] = not is_error and result["length"] > 5

        return result
    except Exception as e:
        return {"error": str(e), "is_hit": False, "is_error": True, "label": label}


def get_route(action, params, label=""):
    """GET from route.htm."""
    global total_requests
    total_requests += 1
    full_params = {"action": action, **params}
    try:
        resp = SESSION.get(BASE_URL, params=full_params, timeout=15)
        ct = resp.headers.get("Content-Type", "")
        result = {
            "status": resp.status_code,
            "content_type": ct,
            "length": len(resp.content),
            "label": label,
        }

        try:
            result["data"] = resp.json()
            result["is_json"] = True
        except (json.JSONDecodeError, ValueError):
            result["data"] = resp.text.strip()
            result["is_json"] = False

        is_error = False
        if result["is_json"] and isinstance(result["data"], dict):
            msg = str(result["data"].get("message", "")) + str(result["data"].get("msg", ""))
            if any(x in msg for x in ["Exception", "null", "error", "Error", "not present", "not met", "Incorrect"]):
                is_error = True
            if result["data"].get("success") is False:
                is_error = True
        elif result["status"] >= 400:
            is_error = True

        result["is_error"] = is_error
        result["is_hit"] = not is_error and result["length"] > 5

        return result
    except Exception as e:
        return {"error": str(e), "is_hit": False, "is_error": True, "label": label}


def save(filename, data):
    filepath = OUTPUT_DIR / filename
    if isinstance(data, (dict, list)):
        with open(filepath, "w", encoding="utf-8") as f:
            json.dump(data, f, ensure_ascii=False, indent=2)
    elif isinstance(data, str):
        with open(filepath, "w", encoding="utf-8") as f:
            f.write(data)
    else:
        with open(filepath, "wb") as f:
            f.write(data)
    return filepath


def log_result(result, extra=""):
    label = result.get("label", "")
    if result.get("is_hit"):
        data = result.get("data")
        preview = ""
        if isinstance(data, (dict, list)):
            preview = json.dumps(data, ensure_ascii=False)[:300]
        elif isinstance(data, str):
            preview = data[:300]
        print(f"  [HIT] {label} (status={result['status']}, len={result['length']})")
        print(f"         {preview}")
        all_hits.append({"label": label, "length": result["length"], "extra": extra})
        return True
    else:
        data = result.get("data", {})
        msg = ""
        if isinstance(data, dict):
            msg = str(data.get("message", ""))[:120]
        elif isinstance(data, str):
            msg = data[:120]
        if msg and extra:
            print(f"  [{extra}] {label}: {msg}")
        return False


# ============================================================
# PHASE 1: findGeom via POST with path/gid/proj
# ============================================================
def phase1_findGeom():
    print("=" * 70)
    print("PHASE 1: findGeom via POST (path, gid, proj)")
    print("=" * 70)

    results = {}

    # From the JS: me._olPostAsync(me._getPublicUrlInApp('route.htm?action=findGeom'),
    #   { path: naviKey, gid: gid, proj: me.getProj().getCode() })
    # The map uses EPSG:3826 (TWD97/TM2)
    projections = ["EPSG:3826", "EPSG:4326", "EPSG:900913", "EPSG:3857"]

    # Try various naviKey (path) values - from map.htm we know "building_estate"
    navi_keys = [
        "building_estate",
        "building", "route", "floor", "room", "node", "edge",
        "navi", "indoor", "outdoor", "campus", "ap", "wifi",
        "path", "network", "facility", "poi",
        # From map.htm: workspace is 'ntuga'
        "ntuga:building_estate",
        "ntuga:route", "ntuga:building", "ntuga:floor",
        "ntuga:node", "ntuga:edge", "ntuga:navi",
        "ntuga:indoor",
    ]

    # Test with different gid values
    gids = ["1", "2", "3", "10", "100", "Y001", "B001", "P001"]

    # First: try each naviKey with gid=1 and EPSG:3826
    print("\n  --- Testing naviKeys with gid=1 ---")
    for nk in navi_keys:
        for proj in projections[:2]:  # Just try 3826 and 4326
            data = {"path": nk, "gid": "1", "proj": proj}
            label = f"findGeom path={nk} gid=1 proj={proj}"
            result = post_route("findGeom", data, label)
            time.sleep(DELAY)

            if log_result(result, "info"):
                safe = re.sub(r'[^\w]', '_', f"{nk}_{proj}")[:60]
                save(f"findGeom_{safe}_gid1.json", result["data"])
                results[label] = result["data"]
            else:
                # Show error only for first projection
                if proj == "EPSG:3826":
                    log_result(result, "err")

    # Second: if we found working naviKeys, try more gids
    if results:
        working_keys = [k.split("path=")[1].split(" ")[0] for k in results.keys()]
        print(f"\n  --- Testing working keys with various gids ---")
        for nk in set(working_keys):
            for gid in gids:
                data = {"path": nk, "gid": gid, "proj": "EPSG:3826"}
                label = f"findGeom path={nk} gid={gid}"
                result = post_route("findGeom", data, label)
                time.sleep(DELAY)

                if log_result(result):
                    safe = re.sub(r'[^\w]', '_', f"{nk}_gid{gid}")[:60]
                    save(f"findGeom_{safe}.json", result["data"])
                    results[label] = result["data"]

    # Third: try without gid (to get all geometries)
    print("\n  --- Testing without gid (get all) ---")
    for nk in navi_keys[:10]:
        data = {"path": nk, "proj": "EPSG:3826"}
        label = f"findGeom path={nk} no_gid"
        result = post_route("findGeom", data, label)
        time.sleep(DELAY)
        if log_result(result, "info"):
            safe = re.sub(r'[^\w]', '_', nk)[:40]
            save(f"findGeom_{safe}_all.json", result["data"])
            results[label] = result["data"]

    # Fourth: try without path (maybe it lists available paths?)
    print("\n  --- Testing without path ---")
    for proj in projections:
        data = {"proj": proj}
        label = f"findGeom no_path proj={proj}"
        result = post_route("findGeom", data, label)
        time.sleep(DELAY)
        if log_result(result, "info"):
            save(f"findGeom_nopath_{proj.replace(':', '_')}.json", result["data"])
            results[label] = result["data"]

    save("_findGeom_results.json", {"hit_count": len(results), "labels": list(results.keys())})
    print(f"\n  findGeom total hits: {len(results)}")
    return results


# ============================================================
# PHASE 2: loadImageByApKey via POST with naviKey/apKey
# ============================================================
def phase2_loadImage():
    print("\n" + "=" * 70)
    print("PHASE 2: loadImageByApKey via POST (naviKey, apKey)")
    print("=" * 70)

    results = {}

    navi_keys = [
        "building_estate", "building", "route", "floor", "room",
        "node", "edge", "navi", "indoor", "outdoor", "campus",
        "ap", "wifi", "path", "network",
    ]

    ap_keys = [str(i) for i in range(1, 51)] + [
        "Y001", "Y002", "B001", "P001",
        "AP001", "wifi-001",
    ]

    # Test each naviKey with apKey=1
    print("\n  --- Testing naviKeys with apKey=1 ---")
    for nk in navi_keys:
        data = {"naviKey": nk, "apKey": "1"}
        label = f"loadImage naviKey={nk} apKey=1"
        result = post_route("loadImageByApKey", data, label)
        time.sleep(DELAY)

        if log_result(result, "info"):
            safe = re.sub(r'[^\w]', '_', nk)[:40]
            save(f"loadImage_{safe}_ap1.json", result["data"])
            results[label] = result["data"]
        else:
            log_result(result, "err")

    # Test numeric apKeys without naviKey
    print("\n  --- Testing numeric apKeys 1-50 ---")
    for ap_id in range(1, 51):
        data = {"apKey": str(ap_id)}
        label = f"loadImage apKey={ap_id}"
        result = post_route("loadImageByApKey", data, label)
        time.sleep(DELAY)

        if log_result(result):
            save(f"loadImage_ap{ap_id}.json", result["data"])
            results[f"apKey={ap_id}"] = result["data"]

    save("_loadImage_results.json", {"hit_count": len(results)})
    print(f"\n  loadImage total hits: {len(results)}")
    return results


# ============================================================
# PHASE 3: searchByDistance via POST with lon, lat
# ============================================================
def phase3_searchByDistance():
    print("\n" + "=" * 70)
    print("PHASE 3: searchByDistance (lon, lat required)")
    print("=" * 70)

    results = {}

    # Yang Ming campus coords
    # EPSG:4326 (WGS84)
    ym_lat_4326 = 25.0218
    ym_lon_4326 = 121.5169

    # EPSG:3826 (TWD97/TM2) approximate
    ym_x_3826 = 304500
    ym_y_3826 = 2767700

    navi_keys = ["building_estate", "building", "route", "indoor", "navi", "node"]

    tests = [
        # GET with lon, lat
        ("GET", {"lon": str(ym_lon_4326), "lat": str(ym_lat_4326)}),
        ("GET", {"lon": str(ym_lon_4326), "lat": str(ym_lat_4326), "distance": "500"}),
        ("GET", {"lon": str(ym_lon_4326), "lat": str(ym_lat_4326), "distance": "1000"}),
        ("GET", {"lon": str(ym_lon_4326), "lat": str(ym_lat_4326), "naviKey": "building_estate"}),
        ("GET", {"lon": str(ym_lon_4326), "lat": str(ym_lat_4326), "naviKey": "building_estate", "distance": "500"}),
        # With TWD97 coords
        ("GET", {"lon": str(ym_x_3826), "lat": str(ym_y_3826)}),
        ("GET", {"lon": str(ym_x_3826), "lat": str(ym_y_3826), "proj": "EPSG:3826"}),
        ("GET", {"lon": str(ym_x_3826), "lat": str(ym_y_3826), "distance": "500"}),
    ]

    for method, params in tests:
        label = f"searchByDistance {' '.join(f'{k}={v}' for k,v in params.items())}"

        if method == "GET":
            result = get_route("searchByDistance", params, label)
        else:
            result = post_route("searchByDistance", params, label)
        time.sleep(DELAY)

        if log_result(result, "info"):
            safe = re.sub(r'[^\w]', '_', label)[:80]
            save(f"searchDist_{safe}.json", result["data"])
            results[label] = result["data"]
        else:
            log_result(result, "err")

    # POST versions
    print("\n  --- Testing POST ---")
    for nk in navi_keys:
        for coords in [(ym_lon_4326, ym_lat_4326), (ym_x_3826, ym_y_3826)]:
            data = {
                "naviKey": nk,
                "lon": str(coords[0]),
                "lat": str(coords[1]),
                "distance": "500",
            }
            label = f"POST searchByDistance nk={nk} lon={coords[0]}"
            result = post_route("searchByDistance", data, label)
            time.sleep(DELAY)

            if log_result(result, "info"):
                safe = re.sub(r'[^\w]', '_', f"{nk}_{coords[0]}")[:60]
                save(f"searchDist_{safe}.json", result["data"])
                results[label] = result["data"]

    save("_searchByDistance_results.json", {"hit_count": len(results)})
    print(f"\n  searchByDistance total hits: {len(results)}")
    return results


# ============================================================
# PHASE 4: getCentroid via POST
# ============================================================
def phase4_getCentroid():
    print("\n" + "=" * 70)
    print("PHASE 4: getCentroid (naviKey required)")
    print("=" * 70)

    results = {}

    navi_keys = [
        "building_estate", "building", "route", "floor", "room",
        "node", "navi", "indoor", "campus",
    ]
    gids = ["1", "2", "3", "10", "100", "Y001", "B001"]

    # POST with various naviKey + gid combos
    for nk in navi_keys:
        for gid in gids[:3]:
            data = {"naviKey": nk, "gid": gid}
            label = f"getCentroid naviKey={nk} gid={gid}"
            result = post_route("getCentroid", data, label)
            time.sleep(DELAY)

            if log_result(result, "info"):
                safe = re.sub(r'[^\w]', '_', f"{nk}_gid{gid}")[:60]
                save(f"centroid_{safe}.json", result["data"])
                results[label] = result["data"]

    # Try with path instead of naviKey
    for nk in navi_keys[:5]:
        data = {"path": nk, "gid": "1"}
        label = f"getCentroid path={nk} gid=1"
        result = post_route("getCentroid", data, label)
        time.sleep(DELAY)
        if log_result(result, "info"):
            save(f"centroid_path_{nk}.json", result["data"])
            results[label] = result["data"]

    save("_getCentroid_results.json", {"hit_count": len(results)})
    print(f"\n  getCentroid total hits: {len(results)}")
    return results


# ============================================================
# PHASE 5: dataTransmissionAPI with JSON query + target
# ============================================================
def phase5_dataTransmission():
    print("\n" + "=" * 70)
    print("PHASE 5: dataTransmissionAPI (JSON query with target)")
    print("=" * 70)

    results = {}

    # The error said "The target must be provided" when we sent JSON
    # So the query param needs to be a JSON string with a "target" field
    queries = [
        {"target": "route"},
        {"target": "building"},
        {"target": "building_estate"},
        {"target": "node"},
        {"target": "edge"},
        {"target": "floor"},
        {"target": "room"},
        {"target": "navi"},
        {"target": "indoor"},
        {"target": "outdoor"},
        {"target": "campus"},
        {"target": "ap"},
        {"target": "wifi"},
        {"target": "path"},
        {"target": "network"},
        {"target": "layer"},
        {"target": "poi"},
        {"target": "facility"},
        # With additional params
        {"target": "route", "type": "all"},
        {"target": "building", "type": "all"},
        {"target": "building_estate", "type": "all"},
        {"target": "building_estate", "buildId": "Y001"},
        {"target": "route", "from": "Y001", "to": "Y002"},
        {"target": "node", "buildId": "Y001"},
        {"target": "indoor", "buildId": "Y001"},
        # ntuga workspace
        {"target": "ntuga:building_estate"},
        {"target": "ntuga:route"},
        {"target": "ntuga:building"},
    ]

    for q in queries:
        q_str = json.dumps(q)
        label = f"dataTransmission target={q.get('target', '?')}"
        if len(q) > 1:
            label += f" +{len(q)-1}params"

        # GET with query as JSON string
        result = get_route("dataTransmissionAPI", {"query": q_str}, label)
        time.sleep(DELAY)

        if log_result(result, "info"):
            safe = re.sub(r'[^\w]', '_', json.dumps(q))[:60]
            save(f"dataTrans_{safe}.json", result["data"])
            results[label] = result["data"]
        else:
            log_result(result, "err")

    # Also try POST
    print("\n  --- Testing POST with query ---")
    for q in queries[:10]:
        q_str = json.dumps(q)
        label = f"POST dataTransmission target={q.get('target', '?')}"
        result = post_route("dataTransmissionAPI", {"query": q_str}, label)
        time.sleep(DELAY)
        if log_result(result, "info"):
            safe = re.sub(r'[^\w]', '_', json.dumps(q))[:60]
            save(f"dataTrans_POST_{safe}.json", result["data"])
            results[label] = result["data"]

    save("_dataTransmission_results.json", {"hit_count": len(results)})
    print(f"\n  dataTransmission total hits: {len(results)}")
    return results


# ============================================================
# PHASE 6: getHeaders and findAll via POST with proper params
# ============================================================
def phase6_headers_findall():
    print("\n" + "=" * 70)
    print("PHASE 6: getHeaders & findAll via POST")
    print("=" * 70)

    results = {}

    # findAll error said tableName is null in the comparison function
    # This suggests the param IS reaching the server but being compared differently
    # Maybe it needs to be sent as a specific field in a JSON body?

    table_names = [
        "building_estate", "route", "building", "floor", "room",
        "node", "edge", "navi", "indoor", "layer",
        "ntuga:building_estate", "ntuga:route",
    ]

    # getHeaders - try various param combos
    print("\n  --- getHeaders ---")
    for tname in table_names:
        # Standard form POST
        result = post_route("getHeaders", {"tableName": tname}, f"getHeaders POST tableName={tname}")
        time.sleep(DELAY)
        if log_result(result, "info"):
            save(f"headers_{tname.replace(':', '_')}.json", result["data"])
            results[f"headers_{tname}"] = result["data"]
        else:
            log_result(result, "err")

        # Try with 'path' param (like findGeom uses)
        result = post_route("getHeaders", {"path": tname}, f"getHeaders POST path={tname}")
        time.sleep(DELAY)
        if log_result(result, "info"):
            save(f"headers_path_{tname.replace(':', '_')}.json", result["data"])
            results[f"headers_path_{tname}"] = result["data"]

        # Try with 'naviKey' param
        result = post_route("getHeaders", {"naviKey": tname}, f"getHeaders POST naviKey={tname}")
        time.sleep(DELAY)
        if log_result(result, "info"):
            save(f"headers_nk_{tname.replace(':', '_')}.json", result["data"])
            results[f"headers_nk_{tname}"] = result["data"]

    # findAll - try via POST
    print("\n  --- findAll ---")
    for tname in table_names:
        result = post_route("findAll", {"tableName": tname}, f"findAll POST tableName={tname}")
        time.sleep(DELAY)
        if log_result(result, "info"):
            save(f"findAll_{tname.replace(':', '_')}.json", result["data"])
            results[f"findAll_{tname}"] = result["data"]
        else:
            log_result(result, "err")

        # Try path param
        result = post_route("findAll", {"path": tname}, f"findAll POST path={tname}")
        time.sleep(DELAY)
        if log_result(result):
            save(f"findAll_path_{tname.replace(':', '_')}.json", result["data"])
            results[f"findAll_path_{tname}"] = result["data"]

    save("_headers_findall_results.json", {"hit_count": len(results)})
    print(f"\n  getHeaders/findAll total hits: {len(results)}")
    return results


# ============================================================
# PHASE 7: Explore the JS wrapper more deeply
# ============================================================
def phase7_deep_js_analysis():
    print("\n" + "=" * 70)
    print("PHASE 7: Deep JS wrapper analysis for all API methods")
    print("=" * 70)

    js_file = Path(r"C:\Users\thc1006\Desktop\NQSD\新增資料夾\data\ymmap_archive\route_data\v3\js_gips.map.gisMapWrapper.js")
    if not js_file.exists():
        print("  JS wrapper file not found!")
        return

    text = js_file.read_text(encoding="utf-8", errors="replace")

    # Find ALL function definitions
    # Look for method definitions in object literal style
    methods = re.findall(r'(\w+)\s*:\s*function\s*\(([^)]*)\)', text)
    print(f"  Found {len(methods)} methods in wrapper:")
    for name, params in methods:
        print(f"    {name}({params})")

    # Find all _olPostAsync and _olGetAsync calls
    post_calls = re.findall(
        r'_olPostAsync\s*\(\s*[^,]+["\']([^"\']+)["\'][^,]*,\s*\{([^}]+)\}',
        text, re.DOTALL
    )
    print(f"\n  POST API calls ({len(post_calls)}):")
    for url_part, params_block in post_calls:
        # Clean up params
        param_names = re.findall(r'(\w+)\s*:', params_block)
        print(f"    POST {url_part} -> {param_names}")

    get_calls = re.findall(
        r'_olGetAsync\s*\(\s*[^,]+["\']([^"\']+)["\'][^,]*,\s*\{([^}]+)\}',
        text, re.DOTALL
    )
    print(f"\n  GET API calls ({len(get_calls)}):")
    for url_part, params_block in get_calls:
        param_names = re.findall(r'(\w+)\s*:', params_block)
        print(f"    GET {url_part} -> {param_names}")

    # Look for all URL patterns
    all_urls = re.findall(r'_getPublicUrlInApp\s*\(["\']([^"\']+)["\']\)', text)
    print(f"\n  Public URL endpoints:")
    for url in sorted(set(all_urls)):
        print(f"    {url}")

    # Look for naviKey usage patterns
    navi_patterns = re.findall(r'naviKey\s*[:=]\s*([^\n,;}{]+)', text)
    print(f"\n  naviKey assignments ({len(navi_patterns)}):")
    for p in navi_patterns[:20]:
        print(f"    naviKey = {p.strip()}")

    # Find _getNaviKeyByOLayerName
    navi_func_match = re.search(r'_getNaviKeyByOLayerName\s*:\s*function[^{]*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}', text, re.DOTALL)
    if navi_func_match:
        print(f"\n  _getNaviKeyByOLayerName function body:")
        body = navi_func_match.group(1)
        print(f"    {body[:500]}")

    # Save comprehensive analysis
    analysis = {
        "methods": [{"name": n, "params": p} for n, p in methods],
        "post_calls": [{"url": u, "params": re.findall(r'(\w+)\s*:', p)} for u, p in post_calls],
        "get_calls": [{"url": u, "params": re.findall(r'(\w+)\s*:', p)} for u, p in get_calls],
        "public_urls": sorted(set(all_urls)),
    }
    save("_deep_js_analysis.json", analysis)

    return analysis


# ============================================================
# PHASE 8: Search with proper schema param
# ============================================================
def phase8_search():
    print("\n" + "=" * 70)
    print("PHASE 8: search action - try to find the right schema")
    print("=" * 70)

    results = {}

    # The error was "Schema 'null' does not exist" - the schema param isn't being read
    # Maybe it needs to be sent differently

    # Try POST with schema
    schemas = [
        "public", "gis", "navi", "campus", "indoor", "route",
        "building", "ym", "yangming", "ntuga",
    ]

    search_terms = ["Y001", "building", "1"]

    for schema in schemas:
        for term in search_terms[:1]:
            # Form POST
            data = {"schema": schema, "keyword": term}
            result = post_route("search", data, f"search POST schema={schema} keyword={term}")
            time.sleep(DELAY)
            if log_result(result, "info"):
                save(f"search_{schema}_{term}.json", result["data"])
                results[f"{schema}_{term}"] = result["data"]

            # Try with 'q' instead
            data = {"schema": schema, "q": term}
            result = post_route("search", data, f"search POST schema={schema} q={term}")
            time.sleep(DELAY)
            if log_result(result):
                save(f"search_{schema}_q_{term}.json", result["data"])
                results[f"{schema}_q_{term}"] = result["data"]

    save("_search_results.json", {"hit_count": len(results)})
    return results


# ============================================================
# PHASE 9: getLayerInfo with the right layer names
# ============================================================
def phase9_getLayerInfo():
    print("\n" + "=" * 70)
    print("PHASE 9: getLayerInfo - try more layer names")
    print("=" * 70)

    results = {}

    # The previous test showed "expected 1, actual 0" - meaning the query works
    # but no matching layer was found. Try more names.
    layer_names = [
        # From map.htm
        "building_estate", "ntu_base", "ntu_base_en",
        "building_estate_127",
        # NAVI_LAYER format
        "NAVI_LAYER_127", "NAVI_LAYER_1", "NAVI_LAYER_2", "NAVI_LAYER_3",
        "NAVI_LAYER_4", "NAVI_LAYER_5", "NAVI_LAYER_10", "NAVI_LAYER_20",
        "NAVI_LAYER_50", "NAVI_LAYER_100",
        # Numbered
        "1", "2", "3", "4", "5", "10", "20", "50", "100", "127",
        # YM specific
        "ym_building", "ym_floor", "ym_route", "ym_indoor",
        "ym_base", "ym_campus",
        # GeoServer layer names
        "ntuga:building_estate", "ntuga:ntu_base",
        # Generic
        "base", "default", "main", "all",
    ]

    for lname in layer_names:
        result = get_route("getLayerInfo", {"layerName": lname}, f"getLayerInfo layerName={lname}")
        time.sleep(DELAY)

        data = result.get("data", {})
        if isinstance(data, dict):
            success = data.get("success")
            msg = data.get("msg", "")
            if success is True or (success is not False and data.get("data") is not None):
                log_result(result, "HIT")
                save(f"layerInfo_{lname.replace(':', '_')}.json", data)
                results[lname] = data
            elif success is False and "actual 0" in str(msg):
                pass  # No match but query works
            else:
                log_result(result, "info")

    # Also try POST
    print("\n  --- POST ---")
    for lname in layer_names[:10]:
        result = post_route("getLayerInfo", {"layerName": lname}, f"POST getLayerInfo layerName={lname}")
        time.sleep(DELAY)
        data = result.get("data", {})
        if isinstance(data, dict) and data.get("success") is True:
            log_result(result, "HIT")
            save(f"layerInfo_POST_{lname.replace(':', '_')}.json", data)
            results[f"POST_{lname}"] = data

    save("_layerInfo_results.json", {"hit_count": len(results)})
    print(f"\n  getLayerInfo total hits: {len(results)}")
    return results


def main():
    print(f"Route.htm Exploitation v4 - {datetime.now().isoformat()}")
    print(f"Using POST with proper GIPS framework parameters")
    print(f"Output: {OUTPUT_DIR}")
    print()

    # Phase 7 first - understand the JS API
    js_analysis = phase7_deep_js_analysis()

    # Phase 1: findGeom via POST
    findgeom_results = phase1_findGeom()

    # Phase 2: loadImageByApKey via POST
    loadimage_results = phase2_loadImage()

    # Phase 3: searchByDistance
    searchdist_results = phase3_searchByDistance()

    # Phase 4: getCentroid
    centroid_results = phase4_getCentroid()

    # Phase 5: dataTransmissionAPI
    datatrans_results = phase5_dataTransmission()

    # Phase 6: getHeaders/findAll
    headers_results = phase6_headers_findall()

    # Phase 8: search
    search_results = phase8_search()

    # Phase 9: getLayerInfo
    layerinfo_results = phase9_getLayerInfo()

    # Final summary
    print("\n" + "=" * 70)
    print("FINAL SUMMARY v4")
    print("=" * 70)
    print(f"Total requests: {total_requests}")
    print(f"Total hits: {len(all_hits)}")
    for h in all_hits:
        print(f"  - {h['label']} (len={h['length']})")

    save("_FINAL_SUMMARY_v4.json", {
        "date": datetime.now().isoformat(),
        "total_requests": total_requests,
        "hits": all_hits,
    })


if __name__ == "__main__":
    main()
