from __future__ import annotations

import uuid

from fastapi import APIRouter, BackgroundTasks, HTTPException

from app.core.command_runner import CommandRunner
from app.core.installer import AptInstaller
from app.core.service_manager import ServiceManager
from app.core.task_runner import TaskRunner
from app.models.schemas import InstallRequest, RemoveRequest, UpdateRequest
from app.storage.repository import Repository


router = APIRouter(prefix="/apps", tags=["apps"])
repository = Repository()
task_runner = TaskRunner(repository)


def _task_id(prefix: str) -> str:
    return f"task_{prefix}_{uuid.uuid4().hex[:12]}"


@router.get("/installed")
def installed_apps() -> list[dict]:
    apps = repository.list_installed_apps()
    command_runner = CommandRunner(repository)
    service_manager = ServiceManager(command_runner)
    apt_installer = AptInstaller(command_runner)
    for app in apps:
        service_checks: list[dict] = []
        component_statuses: list[str] = []
        for component in repository.list_installed_components(app["app_id"]):
            check_status = component.get("service_check_status", "not-checked")
            if check_status != "not-checked":
                component_statuses.append(check_status)
            for check in component.get("service_checks", []):
                service_name = str(check.get("serviceName") or "").strip()
                if not service_name:
                    continue
                current_check = service_manager.get_service_status(service_name)
                if current_check.get("status") == "unknown" and current_check.get("errorMessage"):
                    current_check = dict(check)
                    current_check["stale"] = True
                elif check.get("readinessType") == "postgresql":
                    readiness_status = "ready" if apt_installer.is_postgresql_ready() else "failed"
                    current_check["readinessType"] = "postgresql"
                    current_check["readinessStatus"] = readiness_status
                    current_check["healthy"] = bool(current_check.get("healthy")) and readiness_status == "ready"
                service_checks.append(
                    {
                        **current_check,
                        "componentId": component["component_id"],
                        "packageName": component.get("package_name"),
                    }
                )

        if service_checks and any(not check.get("healthy") for check in service_checks):
            overall_status = "unhealthy"
        elif service_checks:
            overall_status = "healthy"
        elif "unhealthy" in component_statuses:
            overall_status = "unhealthy"
        elif "checking" in component_statuses:
            overall_status = "checking"
        elif "healthy" in component_statuses:
            overall_status = "healthy"
        elif "not-applicable" in component_statuses:
            overall_status = "not-applicable"
        else:
            overall_status = "not-checked"

        app["serviceCheckStatus"] = overall_status
        app["serviceChecks"] = service_checks
    return apps


@router.post("/install")
def install_app(request: InstallRequest, background_tasks: BackgroundTasks) -> dict[str, str]:
    if not request.version:
        raise HTTPException(status_code=400, detail="version is required")
    task_id = _task_id("install")
    repository.create_task(task_id, "install", request.app_id, request.app_name)
    background_tasks.add_task(task_runner.run_install, task_id, request, "install")
    return {"taskId": task_id, "status": "queued"}


@router.post("/update")
def update_app(request: UpdateRequest, background_tasks: BackgroundTasks) -> dict[str, str]:
    if not request.version:
        raise HTTPException(status_code=400, detail="version or targetVersion is required")
    task_id = _task_id("update")
    repository.create_task(task_id, "update", request.app_id, request.app_name)
    background_tasks.add_task(task_runner.run_install, task_id, request, "update")
    return {"taskId": task_id, "status": "queued"}


@router.post("/remove")
def remove_app(request: RemoveRequest, background_tasks: BackgroundTasks) -> dict[str, str]:
    if not request.package_name and not repository.list_installed_components(request.app_id):
        raise HTTPException(status_code=400, detail="packageName is required when app is not tracked locally")
    task_id = _task_id("remove")
    repository.create_task(task_id, "remove", request.app_id, request.app_id)
    background_tasks.add_task(task_runner.run_remove, task_id, request)
    return {"taskId": task_id, "status": "queued"}
