# 用户关注和收藏 API 视图
# 提供关注、取消关注、收藏、取消收藏等功能

import json
import logging
from functools import wraps
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.shortcuts import get_object_or_404

from blog.models import Article
from blog.models_social import UserFollow, ArticleFavorite, ArticleLike
from blog.rate_limit import rate_limit, user_rate_limit

logger = logging.getLogger(__name__)
User = get_user_model()


def ajax_login_required(view_func):
    """
    自定义装饰器：AJAX请求时返回JSON响应而不是重定向
    """
    @wraps(view_func)
    def wrapper(request, *args, **kwargs):
        if not request.user.is_authenticated:
            return JsonResponse({
                'success': False,
                'message': '请先登录',
                'login_required': True
            }, status=401)
        return view_func(request, *args, **kwargs)
    return wrapper


# ==================== 关注相关 API ====================

@ajax_login_required
@require_http_methods(["POST"])
@user_rate_limit(limit={'requests': 20, 'window': 60}, scope='follow')  # 20次/分钟
def follow_user_api(request):
    """
    关注用户 API

    POST 参数：
        - user_id: 要关注的用户ID

    返回：
        JSON: {success: true, message: xxx}
    """
    try:
        data = json.loads(request.body)
        user_id = data.get('user_id')

        if not user_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 user_id 参数'
            }, status=400)

        # 获取要关注的用户
        following_user = get_object_or_404(User, id=user_id)

        # 不能关注自己
        if following_user == request.user:
            return JsonResponse({
                'success': False,
                'message': '不能关注自己'
            }, status=400)

        # 执行关注
        follow = UserFollow.follow(request.user, following_user)

        if follow:
            return JsonResponse({
                'success': True,
                'message': f'已关注 {following_user.username}',
                'following_count': UserFollow.get_following_count(request.user),
                'is_following': True
            })
        else:
            return JsonResponse({
                'success': False,
                'message': '已经关注过该用户'
            }, status=400)

    except User.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '用户不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"关注用户失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'关注失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["POST"])
@user_rate_limit(limit={'requests': 20, 'window': 60}, scope='unfollow')  # 20次/分钟
def unfollow_user_api(request):
    """
    取消关注用户 API

    POST 参数：
        - user_id: 要取消关注的用户ID

    返回：
        JSON: {success: true, message: xxx}
    """
    try:
        data = json.loads(request.body)
        user_id = data.get('user_id')

        if not user_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 user_id 参数'
            }, status=400)

        # 获取要取消关注的用户
        following_user = get_object_or_404(User, id=user_id)

        # 执行取消关注
        success = UserFollow.unfollow(request.user, following_user)

        if success:
            return JsonResponse({
                'success': True,
                'message': f'已取消关注 {following_user.username}',
                'following_count': UserFollow.get_following_count(request.user),
                'is_following': False
            })
        else:
            return JsonResponse({
                'success': False,
                'message': '未关注该用户'
            }, status=400)

    except User.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '用户不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"取消关注失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'取消关注失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["GET"])
@user_rate_limit(limit={'requests': 100, 'window': 60}, scope='check_following')  # 100次/分钟
def check_following_api(request):
    """
    检查是否已关注某用户 API

    GET 参数：
        - user_id: 用户ID

    返回：
        JSON: {success: true, is_following: true/false}
    """
    try:
        user_id = request.GET.get('user_id')

        if not user_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 user_id 参数'
            }, status=400)

        following_user = get_object_or_404(User, id=user_id)
        is_following = UserFollow.is_following(request.user, following_user)

        return JsonResponse({
            'success': True,
            'is_following': is_following
        })

    except User.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '用户不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"检查关注状态失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'检查失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["GET"])
@user_rate_limit(limit={'requests': 50, 'window': 60}, scope='following_list')  # 50次/分钟
def following_list_api(request):
    """
    获取关注列表 API

    GET 参数：
        - user_id: 用户ID（可选，默认为当前用户）
        - limit: 返回数量限制（可选）

    返回：
        JSON: {success: true, following: [...], count: xxx}
    """
    try:
        user_id = request.GET.get('user_id')
        limit = request.GET.get('limit', 20)

        try:
            limit = int(limit)
        except ValueError:
            limit = 20

        # 获取用户
        if user_id:
            user = get_object_or_404(User, id=user_id)
        else:
            user = request.user

        # 获取关注列表
        following_list = UserFollow.get_following_list(user, limit)

        following_data = []
        for u in following_list:
            following_data.append({
                'id': u.id,
                'username': u.username,
                'email': u.email if u == request.user else None,
                'date_joined': u.date_joined.strftime('%Y-%m-%d')
            })

        return JsonResponse({
            'success': True,
            'following': following_data,
            'count': UserFollow.get_following_count(user),
            'total_count': len(following_data)
        })

    except User.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '用户不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"获取关注列表失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'获取失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["GET"])
