# retoor <retoor@molodetz.nl>

from typing import Optional

from devplacepy.database import (
    get_table,
    get_users_by_uids,
    get_user_votes,
    get_vote_counts,
    get_user_stars,
)
from devplacepy.avatar import avatar_seed
from devplacepy.services.devrant.avatar import avatar_payload
from devplacepy.services.devrant.feed import build_rant_list
from devplacepy.services.devrant.ids import to_unix
from devplacepy.services.devrant.serializers import serialize_comment

PROFILE_RANT_LIMIT = 50
PROFILE_COMMENT_LIMIT = 50
SKILLS_MAX_WORDS = 8


def skills_from_bio(bio: Optional[str]) -> str:
    if not bio:
        return ""
    words = bio.replace("\n", " ").split()
    return " ".join(words[:SKILLS_MAX_WORDS])


def _user_rants(user: dict, viewer: Optional[dict]) -> list:
    posts = list(
        get_table("posts").find(
            user_uid=user["uid"],
            deleted_at=None,
            order_by=["-created_at"],
            _limit=PROFILE_RANT_LIMIT,
        )
    )
    return build_rant_list(posts, viewer)


def _user_comments(user: dict, viewer: Optional[dict]) -> list:
    comments = list(
        get_table("comments").find(
            user_uid=user["uid"],
            target_type="post",
            deleted_at=None,
            order_by=["-created_at"],
            _limit=PROFILE_COMMENT_LIMIT,
        )
    )
    if not comments:
        return []
    target_uids = list({comment["target_uid"] for comment in comments})
    posts_table = get_table("posts")
    rant_ids = {
        post["uid"]: int(post["id"])
        for post in posts_table.find(posts_table.table.columns.uid.in_(target_uids))
    }
    comment_uids = [comment["uid"] for comment in comments]
    authors = get_users_by_uids([user["uid"]])
    user_scores = {user["uid"]: get_user_stars(user["uid"])}
    ups, downs = get_vote_counts(comment_uids)
    score_map = {uid: ups.get(uid, 0) - downs.get(uid, 0) for uid in comment_uids}
    my_votes = get_user_votes(viewer["uid"], comment_uids) if viewer else {}
    return [
        serialize_comment(
            comment,
            rant_ids.get(comment["target_uid"], 0),
            authors=authors,
            user_scores=user_scores,
            my_votes=my_votes,
            score_map=score_map,
        )
        for comment in comments
    ]


def build_profile(user: dict, viewer: Optional[dict]) -> dict:
    bio = user.get("bio") or ""
    rants = _user_rants(user, viewer)
    comments = _user_comments(user, viewer)
    return {
        "username": user.get("username") or "",
        "score": get_user_stars(user["uid"]),
        "about": bio,
        "location": user.get("location") or "",
        "created_time": to_unix(user.get("created_at")),
        "skills": skills_from_bio(bio),
        "github": user.get("git_link") or "",
        "website": user.get("website") or "",
        "avatar": avatar_payload(avatar_seed(user)),
        "content": {
            "content": {
                "rants": rants,
                "upvoted": [],
                "comments": comments,
                "favorites": [],
                "viewed": [],
            },
            "counts": {
                "rants": len(rants),
                "upvoted": 0,
                "comments": len(comments),
                "favorites": 0,
                "collabs": 0,
            },
        },
    }
