import os
import requests
from bs4 import BeautifulSoup
import subprocess
from math import pi, atan, exp

# 📌 Adjust this to match your tile directory URL
ROOT_URL = "https://node.redfish.com/Documents/kaz/EatonFire/Eaton_NYT/"

# 📌 Set the zoom level you want to use (change as needed)
ZOOM_LEVEL = 16  # Adjust this value to use a different zoom

# Output directories
OUTPUT_DIR = f"tiles_z{ZOOM_LEVEL}"
TILES_LIST_FILE = "tiles.txt"
VRT_FILE = "output.vrt"
GEOTIFF_FILE = "output.tif"

# Function to get Apache directory listing
def get_directory_listing(url):
    try:
        response = requests.get(url)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, "html.parser")
        links = [a['href'] for a in soup.find_all('a', href=True)]
        return [link.strip("/") for link in links if not link.startswith("?") and not link == "../"]
    except Exception as e:
        print(f"⚠️ Failed to fetch directory listing for {url}: {e}")
        return []

# Convert ZXY tile coordinates to geographic bounding box
def tile_to_bbox(x, y, z):
    """Returns (minX, minY, maxX, maxY) in EPSG:3857 for the given ZXY tile."""
    tile_size = 256  # Standard Web Mercator tile size
    initial_resolution = 2 * pi * 6378137 / tile_size
    origin_shift = 2 * pi * 6378137 / 2.0

    def pixels_to_meters(px, py, zoom):
        res = initial_resolution / (2**zoom)
        mx = px * res - origin_shift
        my = origin_shift - py * res
        return mx, my

    minX, minY = pixels_to_meters(x * tile_size, (y + 1) * tile_size, z)
    maxX, maxY = pixels_to_meters((x + 1) * tile_size, y * tile_size, z)

    return minX, minY, maxX, maxY


# Function to download tiles for a specific zoom level
def download_tiles_for_zoom(base_url, output_dir, z):
    os.makedirs(output_dir, exist_ok=True)
    
    # Get the list of X tile directories
    x_dirs = get_directory_listing(f"{base_url}{z}/")
    x_dirs = [x for x in x_dirs if x.isdigit()]  # Ensure only numeric X directories

    for x in x_dirs:
        x_int = int(x)
        y_dir_url = f"{base_url}{z}/{x}/"
        y_files = get_directory_listing(y_dir_url)
        y_files = [y for y in y_files if y.endswith(".png")]  # Only valid tile images

        for y_file in y_files:
            y_int = int(y_file.replace(".png", ""))
            tile_path = os.path.join(output_dir, f"{z}_{x}_{y_file}")
            geotiff_path = tile_path.replace('.png', '.tif')

            # ✅ Skip if GeoTIFF already exists
            if os.path.exists(geotiff_path):
                print(f"⏩ Skipping {geotiff_path}, already georeferenced.")
                continue

            # Download tile if not already present
            if not os.path.exists(tile_path):
                tile_url = f"{y_dir_url}{y_file}"
                try:
                    response = requests.get(tile_url, stream=True)
                    if response.status_code == 200:
                        with open(tile_path, 'wb') as f:
                            f.write(response.content)
                        print(f"✅ Downloaded: {tile_url}")
                    else:
                        print(f"⚠️ Failed to download: {tile_url} (Status: {response.status_code})")
                        continue
                except Exception as e:
                    print(f"❌ Error downloading {tile_url}: {e}")
                    continue

            # ✅ Georeference the tile (convert to GeoTIFF)
            lon1, lat1, lon2, lat2 = tile_to_bbox(x_int, y_int, z)
            print(f"🗺 Georeferencing tile {z}/{x}/{y_file} with bbox: {lon1}, {lat1}, {lon2}, {lat2}")
            subprocess.run([
                "gdal_translate",
                "-a_ullr", str(lon1), str(lat2), str(lon2), str(lat1),  # Switch latitudes
                "-a_srs", "EPSG:3857",
                tile_path,
                geotiff_path
            ], check=True)



# Step 1: Download tiles only for the specified zoom level
print(f"🔎 Scraping directory and downloading tiles for zoom level {ZOOM_LEVEL}...")
download_tiles_for_zoom(ROOT_URL, OUTPUT_DIR, ZOOM_LEVEL)

# Step 2: Generate tiles.txt
print("📜 Generating tiles.txt...")
tiles_paths = []
for root, _, files in os.walk(OUTPUT_DIR):
    for file in files:
        if file.endswith(".tif"):  # Only use georeferenced tiles
            tiles_paths.append(os.path.abspath(os.path.join(root, file)))

if tiles_paths:
    with open(TILES_LIST_FILE, 'w') as f:
        for tile_path in tiles_paths:
            f.write(f"{tile_path}\n")

    # Step 3: Build VRT if tiles exist
    print("🛠 Creating VRT...")
    subprocess.run([
        "gdalbuildvrt",
        "-input_file_list", TILES_LIST_FILE,
        VRT_FILE
    ], check=True)

    # Step 4: Convert VRT to GeoTIFF
    print("🗺 Creating GeoTIFF...")
    subprocess.run([
        "gdal_translate",
        "-of", "GTiff",
        "-a_srs", "EPSG:3857",
        VRT_FILE,
        GEOTIFF_FILE
    ], check=True)

    print(f"🎉 GeoTIFF created: {GEOTIFF_FILE}")
else:
    print("⚠️ No tiles downloaded. Skipping VRT and GeoTIFF creation.")
