"""YakPanel - Docker API - list/start/stop containers via docker CLI"""
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel

from app.core.utils import exec_shell_sync
from app.api.auth import get_current_user
from app.models.user import User

router = APIRouter(prefix="/docker", tags=["docker"])


class RunContainerRequest(BaseModel):
    image: str
    name: str = ""
    ports: str = ""
    cmd: str = ""


@router.get("/containers")
async def docker_containers(current_user: User = Depends(get_current_user)):
    """List Docker containers (docker ps -a)"""
    out, err = exec_shell_sync(
        'docker ps -a --format "{{.ID}}\t{{.Image}}\t{{.Status}}\t{{.Names}}\t{{.Ports}}"',
        timeout=10,
    )
    if err and "Cannot connect" in err:
        return {"containers": [], "error": "Docker not available"}
    containers = []
    for line in out.strip().split("\n"):
        line = line.strip()
        if not line:
            continue
        parts = line.split("\t", 4)
        if len(parts) >= 5:
            containers.append({
                "id": parts[0][:12],
                "id_full": parts[0],
                "image": parts[1],
                "status": parts[2],
                "names": parts[3],
                "ports": parts[4],
            })
        elif len(parts) >= 4:
            containers.append({
                "id": parts[0][:12],
                "id_full": parts[0],
                "image": parts[1],
                "status": parts[2],
                "names": parts[3],
                "ports": "",
            })
    return {"containers": containers}


@router.get("/images")
async def docker_images(current_user: User = Depends(get_current_user)):
    """List Docker images (docker images)"""
    out, err = exec_shell_sync(
        'docker images --format "{{.Repository}}\t{{.Tag}}\t{{.ID}}\t{{.Size}}"',
        timeout=10,
    )
    if err and "Cannot connect" in err:
        return {"images": [], "error": "Docker not available"}
    images = []
    for line in out.strip().split("\n"):
        line = line.strip()
        if not line:
            continue
        parts = line.split("\t", 3)
        if len(parts) >= 4:
            images.append({
                "repository": parts[0],
                "tag": parts[1],
                "id": parts[2],
                "size": parts[3],
            })
    return {"images": images}


@router.post("/pull")
async def docker_pull(
    image: str,
    current_user: User = Depends(get_current_user),
):
    """Pull Docker image (docker pull)"""
    if not image or " " in image or "'" in image or '"' in image:
        raise HTTPException(status_code=400, detail="Invalid image name")
    out, err = exec_shell_sync(f"docker pull {image}", timeout=600)
    if err and "error" in err.lower():
        raise HTTPException(status_code=500, detail=err.strip() or out.strip())
    return {"status": True, "msg": "Pulled"}


@router.post("/run")
async def docker_run(
    body: RunContainerRequest,
    current_user: User = Depends(get_current_user),
):
    """Run a new container (docker run -d)"""
    image = (body.image or "").strip()
    if not image:
        raise HTTPException(status_code=400, detail="Image required")
    if " " in image or "'" in image or '"' in image:
        raise HTTPException(status_code=400, detail="Invalid image name")
    cmd = f"docker run -d {image}"
    if body.name:
        name = body.name.strip().replace(" ", "-")
        if name and all(c.isalnum() or c in "-_" for c in name):
            cmd += f" --name {name}"
    if body.ports:
        for p in body.ports.replace(",", " ").split():
            p = p.strip()
            if p:
                cmd += f" -p {p}" if ":" in p else f" -p {p}:{p}"
    if body.cmd:
        cmd += f" {body.cmd}"
    out, err = exec_shell_sync(cmd, timeout=60)
    if err and "error" in err.lower():
        raise HTTPException(status_code=500, detail=err.strip() or out.strip())
    return {"status": True, "msg": "Container started", "id": out.strip()[:12]}


@router.post("/{container_id}/start")
async def docker_start(
    container_id: str,
    current_user: User = Depends(get_current_user),
):
    """Start container"""
    if " " in container_id or "'" in container_id or '"' in container_id:
        raise HTTPException(status_code=400, detail="Invalid container ID")
    out, err = exec_shell_sync(f"docker start {container_id}", timeout=30)
    if err and "error" in err.lower():
        raise HTTPException(status_code=500, detail=err.strip() or out.strip())
    return {"status": True, "msg": "Started"}


@router.post("/{container_id}/stop")
async def docker_stop(
    container_id: str,
    current_user: User = Depends(get_current_user),
):
    """Stop container"""
    if " " in container_id or "'" in container_id or '"' in container_id:
        raise HTTPException(status_code=400, detail="Invalid container ID")
    out, err = exec_shell_sync(f"docker stop {container_id}", timeout=30)
    if err and "error" in err.lower():
        raise HTTPException(status_code=500, detail=err.strip() or out.strip())
    return {"status": True, "msg": "Stopped"}


@router.post("/{container_id}/restart")
async def docker_restart(
    container_id: str,
    current_user: User = Depends(get_current_user),
):
    """Restart container"""
    if " " in container_id or "'" in container_id or '"' in container_id:
        raise HTTPException(status_code=400, detail="Invalid container ID")
    out, err = exec_shell_sync(f"docker restart {container_id}", timeout=30)
    if err and "error" in err.lower():
        raise HTTPException(status_code=500, detail=err.strip() or out.strip())
    return {"status": True, "msg": "Restarted"}
