# retoor <retoor@molodetz.nl>

import logging
from typing import Annotated
from datetime import datetime, timezone
from fastapi import Depends, APIRouter, Request
from fastapi.responses import HTMLResponse
from devplacepy.constants import TOPICS
from devplacepy.database import (
    db,
    get_table,
    resolve_by_slug,
    resolve_object_url,
    mark_notifications_read_by_target,
)
from devplacepy.utils import (
    get_current_user,
    require_user,
    time_ago,
    not_found,
    generate_uid,
    XP_POST,
)
from devplacepy.content import (
    load_detail,
    edit_content_item,
    delete_content_item,
    create_content_item,
    detail_context,
    canonical_redirect,
    first_image_url,
)
from devplacepy.responses import respond, action_result
from devplacepy.schemas import PostDetailOut
from devplacepy.seo import (
    base_seo_context,
    site_url,
    website_schema,
    discussion_forum_posting,
    comment_schema_list,
)
from devplacepy.attachments import save_inline_image
from devplacepy.models import PostForm, PostEditForm
from devplacepy.services.audit import record as audit
from devplacepy.services.opinionwar import store as war_store
from devplacepy.dependencies import json_or_form

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

@router.post("/create")
async def create_post(request: Request, data: Annotated[PostForm, Depends(json_or_form(PostForm))]):
    user = require_user(request)
    content = data.content.strip()
    title = data.title.strip()
    topic = data.topic
    project_uid = data.project_uid

    image_filename = None
    form = await request.form()
    image_file = form.get("image")
    if (
        image_file is not None
        and hasattr(image_file, "filename")
        and image_file.filename
    ):
        image_filename = save_inline_image(await image_file.read(), image_file.filename)
        if image_filename:
            content += f"\n\n![](/static/uploads/{image_filename})"

    slug_text = title if title else content[:50]
    uid, post_slug = create_content_item(
        "posts",
        "post",
        user,
        {
            "title": title or None,
            "content": content,
            "topic": topic,
            "project_uid": project_uid or None,
            "image": image_filename,
        },
        slug_text,
        XP_POST,
        "First Post",
        content,
        data.attachment_uids,
        request,
    )

    create_poll(uid, user, data.poll_question, data.poll_options, request)
    war_store.create_war(uid, user, data.war_faction_a, data.war_faction_b, request)
    url = f"/posts/{post_slug}"
    return action_result(request, url, data={"uid": uid, "slug": post_slug, "url": url})

def create_poll(
    post_uid: str, user: dict, question: str, options: list[str], request=None
) -> None:
    question = question.strip()
    labels = [option.strip() for option in options if option.strip()][:6]
    if not question or len(labels) < 2:
        return
    poll_uid = generate_uid()
    get_table("polls").insert(
        {
            "uid": poll_uid,
            "post_uid": post_uid,
            "user_uid": user["uid"],
            "question": question,
            "created_at": datetime.now(timezone.utc).isoformat(),
            "deleted_at": None,
            "deleted_by": None,
        }
    )
    get_table("poll_options").insert_many(
        [
            {
                "uid": generate_uid(),
                "poll_uid": poll_uid,
                "label": label,
                "position": index,
                "deleted_at": None,
                "deleted_by": None,
            }
            for index, label in enumerate(labels)
        ]
    )
    audit.record(
        request,
        "poll.create",
        user=user,
        target_type="poll",
        target_uid=poll_uid,
        target_label=question,
        metadata={"option_count": len(labels), "question": question},
        summary=f"{user['username']} added a poll to post {post_uid}",
        links=[audit.poll(poll_uid, question), audit.parent("post", post_uid)],
    )

@router.get("/{post_slug}", response_class=HTMLResponse)
async def view_post(request: Request, post_slug: str):
    user = get_current_user(request)
    detail = load_detail("posts", "post", post_slug, user)
    if not detail:
        raise not_found("Post not found")
    post = detail["item"]
    redirect = canonical_redirect("posts", post, post_slug)
    if redirect:
        return redirect
    if user:
        mark_notifications_read_by_target(
            user["uid"], resolve_object_url("post", post["uid"])
        )
    author = detail["author"]
    top_level = detail["comments"]

    def count_all(items):
        total = len(items)
        for item in items:
            total += count_all(item.get("children", []))
        return total

    comment_count = count_all(top_level)
    base = site_url(request)
    seo_ctx = base_seo_context(
        request,
        title=post.get("title") or "Post",
        description=post.get("content", ""),
        seo_target=("post", post["uid"]),
        breadcrumbs=[
            {"name": "Home", "url": "/feed"},
            {"name": "Feed", "url": "/feed"},
            {
                "name": post.get("title") or "Post",
                "url": f"/posts/{post['slug'] or post['uid']}",
            },
        ],
        og_type="article",
        og_image=first_image_url(post, detail["attachments"]),
        schemas=[
            website_schema(base),
            discussion_forum_posting(
                post,
                author,
                comment_count,
                detail["star_count"],
                base,
                comments=comment_schema_list(top_level, base),
            ),
        ],
    )

    related_posts = []
    if "posts" in db.tables:
        rows = list(
            db.query(
                "SELECT p.*, u.username FROM posts p JOIN users u ON p.user_uid = u.uid WHERE p.topic = :t AND p.uid != :uid AND p.deleted_at IS NULL ORDER BY p.created_at DESC LIMIT 5",
                t=post.get("topic", ""),
                uid=post["uid"],
            )
        )
        for r in rows:
            related_posts.append(
                {
                    "post": r,
                    "author": {"username": r["username"]},
                    "time_ago": time_ago(r["created_at"]),
                }
            )

    return respond(
        request,
        "post.html",
        detail_context(
            request,
            user,
            detail,
            "post",
            seo_ctx,
            {
                "comment_count": comment_count,
                "related_posts": related_posts,
                "topics": list(TOPICS),
            },
        ),
        model=PostDetailOut,
    )

@router.post("/edit/{post_slug}")
async def edit_post(
    request: Request, post_slug: str, data: Annotated[PostEditForm, Depends(json_or_form(PostEditForm))]
):
    user = require_user(request)
    result = edit_content_item(
        request,
        "posts",
        user,
        post_slug,
        {
            "content": data.content.strip(),
            "title": data.title.strip() or None,
            "topic": data.topic,
        },
        "/feed",
        target_type="post",
    )
    if data.poll_question.strip():
        post = resolve_by_slug(get_table("posts"), post_slug)
        if (
            post
            and post["user_uid"] == user["uid"]
            and not get_table("polls").find_one(post_uid=post["uid"], deleted_at=None)
        ):
            create_poll(
                post["uid"], user, data.poll_question, data.poll_options, request
            )
    return result

@router.post("/delete/{post_slug}")
async def delete_post(request: Request, post_slug: str):
    user = require_user(request)
    return delete_content_item(
        request, "posts", "post", user, post_slug, "/feed", inline_image_field="image"
    )
