# 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 RedirectResponse, JSONResponse
from devplacepy.database import get_table, get_poll_for_post, _now_iso
from devplacepy.utils import generate_uid, require_user, track_action, redirect_back
from devplacepy.models import PollVoteForm
from devplacepy.services.audit import record as audit
from devplacepy.dependencies import json_or_form

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

@router.post("/{poll_uid}/vote")
async def vote_poll(
    request: Request, poll_uid: str, data: Annotated[PollVoteForm, Depends(json_or_form(PollVoteForm))]
):
    user = require_user(request)
    poll = get_table("polls").find_one(uid=poll_uid, deleted_at=None)
    if not poll:
        return JSONResponse({"error": "Poll not found"}, status_code=404)
    option = get_table("poll_options").find_one(
        uid=data.option_uid, poll_uid=poll_uid, deleted_at=None
    )
    if not option:
        return JSONResponse({"error": "Invalid option"}, status_code=400)

    poll_votes = get_table("poll_votes")
    existing = poll_votes.find_one(poll_uid=poll_uid, user_uid=user["uid"])
    if existing:
        if existing.get("deleted_at"):
            poll_votes.update(
                {
                    "id": existing["id"],
                    "option_uid": data.option_uid,
                    "deleted_at": None,
                    "deleted_by": None,
                },
                ["id"],
            )
            poll_event = "poll.vote.cast"
        elif existing["option_uid"] == data.option_uid:
            poll_votes.update(
                {"id": existing["id"], "deleted_at": _now_iso(), "deleted_by": user["uid"]},
                ["id"],
            )
            poll_event = "poll.vote.clear"
        else:
            poll_votes.update(
                {"id": existing["id"], "option_uid": data.option_uid}, ["id"]
            )
            poll_event = "poll.vote.change"
    else:
        poll_votes.insert(
            {
                "uid": generate_uid(),
                "poll_uid": poll_uid,
                "option_uid": data.option_uid,
                "user_uid": user["uid"],
                "created_at": datetime.now(timezone.utc).isoformat(),
                "deleted_at": None,
                "deleted_by": None,
            }
        )
        poll_event = "poll.vote.cast"

    audit.record(
        request,
        poll_event,
        user=user,
        target_type="poll",
        target_uid=poll_uid,
        old_value=existing["option_uid"] if existing else None,
        new_value=None if poll_event == "poll.vote.clear" else data.option_uid,
        metadata={"question": poll.get("question")},
        summary=f"{user['username']} {poll_event.split('.')[-1]} vote in poll {poll.get('question')}",
        links=[audit.poll(poll_uid, poll.get("question")), audit.option(data.option_uid, option.get("label"))],
    )
    if poll_event == "poll.vote.cast":
        track_action(user["uid"], "poll")

    result = get_poll_for_post(poll["post_uid"], user)
    if request.headers.get("x-requested-with") == "fetch":
        return JSONResponse(result)
    return RedirectResponse(url=redirect_back(request), status_code=302)
