"""CRUD API для own_planned_project (#1169 PR1, ТЗ §25.3).

POST   /api/v1/own-projects        → 201 OwnPlannedProjectOut   (create)
GET    /api/v1/own-projects        → OwnPlannedProjectList       (list + filters + pagination)
GET    /api/v1/own-projects/{id}   → OwnPlannedProjectOut        (one; 404 если нет)
PUT    /api/v1/own-projects/{id}   → OwnPlannedProjectOut        (partial update; 404 если нет)
DELETE /api/v1/own-projects/{id}   → 204                         (hard delete; 404 если нет)

«Наши будущие/планируемые проекты» приватного пайплайна — второй источник §25.3-движка
каннибализации (парный к «текущим» из domrf, см. site_finder/own_portfolio.py).

Access control: backend rbac_guard (app/main.py) хард-блокирует ТОЛЬКО /api/v1/admin/*.
На /api/v1/own-projects pilot отсекается FRONTEND-овым RouteGuard + Caddy, НЕ бэкендом;
до эндпоинта доходят analyst+admin. created_by автора берём из X-Authenticated-User (тот
же заголовок, что Caddy basic_auth пробрасывает в backend) — НЕ из тела (зеркало insight).

Хэндлеры sync `def` (зеркало insights.py): сервис ходит в БД через sync SQLAlchemy
Session, поэтому FastAPI исполняет их в threadpool — event loop не блокируется.
"""

from __future__ import annotations

import logging
from typing import Annotated, Any

from fastapi import APIRouter, Depends, Header, HTTPException, Query, status
from sqlalchemy.orm import Session

from app.core.db import get_db
from app.schemas.own_project import (
    OwnPlannedProjectCreate,
    OwnPlannedProjectList,
    OwnPlannedProjectOut,
    OwnPlannedProjectUpdate,
    OwnProjectClass,
)
from app.services.own_projects import (
    create_own_project,
    delete_own_project,
    get_own_project,
    list_own_projects,
    update_own_project,
)

logger = logging.getLogger(__name__)

router = APIRouter()


def _require_user(x_authenticated_user: str | None) -> str:
    """Вернуть автора из X-Authenticated-User или 401 (зеркало insights._require_user).

    В проде Caddy basic_auth всегда пробрасывает заголовок для авторизованных, а
    rbac_guard рубит запросы без него ещё до роутера. Эта проверка — defence in depth
    (+ корректный ответ в test-mode, где rbac_guard выключен).
    """
    if x_authenticated_user and x_authenticated_user.strip():
        return x_authenticated_user.strip()
    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="no authenticated user (X-Authenticated-User required)",
    )


@router.post("", response_model=OwnPlannedProjectOut, status_code=status.HTTP_201_CREATED)
def create_own_project_endpoint(
    payload: OwnPlannedProjectCreate,
    db: Annotated[Session, Depends(get_db)],
    x_authenticated_user: Annotated[str | None, Header()] = None,
) -> Any:
    """Создать планируемый проект. created_by = X-Authenticated-User."""
    created_by = _require_user(x_authenticated_user)
    return create_own_project(db, created_by, payload)


@router.get("", response_model=OwnPlannedProjectList)
def list_own_projects_endpoint(
    db: Annotated[Session, Depends(get_db)],
    district: Annotated[str | None, Query(description="Фильтр по району")] = None,
    obj_class: Annotated[OwnProjectClass | None, Query(description="Фильтр по классу")] = None,
    created_by: Annotated[str | None, Query(description="Фильтр по автору")] = None,
    limit: Annotated[int, Query(ge=1, le=200)] = 50,
    offset: Annotated[int, Query(ge=0)] = 0,
) -> Any:
    """Список планируемых проектов с фильтрами + пагинацией."""
    return list_own_projects(
        db,
        district=district,
        obj_class=obj_class,
        created_by=created_by,
        limit=limit,
        offset=offset,
    )


@router.get("/{project_id}", response_model=OwnPlannedProjectOut)
def get_own_project_endpoint(
    project_id: int,
    db: Annotated[Session, Depends(get_db)],
) -> Any:
    """Вернуть один планируемый проект. 404 если не найден."""
    project = get_own_project(db, project_id)
    if project is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Own planned project not found"
        )
    return project


@router.put("/{project_id}", response_model=OwnPlannedProjectOut)
def update_own_project_endpoint(
    project_id: int,
    payload: OwnPlannedProjectUpdate,
    db: Annotated[Session, Depends(get_db)],
    x_authenticated_user: Annotated[str | None, Header()] = None,
) -> Any:
    """Partial update планируемого проекта. 404 если не найден."""
    _require_user(x_authenticated_user)
    project = update_own_project(db, project_id, payload)
    if project is None:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Own planned project not found"
        )
    return project


@router.delete("/{project_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_own_project_endpoint(
    project_id: int,
    db: Annotated[Session, Depends(get_db)],
    x_authenticated_user: Annotated[str | None, Header()] = None,
) -> None:
    """Удалить планируемый проект. 404 если не найден."""
    _require_user(x_authenticated_user)
    deleted = delete_own_project(db, project_id)
    if not deleted:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND, detail="Own planned project not found"
        )
