# retoor <retoor@molodetz.nl>

import logging
from typing import Annotated
from fastapi import Depends, APIRouter, Request
from devplacepy.models import GistForm, GistEditForm
from fastapi.responses import HTMLResponse
from devplacepy.database import (
    get_table,
    get_users_by_uids,
    get_gist_languages,
    get_recent_comments_by_target_uids,
    paginate,
    text_search_clause,
    resolve_object_url,
    mark_notifications_read_by_target,
)
from devplacepy.content import (
    load_detail,
    edit_content_item,
    delete_content_item,
    enrich_items,
    create_content_item,
    detail_context,
    canonical_redirect,
    first_image_url,
)
from devplacepy.utils import get_current_user, require_user, not_found, XP_GIST
from devplacepy.seo import (
    base_seo_context,
    site_url,
    website_schema,
    software_source_code_schema,
    list_page_seo,
    next_page_url,
)
from devplacepy.responses import respond, action_result
from devplacepy.schemas import GistsOut, GistDetailOut
from devplacepy.dependencies import json_or_form

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

LANGUAGES = [
    ("python", "Python"),
    ("javascript", "JavaScript"),
    ("typescript", "TypeScript"),
    ("html", "HTML"),
    ("css", "CSS"),
    ("c", "C"),
    ("cpp", "C++"),
    ("java", "Java"),
    ("go", "Go"),
    ("rust", "Rust"),
    ("sql", "SQL"),
    ("bash", "Bash"),
    ("yaml", "YAML"),
    ("json", "JSON"),
    ("markdown", "Markdown"),
    ("markdown_rendered", "Markdown Rendered"),
    ("swift", "Swift"),
    ("php", "PHP"),
    ("ruby", "Ruby"),
    ("kotlin", "Kotlin"),
    ("lua", "Lua"),
    ("perl", "Perl"),
    ("haskell", "Haskell"),
    ("elixir", "Elixir"),
    ("r", "R"),
    ("dart", "Dart"),
    ("scala", "Scala"),
    ("plaintext", "Plain Text"),
]

def get_gists_list(user_uid=None, language=None, search="", before=None, viewer=None):
    gists_table = get_table("gists")
    filters = {}
    if user_uid:
        filters["user_uid"] = user_uid
    if language:
        filters["language"] = language

    search_match = text_search_clause(
        gists_table, search, ("title", "description"), author_field="user_uid"
    )
    clauses = [search_match] if search_match is not None else []

    total = gists_table.count(*clauses, deleted_at=None, **filters)
    gists, next_cursor = paginate(
        gists_table,
        *clauses,
        before=before,
        viewer_uid=viewer["uid"] if viewer else None,
        **filters,
    )

    if not gists:
        return [], next_cursor, total

    users_map = get_users_by_uids([g["user_uid"] for g in gists])
    enriched = enrich_items(gists, "gist", users_map, user=viewer)
    recent_comments = get_recent_comments_by_target_uids(
        "gist", [g["uid"] for g in gists], 3, viewer
    )
    for item in enriched:
        item["recent_comments"] = recent_comments.get(item["gist"]["uid"], [])
    return enriched, next_cursor, total

@router.get("", response_class=HTMLResponse)
async def gists_page(
    request: Request,
    language: str = None,
    user_uid: str = None,
    search: str = "",
    before: str = None,
):
    user = get_current_user(request)
    gists_list, next_cursor, total_count = get_gists_list(
        user_uid, language, search, before, viewer=user
    )
    seo_ctx = list_page_seo(
        request,
        title="Gists",
        description=f"Browse {total_count} code snippets on DevPlace.",
        breadcrumbs=[
            {"name": "Home", "url": "/feed"},
            {"name": "Gists", "url": "/gists"},
        ],
        next_url=next_page_url(request, next_cursor),
    )
    return respond(
        request,
        "gists.html",
        {
            **seo_ctx,
            "request": request,
            "user": user,
            "gists": gists_list,
            "total_count": total_count,
            "next_cursor": next_cursor,
            "current_language": language,
            "search": search,
            "languages": LANGUAGES,
            "gist_language_codes": get_gist_languages(),
        },
        model=GistsOut,
    )

@router.get("/{gist_slug}", response_class=HTMLResponse)
async def gist_detail(request: Request, gist_slug: str):
    user = get_current_user(request)
    detail = load_detail("gists", "gist", gist_slug, user)
    if not detail:
        raise not_found("Gist not found")
    gist = detail["item"]
    redirect = canonical_redirect("gists", gist, gist_slug)
    if redirect:
        return redirect
    if user:
        mark_notifications_read_by_target(
            user["uid"], resolve_object_url("gist", gist["uid"])
        )

    base = site_url(request)
    seo_ctx = base_seo_context(
        request,
        title=gist.get("title", "Gist"),
        description=gist.get("description") or "",
        seo_target=("gist", gist["uid"]),
        og_type="article",
        og_image=first_image_url(gist, detail["attachments"]),
        breadcrumbs=[
            {"name": "Home", "url": "/feed"},
            {"name": "Gists", "url": "/gists"},
            {
                "name": gist.get("title", "Gist"),
                "url": f"/gists/{gist['slug'] or gist['uid']}",
            },
        ],
        schemas=[website_schema(base), software_source_code_schema(gist, base)],
    )
    return respond(
        request,
        "gist_detail.html",
        detail_context(
            request,
            user,
            detail,
            "gist",
            seo_ctx,
            {
                "languages": LANGUAGES,
            },
        ),
        model=GistDetailOut,
    )

@router.post("/create")
async def create_gist(request: Request, data: Annotated[GistForm, Depends(json_or_form(GistForm))]):
    user = require_user(request)
    title = data.title.strip()
    description = data.description.strip()
    source_code = data.source_code.strip()
    language = data.language

    valid_languages = {lang[0] for lang in LANGUAGES}
    if language not in valid_languages:
        language = "plaintext"

    uid, gist_slug = create_content_item(
        "gists",
        "gist",
        user,
        {
            "title": title,
            "description": description or None,
            "source_code": source_code,
            "language": language,
        },
        title,
        XP_GIST,
        "First Gist",
        description or "",
        data.attachment_uids,
        request,
    )
    url = f"/gists/{gist_slug}"
    return action_result(request, url, data={"uid": uid, "slug": gist_slug, "url": url})

@router.post("/edit/{gist_slug}")
async def edit_gist(
    request: Request, gist_slug: str, data: Annotated[GistEditForm, Depends(json_or_form(GistEditForm))]
):
    user = require_user(request)
    language = data.language
    if language not in {lang[0] for lang in LANGUAGES}:
        language = "plaintext"
    return edit_content_item(
        request,
        "gists",
        user,
        gist_slug,
        {
            "title": data.title.strip(),
            "description": data.description.strip() or None,
            "source_code": data.source_code.strip(),
            "language": language,
        },
        "/gists",
        target_type="gist",
    )

@router.post("/delete/{gist_slug}")
async def delete_gist(request: Request, gist_slug: str):
    user = require_user(request)
    return delete_content_item(request, "gists", "gist", user, gist_slug, "/gists")
