"""YakPanel - SSL/Domains API - Let's Encrypt via certbot"""
import os
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from pydantic import BaseModel

from app.core.database import get_db
from app.core.config import get_runtime_config
from app.core.utils import exec_shell_sync
from app.api.auth import get_current_user
from app.models.user import User
from app.models.site import Site, Domain

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


@router.get("/domains")
async def ssl_domains(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """List all domains from sites with site path for certbot webroot"""
    result = await db.execute(
        select(Domain, Site).join(Site, Domain.pid == Site.id).order_by(Domain.name)
    )
    rows = result.all()
    return [
        {
            "id": d.id,
            "name": d.name,
            "port": d.port,
            "site_id": s.id,
            "site_name": s.name,
            "site_path": s.path,
        }
        for d, s in rows
    ]


class RequestCertRequest(BaseModel):
    domain: str
    webroot: str
    email: str


@router.post("/request")
async def ssl_request_cert(
    body: RequestCertRequest,
    current_user: User = Depends(get_current_user),
):
    """Request Let's Encrypt certificate via certbot (webroot challenge)"""
    if not body.domain or not body.webroot or not body.email:
        raise HTTPException(status_code=400, detail="domain, webroot and email required")
    if ".." in body.domain or ".." in body.webroot:
        raise HTTPException(status_code=400, detail="Invalid path")
    cfg = get_runtime_config()
    allowed = [os.path.abspath(cfg["www_root"]), os.path.abspath(cfg["setup_path"])]
    webroot_abs = os.path.abspath(body.webroot)
    if not any(webroot_abs.startswith(a + os.sep) or webroot_abs == a for a in allowed):
        raise HTTPException(status_code=400, detail="Webroot must be under www_root or setup_path")
    cmd = (
        f'certbot certonly --webroot -w "{body.webroot}" -d "{body.domain}" '
        f'--non-interactive --agree-tos --email "{body.email}"'
    )
    out, err = exec_shell_sync(cmd, timeout=120)
    if err and "error" in err.lower() and "successfully" not in err.lower():
        raise HTTPException(status_code=500, detail=err.strip() or out.strip())
    return {"status": True, "msg": "Certificate requested", "output": out}


@router.get("/certificates")
async def ssl_list_certificates(current_user: User = Depends(get_current_user)):
    """List existing Let's Encrypt certificates"""
    live_dir = "/etc/letsencrypt/live"
    if not os.path.isdir(live_dir):
        return {"certificates": []}
    certs = []
    for name in os.listdir(live_dir):
        if name.startswith("."):
            continue
        path = os.path.join(live_dir, name)
        if os.path.isdir(path) and os.path.isfile(os.path.join(path, "fullchain.pem")):
            certs.append({"name": name, "path": path})
    return {"certificates": sorted(certs, key=lambda x: x["name"])}
