"""CMS: services, testimonials, portfolio, site copy.
Public GETs / admin-only mutations."""
from datetime import datetime, timezone
from bson import ObjectId
from bson.errors import InvalidId
from fastapi import APIRouter, Depends, HTTPException

from deps import get_db, require_roles
from models import ServiceItem, TestimonialItem, PortfolioItem, SiteCopyIn

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

DEFAULT_COPY = {
    "hero_eyebrow": "Agencia de desarrollo digital",
    "hero_title": "Construimos el quinto sueño de tu marca.",
    "hero_subtitle": "Desarrollo web, apps móviles y experiencias digitales que combinan diseño impecable con tecnología de alto impacto.",
    "hero_cta_label": "Iniciar proyecto",
    "about_title": "Una agencia, infinitas posibilidades.",
    "about_body": "Somos 5to sueño, un equipo multidisciplinario obsesionado con transformar ideas ambiciosas en productos digitales que generan resultados reales. Metodología ágil, código limpio y diseño centrado en personas.",
    "values": [
        {"title": "Velocidad", "body": "Iteramos rápido sin sacrificar calidad."},
        {"title": "Transparencia", "body": "Visibilidad total del progreso, siempre."},
        {"title": "Innovación", "body": "Stack moderno, prácticas de vanguardia."},
        {"title": "Compromiso", "body": "Tu producto es nuestro producto."},
    ],
}


def _oid(s: str):
    try:
        return ObjectId(s)
    except InvalidId:
        raise HTTPException(status_code=400, detail="ID inválido")


# -------- site copy ----------
@router.get("/site")
async def get_site_copy():
    db = get_db()
    doc = await db.site_copy.find_one({"_id": "main"})
    if not doc:
        return DEFAULT_COPY
    doc.pop("_id", None)
    return {**DEFAULT_COPY, **doc}


@router.put("/site")
async def update_site_copy(payload: SiteCopyIn, _: dict = Depends(require_roles("admin"))):
    db = get_db()
    update = {k: v for k, v in payload.model_dump(exclude_unset=True).items()}
    update["updated_at"] = datetime.now(timezone.utc).isoformat()
    await db.site_copy.update_one({"_id": "main"}, {"$set": update}, upsert=True)
    doc = await db.site_copy.find_one({"_id": "main"})
    doc.pop("_id", None)
    return {**DEFAULT_COPY, **doc}


# -------- generic collection helpers ----------
def _ser(d: dict) -> dict:
    d["id"] = str(d["_id"])
    d.pop("_id", None)
    return d


async def _list(col: str):
    db = get_db()
    cur = db[col].find({}).sort("order", 1)
    return [_ser(x) async for x in cur]


async def _create(col: str, data: dict):
    db = get_db()
    data["created_at"] = datetime.now(timezone.utc).isoformat()
    res = await db[col].insert_one(data)
    data["_id"] = res.inserted_id
    return _ser(data)


async def _update(col: str, item_id: str, data: dict):
    db = get_db()
    oid = _oid(item_id)
    res = await db[col].find_one_and_update({"_id": oid}, {"$set": data}, return_document=True)
    if not res:
        raise HTTPException(status_code=404, detail="No encontrado")
    return _ser(res)


async def _delete(col: str, item_id: str):
    db = get_db()
    oid = _oid(item_id)
    r = await db[col].delete_one({"_id": oid})
    if r.deleted_count == 0:
        raise HTTPException(status_code=404, detail="No encontrado")
    return {"ok": True}


# -------- services ----------
@router.get("/services")
async def list_services():
    return await _list("services")


@router.post("/services")
async def create_service(item: ServiceItem, _: dict = Depends(require_roles("admin"))):
    return await _create("services", item.model_dump())


@router.patch("/services/{item_id}")
async def update_service(item_id: str, item: ServiceItem, _: dict = Depends(require_roles("admin"))):
    return await _update("services", item_id, item.model_dump())


@router.delete("/services/{item_id}")
async def delete_service(item_id: str, _: dict = Depends(require_roles("admin"))):
    return await _delete("services", item_id)


# -------- testimonials ----------
@router.get("/testimonials")
async def list_testimonials():
    return await _list("testimonials")


@router.post("/testimonials")
async def create_testimonial(item: TestimonialItem, _: dict = Depends(require_roles("admin"))):
    return await _create("testimonials", item.model_dump())


@router.patch("/testimonials/{item_id}")
async def update_testimonial(item_id: str, item: TestimonialItem, _: dict = Depends(require_roles("admin"))):
    return await _update("testimonials", item_id, item.model_dump())


@router.delete("/testimonials/{item_id}")
async def delete_testimonial(item_id: str, _: dict = Depends(require_roles("admin"))):
    return await _delete("testimonials", item_id)


# -------- portfolio ----------
@router.get("/portfolio")
async def list_portfolio():
    return await _list("portfolio")


@router.post("/portfolio")
async def create_portfolio(item: PortfolioItem, _: dict = Depends(require_roles("admin"))):
    return await _create("portfolio", item.model_dump())


@router.patch("/portfolio/{item_id}")
async def update_portfolio(item_id: str, item: PortfolioItem, _: dict = Depends(require_roles("admin"))):
    return await _update("portfolio", item_id, item.model_dump())


@router.delete("/portfolio/{item_id}")
async def delete_portfolio(item_id: str, _: dict = Depends(require_roles("admin"))):
    return await _delete("portfolio", item_id)
