# retoor <retoor@molodetz.nl>

import logging
import secrets
from datetime import datetime, timezone

from fastapi import APIRouter, Request

from devplacepy.database import get_table
from devplacepy.utils import XP_POST
from devplacepy.content import (
    create_content_item,
    delete_content_item,
    apply_vote,
    create_comment_record,
    set_bookmark,
    is_owner,
    is_admin,
)
from devplacepy.services.audit import record as audit
from devplacepy.services.correction import schedule_correction
from devplacepy.services.ai_modifier import schedule_modification
from devplacepy.services.devrant.params import merge_params
from devplacepy.services.devrant.ids import as_int, post_by_id
from devplacepy.services.devrant.feed import list_rants, search_rants, load_rant_detail
from devplacepy.services.devrant.serializers import encode_tags
from devplacepy.routers.devrant._shared import dr_ok, dr_error, resolve_actor, unauthorized

logger = logging.getLogger(__name__)
router = APIRouter()

DEFAULT_LIMIT = 20
MAX_LIMIT = 50


def _parse_tags(raw: object) -> list:
    if not raw:
        return []
    if isinstance(raw, list):
        return [str(tag).strip() for tag in raw if str(tag).strip()]
    return [tag.strip() for tag in str(raw).split(",") if tag.strip()]


@router.get("/devrant/rants")
async def rant_feed(request: Request):
    params = await merge_params(request)
    viewer = resolve_actor(request, params)
    sort = params.get("sort") or "recent"
    limit = min(MAX_LIMIT, max(1, as_int(params.get("limit"), DEFAULT_LIMIT)))
    skip = max(0, as_int(params.get("skip"), 0))
    rants = list_rants(sort, limit, skip, viewer)
    num_notifs = 0
    if viewer:
        num_notifs = get_table("notifications").count(
            user_uid=viewer["uid"], read=False
        )
    return dr_ok(
        rants=rants,
        settings={"notif_state": -1, "notif_token": ""},
        set=secrets.token_hex(6),
        wrw=0,
        dpp=0,
        num_notifs=num_notifs,
        unread={"total": num_notifs},
        news=None,
    )


@router.get("/devrant/search")
async def search(request: Request):
    params = await merge_params(request)
    viewer = resolve_actor(request, params)
    term = (params.get("term") or "").strip()
    return dr_ok(results=search_rants(term, viewer) if term else [])


@router.post("/devrant/rants")
async def create_rant(request: Request):
    params = await merge_params(request)
    user = resolve_actor(request, params)
    if not user:
        return unauthorized()
    text = (params.get("rant") or "").strip()
    if len(text) < 1:
        return dr_error("Your rant is too short.")
    if len(text) > 125000:
        return dr_error("Your rant is too long.")
    tags = _parse_tags(params.get("tags"))
    project_uid = params.get("project_uid") or None
    uid, slug = create_content_item(
        "posts",
        "post",
        user,
        {
            "title": None,
            "content": text,
            "topic": "rant",
            "project_uid": project_uid,
            "image": None,
            "tags": encode_tags(tags),
        },
        text[:50],
        XP_POST,
        "First Post",
        text,
        None,
        request,
    )
    post = get_table("posts").find_one(uid=uid)
    return dr_ok(rant_id=int(post["id"]))


@router.get("/devrant/rants/{rant_id}")
async def get_rant(request: Request, rant_id: str):
    params = await merge_params(request)
    viewer = resolve_actor(request, params)
    post = post_by_id(rant_id)
    if not post:
        return dr_error("This rant does not exist.")
    detail = load_rant_detail(post, viewer)
    return dr_ok(rant=detail["rant"], comments=detail["comments"], subscribed=0)


@router.post("/devrant/rants/{rant_id}")
async def edit_rant(request: Request, rant_id: str):
    params = await merge_params(request)
    user = resolve_actor(request, params)
    if not user:
        return unauthorized()
    post = post_by_id(rant_id)
    if not post:
        return dr_error("This rant does not exist.", fail_reason="not_found")
    if not is_owner(post, user):
        return dr_error("You can only edit your own rants.", fail_reason="not_owner")
    text = (params.get("rant") or "").strip()
    if len(text) < 1 or len(text) > 125000:
        return dr_error("Invalid rant length.", fail_reason="length")
    tags = _parse_tags(params.get("tags"))
    get_table("posts").update(
        {
            "uid": post["uid"],
            "content": text,
            "tags": encode_tags(tags),
            "updated_at": datetime.now(timezone.utc).isoformat(),
        },
        ["uid"],
    )
    schedule_correction(user, "posts", post["uid"], request)
    schedule_modification(user, "posts", post["uid"], request)
    audit.record(
        request,
        "post.edit",
        user=user,
        target_type="post",
        target_uid=post["uid"],
        origin="devrant",
        summary=f"{user['username']} edited rant {post['id']}",
        links=[audit.target("post", post["uid"])],
    )
    return dr_ok()


@router.delete("/devrant/rants/{rant_id}")
async def delete_rant(request: Request, rant_id: str):
    params = await merge_params(request)
    user = resolve_actor(request, params)
    if not user:
        return unauthorized()
    post = post_by_id(rant_id)
    if not post:
        return dr_error("This rant does not exist.")
    if not (is_owner(post, user) or is_admin(user)):
        return dr_error("You can only delete your own rants.")
    delete_content_item(request, "posts", "post", user, post["slug"], "/feed")
    return dr_ok()


@router.post("/devrant/rants/{rant_id}/vote")
async def vote_rant(request: Request, rant_id: str):
    params = await merge_params(request)
    user = resolve_actor(request, params)
    if not user:
        return unauthorized()
    post = post_by_id(rant_id)
    if not post:
        return dr_error("This rant does not exist.")
    value = as_int(params.get("vote"))
    if value not in (-1, 0, 1):
        return dr_error("Invalid vote.")
    apply_vote(request, user, "post", post["uid"], value)
    fresh = get_table("posts").find_one(uid=post["uid"])
    detail = load_rant_detail(fresh, user)
    return dr_ok(rant=detail["rant"])


@router.post("/devrant/rants/{rant_id}/favorite")
async def favorite_rant(request: Request, rant_id: str):
    return await _set_favorite(request, rant_id, True)


@router.post("/devrant/rants/{rant_id}/unfavorite")
async def unfavorite_rant(request: Request, rant_id: str):
    return await _set_favorite(request, rant_id, False)


async def _set_favorite(request: Request, rant_id: str, saved: bool):
    params = await merge_params(request)
    user = resolve_actor(request, params)
    if not user:
        return unauthorized()
    post = post_by_id(rant_id)
    if not post:
        return dr_error("This rant does not exist.")
    set_bookmark(request, user, "post", post["uid"], saved)
    return dr_ok()


@router.post("/devrant/rants/{rant_id}/comments")
async def comment_rant(request: Request, rant_id: str):
    params = await merge_params(request)
    user = resolve_actor(request, params)
    if not user:
        return unauthorized()
    post = post_by_id(rant_id)
    if not post:
        return dr_error("This rant does not exist.")
    text = (params.get("comment") or "").strip()
    if len(text) < 1:
        return dr_error("Your comment is too short.")
    if len(text) > 1000:
        return dr_error("Your comment is too long.")
    create_comment_record(request, user, "post", post["uid"], text)
    return dr_ok()
