"""Areas router — thin: parse -> service -> schema.

All behavior lives in services/areas.py (the v1 port). Sync def per
standards (DB routes). Garden scoping via Depends(current_garden_id).

NOTE for main.py wiring: include this router AND routers/layout.py (which
serves GET /api/areas/{id}/layout and POST /api/plants/{id}/positions).
"""
from __future__ import annotations

from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session

from ..db import get_db
from ..deps import current_garden_id
from ..schemas.areas import (
    AreaCreate,
    AreaDeleteOut,
    AreaDetailOut,
    AreasIndexOut,
    AreaOut,
    AreaUpdate,
    OkOut,
    ParentPositionOut,
    ParentPositionRequest,
    ReorderRequest,
)
from ..services import areas as areas_svc

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


@router.get("", response_model=AreasIndexOut)
def areas_index(
    include_archived: bool = False,
    status: str = "planted",
    garden_id: int = Depends(current_garden_id),
    db: Session = Depends(get_db),
):
    """Area tree (with subtree plant counts + species summaries) + flat
    picker options + compact drill-down picker payload."""
    return areas_svc.get_areas_index(
        db, garden_id, include_archived=include_archived, status=status
    )


@router.post("", response_model=AreaOut, status_code=201)
def area_create(
    body: AreaCreate,
    garden_id: int = Depends(current_garden_id),
    db: Session = Depends(get_db),
):
    return areas_svc.create_area(db, garden_id, **body.model_dump())


# Declared before /{area_id} so the literal segment can never be shadowed.
@router.post("/reorder", response_model=OkOut)
def area_reorder(
    body: ReorderRequest,
    garden_id: int = Depends(current_garden_id),
    db: Session = Depends(get_db),
):
    """Re-parent + resequence siblings (v1 drag-arrange). Cycles rejected
    with error code ``area_cycle_rejected``."""
    return areas_svc.reorder_area(
        db, garden_id, body.area_id, body.parent_id, body.new_index
    )


@router.get("/{area_id}", response_model=AreaDetailOut)
def area_detail(
    area_id: int,
    status: str = "planted",
    include_archived: bool = False,
    garden_id: int = Depends(current_garden_id),
    db: Session = Depends(get_db),
):
    """Area + breadcrumbs + enriched child summaries + direct plants +
    sketch payload (geometry, resolved plant positions, child positions)."""
    return areas_svc.get_area_detail(
        db, garden_id, area_id, status=status, include_archived=include_archived
    )


@router.patch("/{area_id}", response_model=AreaOut)
def area_update(
    area_id: int,
    body: AreaUpdate,
    garden_id: int = Depends(current_garden_id),
    db: Session = Depends(get_db),
):
    """Partial update (name/notes/parent/dims/rotation/environment texts).
    Only fields present in the body are applied."""
    return areas_svc.update_area(
        db, garden_id, area_id, body.model_dump(exclude_unset=True)
    )


@router.delete("/{area_id}", response_model=AreaDeleteOut)
def area_delete(
    area_id: int,
    garden_id: int = Depends(current_garden_id),
    db: Session = Depends(get_db),
):
    """Recursive delete: descendants removed, plants unlinked (never deleted)."""
    return areas_svc.delete_area(db, garden_id, area_id)


@router.post("/{area_id}/parent-position", response_model=ParentPositionOut)
def area_parent_position(
    area_id: int,
    body: ParentPositionRequest,
    garden_id: int = Depends(current_garden_id),
    db: Session = Depends(get_db),
):
    """Save the child's center position within its parent (feet, clamped)."""
    return areas_svc.set_parent_position(db, garden_id, area_id, body.x, body.y)
