from typing import List, Optional

from django.db.models import F
from django.shortcuts import get_object_or_404
from ninja import Router, Schema
from ninja.pagination import paginate, PaginationBase

from .auth import AuthBearer
from .models import Post, Category, Tag
from .schemas import (
    PostCreate,
    PostUpdate,
    PostOut,
    ErrorMessage,
)

router = Router()


class PaginatedPostResponse(Schema):
    items: List[PostOut]
    total: int
    page: int
    size: int
    pages: int


@router.get("", response=PaginatedPostResponse)
def list_posts(
    request,
    page: int = 1,
    size: int = 10,
    category_id: Optional[int] = None,
    tag_id: Optional[int] = None,
    author_id: Optional[int] = None,
    search: Optional[str] = None,
    sort: Optional[str] = None
):
    posts = Post.objects.filter(is_deleted=False)
    
    if category_id:
        posts = posts.filter(category_id=category_id)
    if tag_id:
        posts = posts.filter(tags__id=tag_id)
    if author_id:
        posts = posts.filter(author_id=author_id)
    if search:
        posts = posts.filter(title__icontains=search) | \
               posts.filter(content__icontains=search)
    
    # 根据排序参数排序
    if sort == 'hot':
        posts = posts.order_by('-views_count')
    elif sort == 'latest':
        posts = posts.order_by('-created_at')
    else:
        # 默认按创建时间倒序
        posts = posts.order_by('-created_at')
    
    # 计算总数
    total = posts.count()
    
    # 计算总页数
    pages = (total + size - 1) // size
    
    # 分页
    offset = (page - 1) * size
    posts = posts.select_related('author', 'category').prefetch_related('tags')[offset:offset + size]
    
    return {
        "items": list(posts),
        "total": total,
        "page": page,
        "size": size,
        "pages": pages
    }


@router.get("/{post_id}", response={200: PostOut, 404: ErrorMessage})
def get_post(request, post_id: int):
    post = get_object_or_404(Post.objects.filter(is_deleted=False), id=post_id)
    # 增加浏览数
    Post.objects.filter(id=post_id).update(views_count=F('views_count') + 1)
    # 重新获取更新后的文章
    post.refresh_from_db()
    return 200, post


@router.post("", response={201: PostOut, 400: ErrorMessage}, auth=AuthBearer())
def create_post(request, data: PostCreate):
    # 如果没有提供摘要，从内容中生成
    if not data.summary:
        # 取内容前100个字符作为摘要
        data.summary = data.content[:100] + '...' if len(data.content) > 100 else data.content

    post = Post.objects.create(
        title=data.title,
        content=data.content,
        summary=data.summary,  # 现在一定会有摘要
        author=request.auth,
        category_id=data.category_id
    )
    
    # 验证标签是否都存在
    tags = []
    if data.tag_ids:
        tags = Tag.objects.filter(id__in=data.tag_ids)
        if len(tags) != len(data.tag_ids):
            return 400, {"detail": "Some tags do not exist"}
    
    # 添加标签
    if tags:
        post.tags.set(tags)
    
    return 201, post


@router.put("/{post_id}", response={200: PostOut, 400: ErrorMessage, 404: ErrorMessage}, auth=AuthBearer())
def update_post(request, post_id: int, data: PostUpdate):
    try:
        post = Post.objects.get(id=post_id, author=request.auth, is_deleted=False)
        
        if data.title is not None:
            post.title = data.title
        if data.content is not None:
            post.content = data.content
        if data.summary is not None:
            post.summary = data.summary
            
        if data.category_id is not None:
            try:
                category = Category.objects.get(id=data.category_id)
                post.category = category
            except Category.DoesNotExist:
                return 400, {"detail": "Category does not exist"}
                
        if data.tag_ids is not None:
            try:
                tags = Tag.objects.filter(id__in=data.tag_ids)
                if len(tags) != len(data.tag_ids):
                    return 400, {"detail": "Some tags do not exist"}
                post.tags.set(tags)
            except:
                return 400, {"detail": "Invalid tag ids"}
        
        post.save()
        return 200, post
        
    except Post.DoesNotExist:
        return 404, {"detail": "Post not found or you don't have permission to edit it"}


@router.delete("/{post_id}", response={204: None, 404: ErrorMessage}, auth=AuthBearer())
def delete_post(request, post_id: int):
    post = get_object_or_404(Post, id=post_id, author=request.auth, is_deleted=False)
    post.delete()  # 这里会调用我们的软删除方法
    return 204, None


@router.get("/my/posts", response=PaginatedPostResponse, auth=AuthBearer())
def get_user_posts(
    request,
    page: int = 1,
    size: int = 10,
):
    """获取当前用户的帖子列表"""
    posts = Post.objects.filter(
        is_deleted=False,
        author=request.auth
    ).select_related('author', 'category').prefetch_related('tags')
    
    # 计算总数
    total = posts.count()
    
    # 计算总页数
    pages = (total + size - 1) // size
    
    # 分页
    offset = (page - 1) * size
    posts = posts[offset:offset + size]
    
    return {
        "items": list(posts),
        "total": total,
        "page": page,
        "size": size,
        "pages": pages
    }
