"""YakPanel - Plugin / Extensions API"""
import json
import re
from urllib.parse import urlparse
from urllib.request import urlopen, Request

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.api.auth import get_current_user
from app.models.user import User
from app.models.plugin import CustomPlugin

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

# Built-in extensions (features) - always enabled
BUILTIN_PLUGINS = [
    {"id": "backup", "name": "Backup", "version": "1.0", "desc": "Site and database backup/restore", "enabled": True, "builtin": True},
    {"id": "ssl", "name": "SSL/ACME", "version": "1.0", "desc": "Let's Encrypt certificates", "enabled": True, "builtin": True},
    {"id": "docker", "name": "Docker", "version": "1.0", "desc": "Container management", "enabled": True, "builtin": True},
    {"id": "node", "name": "Node.js", "version": "1.0", "desc": "PM2 process manager", "enabled": True, "builtin": True},
    {"id": "services", "name": "Services", "version": "1.0", "desc": "System service control", "enabled": True, "builtin": True},
    {"id": "logs", "name": "Logs", "version": "1.0", "desc": "Log file viewer", "enabled": True, "builtin": True},
    {"id": "terminal", "name": "Terminal", "version": "1.0", "desc": "Web terminal", "enabled": True, "builtin": True},
    {"id": "monitor", "name": "Monitor", "version": "1.0", "desc": "System monitoring", "enabled": True, "builtin": True},
]


@router.get("/list")
async def plugin_list(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """List built-in + custom plugins"""
    result = await db.execute(select(CustomPlugin).order_by(CustomPlugin.id))
    custom = result.scalars().all()
    builtin_ids = {p["id"] for p in BUILTIN_PLUGINS}
    plugins = list(BUILTIN_PLUGINS)
    for c in custom:
        plugins.append({
            "id": c.plugin_id,
            "name": c.name,
            "version": c.version,
            "desc": c.desc,
            "enabled": c.enabled,
            "builtin": False,
            "db_id": c.id,
        })
    return {"plugins": plugins}


class AddPluginRequest(BaseModel):
    url: str


@router.post("/add-from-url")
async def plugin_add_from_url(
    body: AddPluginRequest,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Add a third-party plugin from a JSON manifest URL"""
    url = (body.url or "").strip()
    if not url:
        raise HTTPException(status_code=400, detail="URL required")
    parsed = urlparse(url)
    if parsed.scheme not in ("http", "https"):
        raise HTTPException(status_code=400, detail="Only http/https URLs allowed")
    if not parsed.netloc or parsed.netloc.startswith("127.") or parsed.netloc == "localhost":
        raise HTTPException(status_code=400, detail="Invalid URL")
    try:
        req = Request(url, headers={"User-Agent": "YakPanel/1.0"})
        with urlopen(req, timeout=10) as r:
            data = r.read(64 * 1024).decode("utf-8", errors="replace")
    except Exception as e:
        raise HTTPException(status_code=400, detail=f"Failed to fetch: {str(e)[:100]}")
    try:
        manifest = json.loads(data)
    except json.JSONDecodeError as e:
        raise HTTPException(status_code=400, detail=f"Invalid JSON: {e}")
    pid = (manifest.get("id") or "").strip()
    name = (manifest.get("name") or "").strip()
    if not pid or not name:
        raise HTTPException(status_code=400, detail="Manifest must have 'id' and 'name'")
    if not re.match(r"^[a-z0-9_-]+$", pid):
        raise HTTPException(status_code=400, detail="Plugin id must be alphanumeric, underscore, hyphen only")
    version = (manifest.get("version") or "1.0").strip()[:32]
    desc = (manifest.get("desc") or "").strip()[:512]
    # Check builtin conflict
    if any(p["id"] == pid for p in BUILTIN_PLUGINS):
        raise HTTPException(status_code=400, detail="Plugin id conflicts with built-in")
    # Check existing custom
    r = await db.execute(select(CustomPlugin).where(CustomPlugin.plugin_id == pid))
    if r.scalar_one_or_none():
        raise HTTPException(status_code=400, detail="Plugin already installed")
    cp = CustomPlugin(
        plugin_id=pid,
        name=name,
        version=version,
        desc=desc,
        source_url=url[:512],
        enabled=True,
    )
    db.add(cp)
    await db.commit()
    return {"status": True, "msg": "Plugin added", "id": cp.plugin_id}


@router.delete("/{plugin_id}")
async def plugin_delete(
    plugin_id: str,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """Remove a custom plugin (built-in plugins cannot be removed)"""
    if any(p["id"] == plugin_id for p in BUILTIN_PLUGINS):
        raise HTTPException(status_code=400, detail="Cannot remove built-in plugin")
    result = await db.execute(select(CustomPlugin).where(CustomPlugin.plugin_id == plugin_id))
    cp = result.scalar_one_or_none()
    if not cp:
        raise HTTPException(status_code=404, detail="Plugin not found")
    await db.delete(cp)
    await db.commit()
    return {"status": True, "msg": "Plugin removed"}
