import logging
from datetime import datetime, timezone
from fastapi import APIRouter, Request, HTTPException
from fastapi.responses import HTMLResponse, RedirectResponse
from devplacepy.database import get_table, load_comments, get_vote_counts, resolve_by_slug, db
from devplacepy.attachments import get_attachments, delete_target_attachments
from devplacepy.templating import templates
from devplacepy.utils import generate_uid, get_current_user, require_user, time_ago, make_combined_slug, create_mention_notifications
from devplacepy.seo import base_seo_context, site_url, website_schema, breadcrumb_schema, combine, software_source_code_schema

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"),
    ("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):
    gists_table = get_table("gists")
    filters = {}
    if user_uid:
        filters["user_uid"] = user_uid
    if language:
        filters["language"] = language

    all_gists = list(gists_table.find(**filters, order_by=["-created_at"]))

    if not all_gists:
        return []

    from devplacepy.database import get_users_by_uids
    uids = [g["user_uid"] for g in all_gists]
    users_map = get_users_by_uids(uids)

    result = []
    for g in all_gists:
        author = users_map.get(g["user_uid"])
        result.append({
            "gist": g,
            "author": author,
            "time_ago": time_ago(g["created_at"]),
        })
    return result


@router.get("", response_class=HTMLResponse)
async def gists_page(request: Request, language: str = None, user_uid: str = None):
    user = get_current_user(request)
    gists_data = get_gists_list(user_uid, language)
    total_count = len(gists_data)
    base = site_url(request)
    seo_ctx = base_seo_context(
        request,
        title="Gists",
        description=f"Browse {total_count} code snippets on DevPlace.",
        breadcrumbs=[
            {"name": "Home", "url": "/feed"},
            {"name": "Gists", "url": "/gists"},
        ],
        schemas=[website_schema(base)],
    )
    return templates.TemplateResponse(request, "gists.html", {
        **seo_ctx,
        "request": request,
        "user": user,
        "gists": gists_data,
        "total_count": total_count,
        "current_language": language,
        "languages": LANGUAGES,
    })


@router.get("/{gist_slug}", response_class=HTMLResponse)
async def gist_detail(request: Request, gist_slug: str):
    user = get_current_user(request)
    gists = get_table("gists")
    gist = resolve_by_slug(gists, gist_slug)
    if not gist:
        raise HTTPException(status_code=404, detail="Gist not found")

    from devplacepy.database import get_users_by_uids
    users_map = get_users_by_uids([gist["user_uid"]])
    author = users_map.get(gist["user_uid"])

    is_owner = user and user["uid"] == gist["user_uid"]

    ups, downs = get_vote_counts([gist["uid"]])
    star_count = ups.get(gist["uid"], 0) - downs.get(gist["uid"], 0)

    comments = load_comments("gist", gist["uid"])

    gist_attachments = get_attachments("gist", gist["uid"])

    base = site_url(request)
    seo_ctx = base_seo_context(
        request,
        title=gist.get("title", "Gist"),
        description=gist.get("description", "")[:160],
        og_type="article",
        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 templates.TemplateResponse(request, "gist_detail.html", {
        **seo_ctx,
        "request": request,
        "user": user,
        "gist": gist,
        "author": author,
        "is_owner": is_owner,
        "star_count": star_count,
        "time_ago": time_ago(gist["created_at"]),
        "comments": comments,
        "languages": LANGUAGES,
        "attachments": gist_attachments,
    })


@router.post("/create")
async def create_gist(request: Request):
    user = require_user(request)
    form = await request.form()
    title = form.get("title", "").strip()
    description = form.get("description", "").strip()
    source_code = form.get("source_code", "").strip()
    language = form.get("language", "plaintext")

    if not title:
        return RedirectResponse(url="/gists", status_code=302)
    if len(title) > 200:
        return RedirectResponse(url="/gists", status_code=302)
    if not source_code:
        return RedirectResponse(url="/gists", status_code=302)
    if len(source_code) > 50000:
        return RedirectResponse(url="/gists", status_code=302)
    if len(description) > 5000:
        return RedirectResponse(url="/gists", status_code=302)

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

    gists = get_table("gists")
    uid = generate_uid()
    gist_slug = make_combined_slug(title, uid)
    gists.insert({
        "uid": uid,
        "user_uid": user["uid"],
        "title": title,
        "slug": gist_slug,
        "description": description or None,
        "source_code": source_code,
        "language": language,
        "stars": 0,
        "created_at": datetime.now(timezone.utc).isoformat(),
    })

    attachment_uids = form.getlist("attachment_uids") if hasattr(form, "getlist") else []

    from devplacepy.attachments import link_attachments
    link_attachments(attachment_uids, "gist", uid)

    create_mention_notifications(description or "", user["uid"], f"/gists/{gist_slug}")

    logger.info(f"Gist {uid} created by {user['username']}")
    return RedirectResponse(url=f"/gists/{gist_slug}", status_code=302)


@router.post("/edit/{gist_slug}")
async def edit_gist(request: Request, gist_slug: str):
    user = require_user(request)
    gists = get_table("gists")
    gist = resolve_by_slug(gists, gist_slug)
    if not gist or gist["user_uid"] != user["uid"]:
        return RedirectResponse(url="/gists", status_code=302)

    form = await request.form()
    title = form.get("title", "").strip()
    description = form.get("description", "").strip()
    source_code = form.get("source_code", "").strip()
    language = form.get("language", "plaintext")

    if not title or len(title) > 200:
        return RedirectResponse(url=f"/gists/{gist['slug'] or gist['uid']}", status_code=302)
    if not source_code or len(source_code) > 50000:
        return RedirectResponse(url=f"/gists/{gist['slug'] or gist['uid']}", status_code=302)
    if len(description) > 5000:
        return RedirectResponse(url=f"/gists/{gist['slug'] or gist['uid']}", status_code=302)

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

    gists.update({
        "uid": gist["uid"],
        "title": title,
        "description": description or None,
        "source_code": source_code,
        "language": language,
    }, ["uid"])

    logger.info(f"Gist {gist['uid']} edited by {user['username']}")
    return RedirectResponse(url=f"/gists/{gist['slug'] or gist['uid']}", status_code=302)


@router.post("/delete/{gist_slug}")
async def delete_gist(request: Request, gist_slug: str):
    user = require_user(request)
    gists = get_table("gists")
    gist = resolve_by_slug(gists, gist_slug)
    if gist and gist["user_uid"] == user["uid"]:
        from devplacepy.attachments import delete_target_attachments
        delete_target_attachments("gist", gist["uid"])
        if "comments" in db.tables:
            for c in get_table("comments").find(target_type="gist", target_uid=gist["uid"]):
                delete_target_attachments("comment", c["uid"])
            get_table("comments").delete(target_type="gist", target_uid=gist["uid"])
        if "votes" in db.tables:
            get_table("votes").delete(target_type="gist", target_uid=gist["uid"])
        gists.delete(id=gist["id"])
        logger.info(f"Gist {gist['uid']} deleted by {user['username']}")
    return RedirectResponse(url="/gists", status_code=302)