@user_rate_limit(limit={'requests': 50, 'window': 60}, scope='followers_list')  # 50次/分钟
def followers_list_api(request):
    """
    获取粉丝列表 API

    GET 参数：
        - user_id: 用户ID（可选，默认为当前用户）
        - limit: 返回数量限制（可选）

    返回：
        JSON: {success: true, followers: [...], count: xxx}
    """
    try:
        user_id = request.GET.get('user_id')
        limit = request.GET.get('limit', 20)

        try:
            limit = int(limit)
        except ValueError:
            limit = 20

        # 获取用户
        if user_id:
            user = get_object_or_404(User, id=user_id)
        else:
            user = request.user

        # 获取粉丝列表
        followers_list = UserFollow.get_followers_list(user, limit)

        followers_data = []
        for u in followers_list:
            followers_data.append({
                'id': u.id,
                'username': u.username,
                'date_joined': u.date_joined.strftime('%Y-%m-%d')
            })

        return JsonResponse({
            'success': True,
            'followers': followers_data,
            'count': UserFollow.get_followers_count(user),
            'total_count': len(followers_data)
        })

    except User.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '用户不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"获取粉丝列表失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'获取失败: {str(e)}'
        }, status=500)


# ==================== 收藏相关 API ====================

@ajax_login_required
@require_http_methods(["POST"])
@user_rate_limit(limit={'requests': 30, 'window': 60}, scope='favorite')  # 30次/分钟
def favorite_article_api(request):
    """
    收藏文章 API

    POST 参数：
        - article_id: 文章ID
        - note: 收藏备注（可选）

    返回：
        JSON: {success: true, message: xxx}
    """
    try:
        data = json.loads(request.body)
        article_id = data.get('article_id')
        note = data.get('note', '')

        if not article_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 article_id 参数'
            }, status=400)

        # 获取文章
        article = get_object_or_404(Article, id=article_id)

        # 执行收藏
        favorite = ArticleFavorite.add_favorite(request.user, article, note)

        if favorite:
            return JsonResponse({
                'success': True,
                'message': f'已收藏文章《{article.title}》',
                'favorite_count': ArticleFavorite.get_article_favorite_count(article),  # 返回文章被收藏次数
                'user_favorite_count': ArticleFavorite.get_favorite_count(request.user),  # 返回用户收藏总数
                'is_favorited': True
            })
        else:
            return JsonResponse({
                'success': False,
                'message': '已经收藏过该文章'
            }, status=400)

    except Article.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '文章不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"收藏文章失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'收藏失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["POST"])
@user_rate_limit(limit={'requests': 30, 'window': 60}, scope='unfavorite')  # 30次/分钟
def unfavorite_article_api(request):
    """
    取消收藏文章 API

    POST 参数：
        - article_id: 文章ID

    返回：
        JSON: {success: true, message: xxx}
    """
    try:
        data = json.loads(request.body)
        article_id = data.get('article_id')

        if not article_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 article_id 参数'
            }, status=400)

        # 获取文章
        article = get_object_or_404(Article, id=article_id)

        # 执行取消收藏
        success = ArticleFavorite.remove_favorite(request.user, article)

        if success:
            return JsonResponse({
                'success': True,
                'message': f'已取消收藏《{article.title}》',
                'favorite_count': ArticleFavorite.get_article_favorite_count(article),  # 返回文章被收藏次数
                'user_favorite_count': ArticleFavorite.get_favorite_count(request.user),  # 返回用户收藏总数
                'is_favorited': False
            })
        else:
            return JsonResponse({
                'success': False,
                'message': '未收藏该文章'
            }, status=400)

    except Article.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '文章不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"取消收藏失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'取消收藏失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["GET"])
@user_rate_limit(limit={'requests': 100, 'window': 60}, scope='check_favorite')  # 100次/分钟
def check_favorite_api(request):
    """
    检查是否已收藏某文章 API

    GET 参数：
        - article_id: 文章ID

    返回：
        JSON: {success: true, is_favorited: true/false}
    """
    try:
        article_id = request.GET.get('article_id')

        if not article_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 article_id 参数'
            }, status=400)

        article = get_object_or_404(Article, id=article_id)
        is_favorited = ArticleFavorite.is_favorited(request.user, article)

        return JsonResponse({
            'success': True,
            'is_favorited': is_favorited,
            'favorite_count': ArticleFavorite.get_article_favorite_count(article),  # 文章被收藏次数
            'user_favorite_count': ArticleFavorite.get_favorite_count(request.user)  # 用户收藏总数
        })

    except Article.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '文章不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"检查收藏状态失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'检查失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["GET"])
@user_rate_limit(limit={'requests': 50, 'window': 60}, scope='favorites_list')  # 50次/分钟
def favorites_list_api(request):
    """
    获取收藏列表 API

    GET 参数：
        - limit: 返回数量限制（可选）

    返回：
        JSON: {success: true, favorites: [...], count: xxx}
    """
    try:
        limit = request.GET.get('limit', 20)

        try:
            limit = int(limit)
        except ValueError:
            limit = 20

        # 获取收藏列表
        favorites = ArticleFavorite.get_user_favorites(request.user, limit)

        favorites_data = []
        for fav in favorites:
            article = fav.article
            favorites_data.append({
                'id': fav.id,
                'article_id': article.id,
                'article_title': article.title,
                'article_url': article.get_absolute_url(),
                'author': article.author.username,
                'category': article.category.name,
                'pub_time': article.pub_time.strftime('%Y-%m-%d'),
                'favorited_time': fav.creation_time.strftime('%Y-%m-%d %H:%M:%S'),
                'note': fav.note
            })

        return JsonResponse({
            'success': True,
            'favorites': favorites_data,
            'count': ArticleFavorite.get_favorite_count(request.user),
            'total_count': len(favorites_data)
        })

    except Exception as e:
        logger.error(f"获取收藏列表失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'获取失败: {str(e)}'
        }, status=500)


