from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
import os
import shutil
import subprocess
import uuid
import zipfile

app = FastAPI()
app.mount("/static", StaticFiles(directory="/var/www/html/qgis-automation/static"), name="static")


# --- Step 1: Save uploaded image ---
def save_uploaded_image(image: UploadFile) -> str:
    os.makedirs("uploads", exist_ok=True)
    image_path = f"uploads/{image.filename}"
    with open(image_path, "wb") as f:
        shutil.copyfileobj(image.file, f)
    return image_path

# --- Step 2: Generate dummy control points ---
def generate_points_file(image_path: str) -> str:
    points_path = image_path.rsplit(".", 1)[0] + "_points.txt"
    with open(points_path, "w") as f:
        f.write("0,0,88.0,22.0\n3487,4620,88.1,22.1\n")  # Example control points
    return points_path

# --- Step 3: Georeference image directly (JPEG input) ---
def georeference_image(image_path: str, points_path: str) -> str:
    if not os.path.exists(image_path):
        raise FileNotFoundError(f"Image not found: {image_path}")

    try:
        subprocess.run(["gdalinfo", image_path], check=True)
    except subprocess.CalledProcessError:
        raise RuntimeError(f"GDAL cannot read image: {image_path}")

    geotiff_path = image_path.rsplit(".", 1)[0] + "_georef.tif"
    command = [
        "gdal_translate",
        "-of", "GTiff",
        "-a_ullr", "88.0", "22.1", "88.1", "22.0",
        "-a_srs", "EPSG:4326",
        image_path,
        geotiff_path
    ]
    subprocess.run(command, check=True)
    return geotiff_path

# --- Step 4: Generate tiles ---
def generate_tiles(geotiff_path: str) -> str:
    if not os.path.exists(geotiff_path):
        raise FileNotFoundError(f"GeoTIFF not found: {geotiff_path}")

    tile_id = uuid.uuid4().hex[:8]
    output_dir = os.path.join("tiles_output", tile_id)
    os.makedirs(output_dir, exist_ok=True)

    command = [
        "gdal2tiles.py",
        "-z", "0-5",
        "-w", "none",
        geotiff_path,
        output_dir
    ]
    try:
        subprocess.run(command, check=True)
    except subprocess.CalledProcessError as e:
        raise RuntimeError(f"Tile generation failed: {e}")

    if not os.listdir(output_dir):
        raise RuntimeError(f"No tiles generated in: {output_dir}")

    return output_dir

# --- Step 5: Zip tiles ---
def zip_tiles(tile_dir: str) -> str:
    zip_path = f"{tile_dir}.zip"
    with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
        for root, _, files in os.walk(tile_dir):
            for file in files:
                full_path = os.path.join(root, file)
                arcname = os.path.relpath(full_path, tile_dir)
                zipf.write(full_path, arcname)
    return zip_path

# --- Route: Upload and process Mouza map ---
@app.post("/georef/")
async def georef_mouza_map(image: UploadFile = File(...)):
    try:
        image_path = save_uploaded_image(image)
        points_path = generate_points_file(image_path)
        geotiff = georeference_image(image_path, points_path)
        tiles_dir = generate_tiles(geotiff)
        zip_path = zip_tiles(tiles_dir)
        tile_id = os.path.basename(tiles_dir)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

    return {
        "message": "Georeferencing complete",
        "tiles_zip": f"/tiles/download/{tile_id}",
        "tile_id": tile_id  # ← Add this line

    }

# --- Route: Download zipped tiles ---
@app.get("/tiles/download/{tile_id}")
def download_tiles(tile_id: str):
    zip_path = f"tiles_output/{tile_id}.zip"
    if not os.path.exists(zip_path):
        raise HTTPException(status_code=404, detail="Zip not found")
    return FileResponse(zip_path, media_type="application/zip", filename=f"{tile_id}.zip")

@app.get("/tiles/{tile_id}/{z}/{x}/{y}.png")
def serve_tile(tile_id: str, z: int, x: int, y: int):
    tile_path = f"/var/www/html/qgis-automation/tiles_output/{tile_id}/{z}/{x}/{y}.png"
    if not os.path.exists(tile_path):
        print(f"Missing tile: {tile_path}")
        raise HTTPException(status_code=404, detail="Tile not found")
    return FileResponse(tile_path, media_type="image/png")
