"""REST endpoints for project management."""
from __future__ import annotations

from pathlib import Path
from typing import Any

from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field, ValidationError

from proxym.config import get_settings
from proxym.observability import log_call

router = APIRouter(tags=["projects"])


# --- Lazy singleton ---

_registry = None


def _get_registry():
    global _registry
    if _registry is None:
        from proxym.projects import ProjectRegistry
        persist = Path.home() / ".config" / "proxym" / "projects.json"
        _registry = ProjectRegistry(persist_path=persist)
        # Auto-scan default directory
        settings = get_settings()
        root = settings.projects_root
        if root:
            _registry.scan_directory(root)
    return _registry


# --- Request models ---

class AddProjectReq(BaseModel):
    """Dodaj projekt — jedno z: path, git_url, ssh."""
    name: str | None = None
    path: str | None = None          # local: ~/github/my-app
    git_url: str | None = None       # git: https://github.com/user/repo.git
    clone_to: str | None = None      # gdzie klonować (domyślnie projects_root)
    ssh_host: str | None = None      # SSH host
    ssh_path: str | None = None      # SSH remote path
    ssh_user: str = "root"
    ssh_key: str | None = None
    ftp_url: str | None = None       # ftp://host/path
    default_tool: str | None = None
    description: str = ""


class UpdateProjectReq(BaseModel):
    name: str | None = None
    default_tool: str | None = None
    description: str | None = None
    status: str | None = None


class ScanReq(BaseModel):
    directory: str                    # folder do skanowania


# --- Endpoints ---

@router.get("/projects")
async def list_projects(
    status: str | None = None,
    source_type: str | None = None,
) -> list[dict[str, Any]]:
    """Lista wszystkich projektów."""
    reg = _get_registry()
    from proxym.projects import ProjectStatus, SourceType
    s = ProjectStatus(status) if status else None
    st = SourceType(source_type) if source_type else None
    return [p.model_dump() for p in reg.list_projects(status=s, source_type=st)]


@router.get("/projects/{project_id}")
async def get_project(project_id: str) -> dict[str, Any]:
    project = _get_registry().get(project_id)
    if not project:
        raise HTTPException(404, f"Project {project_id} not found")
    return project.model_dump()


@router.post("/projects")
@log_call(level="info")
async def add_project(req: AddProjectReq) -> dict[str, Any]:
    """Dodaj projekt — auto-detect typu z podanych parametrów."""
    reg = _get_registry()

    if req.path:
        # Lokalny folder
        from proxym.projects import Project, SourceType
        path = str(Path(req.path).expanduser().resolve())
        project = Project(
            name=req.name or Path(path).name,
            source_type=SourceType.local,
            source_path=path,
            local_path=path,
            default_tool=req.default_tool,
            description=req.description,
        )
        return reg.add(project).model_dump()

    elif req.git_url:
        # Git repo
        settings = get_settings()
        clone_to = req.clone_to or settings.projects_root or "~/github"
        return reg.add_git_repo(req.git_url, clone_to=clone_to).model_dump()

    elif req.ssh_host and req.ssh_path:
        # SSH remote
        return reg.add_ssh_project(
            host=req.ssh_host,
            path=req.ssh_path,
            user=req.ssh_user,
            ssh_key=req.ssh_key,
            name=req.name,
        ).model_dump()

    elif req.ftp_url:
        from proxym.projects import Project, SourceType
        name = req.name or req.ftp_url.rsplit("/", 1)[-1]
        project = Project(
            name=name,
            source_type=SourceType.ftp,
            source_path=req.ftp_url,
            description=req.description,
        )
        return reg.add(project).model_dump()

    else:
        raise HTTPException(400, "Provide at least one: path, git_url, ssh_host+ssh_path, or ftp_url")


@router.put("/projects/{project_id}")
async def update_project(project_id: str, req: UpdateProjectReq) -> dict[str, Any]:
    updates = {k: v for k, v in req.model_dump().items() if v is not None}
    result = _get_registry().update(project_id, updates)
    if not result:
        raise HTTPException(404)
    return result.model_dump()


@router.delete("/projects/{project_id}")
async def remove_project(project_id: str) -> dict[str, str]:
    if _get_registry().remove(project_id):
        return {"status": "deleted"}
    raise HTTPException(404)


@router.post("/projects/scan")
@log_call(level="info")
async def scan_directory(req: ScanReq) -> dict[str, Any]:
    """Skanuj folder i dodaj znalezione projekty."""
    added = _get_registry().scan_directory(req.directory)
    return {
        "scanned": req.directory,
        "added": len(added),
        "projects": [p.model_dump() for p in added],
    }


@router.get("/projects/{project_id}/tickets")
async def project_tickets(project_id: str) -> list[dict[str, Any]]:
    """Tickety powiązane z projektem."""
    from proxym.dashboard._tickets_api import _tickets
    mgr = _tickets()
    all_tickets = mgr.list_tickets()
    return [
        t.summary() for t in all_tickets
        if getattr(t, "project_id", None) == project_id
    ]


@router.post("/projects/{project_id}/tickets")
async def create_project_ticket(project_id: str, req: dict[str, Any]) -> dict[str, Any]:
    """Stwórz ticket od razu powiązany z projektem."""
    # Ensure project exists
    project = _get_registry().get(project_id)
    if not project:
        raise HTTPException(404, f"Project {project_id} not found")

    from proxym.dashboard._tickets_api import CreateTicketReq, create_ticket

    payload = dict(req or {})
    payload["project_id"] = project_id
    try:
        ticket_req = CreateTicketReq(**payload)
    except ValidationError as e:
        # Request body validation errors should not surface as 500.
        raise HTTPException(422, {"detail": e.errors()})

    # Call create_ticket with validated/normalized types.
    return await create_ticket(**ticket_req.model_dump())