# ==================== 点赞相关 API ====================

@ajax_login_required
@require_http_methods(["POST"])
@user_rate_limit(limit={'requests': 60, 'window': 60}, scope='like')  # 60次/分钟
def like_article_api(request):
    """
    点赞文章 API

    POST 参数：
        - article_id: 文章ID

    返回：
        JSON: {success: true, message: xxx, like_count: xxx}
    """
    try:
        data = json.loads(request.body)
        article_id = data.get('article_id')

        if not article_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 article_id 参数'
            }, status=400)

        # 获取文章
        article = get_object_or_404(Article, id=article_id)

        # 执行点赞
        like = ArticleLike.add_like(request.user, article)

        if like:
            like_count = ArticleLike.get_article_like_count(article)
            return JsonResponse({
                'success': True,
                'message': f'已点赞《{article.title}》',
                'like_count': like_count,
                'is_liked': True
            })
        else:
            return JsonResponse({
                'success': False,
                'message': '已经点赞过该文章'
            }, status=400)

    except Article.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '文章不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"点赞文章失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'点赞失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["POST"])
@user_rate_limit(limit={'requests': 60, 'window': 60}, scope='unlike')  # 60次/分钟
def unlike_article_api(request):
    """
    取消点赞文章 API

    POST 参数：
        - article_id: 文章ID

    返回：
        JSON: {success: true, message: xxx, like_count: xxx}
    """
    try:
        data = json.loads(request.body)
        article_id = data.get('article_id')

        if not article_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 article_id 参数'
            }, status=400)

        # 获取文章
        article = get_object_or_404(Article, id=article_id)

        # 执行取消点赞
        success = ArticleLike.remove_like(request.user, article)

        if success:
            like_count = ArticleLike.get_article_like_count(article)
            return JsonResponse({
                'success': True,
                'message': f'已取消点赞《{article.title}》',
                'like_count': like_count,
                'is_liked': False
            })
        else:
            return JsonResponse({
                'success': False,
                'message': '未点赞该文章'
            }, status=400)

    except Article.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '文章不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"取消点赞失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'取消点赞失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["GET"])
@user_rate_limit(limit={'requests': 100, 'window': 60}, scope='check_like')  # 100次/分钟
def check_like_api(request):
    """
    检查是否已点赞某文章 API

    GET 参数：
        - article_id: 文章ID

    返回：
        JSON: {success: true, is_liked: true/false, like_count: xxx}
    """
    try:
        article_id = request.GET.get('article_id')

        if not article_id:
            return JsonResponse({
                'success': False,
                'message': '缺少 article_id 参数'
            }, status=400)

        article = get_object_or_404(Article, id=article_id)
        is_liked = ArticleLike.is_liked(request.user, article)
        like_count = ArticleLike.get_article_like_count(article)

        return JsonResponse({
            'success': True,
            'is_liked': is_liked,
            'like_count': like_count
        })

    except Article.DoesNotExist:
        return JsonResponse({
            'success': False,
            'message': '文章不存在'
        }, status=404)
    except Exception as e:
        logger.error(f"检查点赞状态失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'检查失败: {str(e)}'
        }, status=500)


@ajax_login_required
@require_http_methods(["GET"])
@user_rate_limit(limit={'requests': 50, 'window': 60}, scope='likes_list')  # 50次/分钟
def likes_list_api(request):
    """
    获取点赞列表 API

    GET 参数：
        - limit: 返回数量限制（可选）

    返回：
        JSON: {success: true, likes: [...], count: xxx}
    """
    try:
        limit = request.GET.get('limit', 20)

        try:
            limit = int(limit)
        except ValueError:
            limit = 20

        # 获取点赞列表
        likes = ArticleLike.get_user_likes(request.user, limit)

        likes_data = []
        for like in likes:
            article = like.article
            likes_data.append({
                'id': like.id,
                'article_id': article.id,
                'article_title': article.title,
                'article_url': article.get_absolute_url(),
                'author': article.author.username,
                'category': article.category.name,
                'pub_time': article.pub_time.strftime('%Y-%m-%d'),
                'liked_time': like.creation_time.strftime('%Y-%m-%d %H:%M:%S')
            })

        return JsonResponse({
            'success': True,
            'likes': likes_data,
            'count': ArticleLike.get_user_like_count(request.user),
            'total_count': len(likes_data)
        })

    except Exception as e:
        logger.error(f"获取点赞列表失败: {e}", exc_info=True)
        return JsonResponse({
            'success': False,
            'message': f'获取失败: {str(e)}'
        }, status=500)
