# app.py
from fastapi import FastAPI, HTTPException, Query
from pydantic import BaseModel
import docker
from docker.errors import APIError, NotFound
import uvicorn
import requests
from uuid import uuid4
import json
from pprint import pprint

app = FastAPI(title="Launch Server")

client = docker.from_env()
HOST = '12.1.52.180'

class PullReq(BaseModel):
    name: str
    tag: str = "latest"

class RunReq(BaseModel):
    image: str
    name: str | None = None
    command: str | None = None
    ports: dict[str, int] | None = None
    env: dict[str, str] | None = None
    library_url: str | None = None

@app.get("/")
def home():
    return {'is_launch_server': True}

@app.get("/containers/debug")
def debug_containers():
    """Debug endpoint to see raw container data"""
    cs = client.containers.list(all=True)
    result = []
    for c in cs:
        result.append({
            "short_id": c.short_id,
            "name": c.name,
            "status_attr": getattr(c, 'status', None),
            "has_attrs": hasattr(c, 'attrs'),
            "attrs_state": c.attrs.get('State') if hasattr(c, 'attrs') else None
        })
    return result
 
@app.get("/images")
def list_images():
    imgs = client.images.list()
    return [{"id": i.short_id, "tags": i.tags} for i in imgs]

@app.post("/images/pull")
def pull_image(req: PullReq):
    try:
        img = client.images.pull(req.name, tag=req.tag)
        return {"id": img.short_id, "tags": img.tags}
    except APIError as e:
        raise HTTPException(400, detail=str(getattr(e, "explanation", e)))

@app.delete("/images/remove")
def remove_image(name: str = Query(..., description="image name or id")):
    try:
        client.images.remove(name, force=True)
        return {"removed": name}
    except NotFound:
        raise HTTPException(404, "Image not found")
    except APIError as e:
        raise HTTPException(400, detail=str(getattr(e, "explanation", e)))

@app.get("/containers")
def list_all_containers():
    cs = client.containers.list(all=True)
    result = []
    for c in cs:
        try:
            # Try different ways to get status
            status = None

            # Method 1: Direct attribute
            if hasattr(c, 'status'):
                status = c.status

            # Method 2: From attrs
            if not status and hasattr(c, 'attrs'):
                status = c.attrs.get('State', {}).get('Status')

            # Fallback
            if not status:
                status = 'unknown'

            result.append({
                "id": c.short_id,
                "name": c.name,
                "image": c.image.tags if hasattr(c.image, 'tags') else [],
                "status": str(status)
            })
        except Exception as e:
            print(f"Error processing container: {e}")
            result.append({
                "id": getattr(c, 'short_id', 'unknown'),
                "name": getattr(c, 'name', 'unknown'),
                "image": [],
                "status": 'error'
            })
    return result

@app.post("/containers/start")
def start_container(req: RunReq):
    pulled = False
    pulled_name = ''
    
    from pprint import pprint
    pprint(req)
    try:
        client.images.get(req.image)
    except:
        pulled = True
        name, _, tag = req.image.partition(":")
        print(req.library_url)
        client.images.pull(f'{req.library_url}/{name}', tag or "latest")
        req.image = f'{req.library_url}/{name}'

    c = client.containers.run(
        req.image,
        name=req.name,
        command=req.command,
        detach=True,
        ports=req.ports,
        environment=req.env,
        restart_policy={"Name": "unless-stopped"},
    )
    return {"id": c.short_id, "name": c.name}

@app.post("/containers/stop")
def stop_container(id_or_name: str = Query(..., description="container id or name"), timeout: int = 10):
    try:
        c = client.containers.get(id_or_name)
        c.stop(timeout=timeout)
        return {"stopped": c.name}
    except NotFound:
        raise HTTPException(404, "Container not found")
    except APIError as e:
        raise HTTPException(400, detail=str(getattr(e, "explanation", e)))

@app.post("/containers/restart")
def restart_container(id_or_name: str = Query(..., description="container id or name"), timeout: int = 10):
    try:
        c = client.containers.get(id_or_name)
        c.restart(timeout=timeout)
        return {"restarted": c.name}
    except NotFound:
        raise HTTPException(404, "Container not found")
    except APIError as e:
        raise HTTPException(400, detail=str(getattr(e, "explanation", e)))

if __name__ == '__main__':
    uvicorn.run(app, host="0.0.0.0", port=9696)
