from flask import request
from flask_jwt_extended import jwt_required

from app.http.requests.v1.comment_request import (
    CreateCommentRequest,
    UpdateCommentRequest,
    DeleteCommentRequest,
    UpdateCommentLikeStatusRequest,
    GetFeedsRequest,
    GetNoticesRequest,
    GetPushFeedRequest,
)
from app.http.requests.v1.post_request import (
    CreatePostRequest,
    UpdatePostRequest,
    DeletePostRequest,
    GetPostRequest,
    UpdatePostLikeStatusRequest,
)
from app.http.responses.presenters.v1.community_presenter import (
    GetPostCategoryPresenter,
    CreatePostPresenter,
    UpdatePostPresenter,
    DeletePostPresenter,
    GetPostPresenter,
    UpdatePostLikeStatusPresenter,
    CreateCommentPresenter,
    UpdateCommentPresenter,
    DeleteCommentPresenter,
    UpdateCommentLikeStatusPresenter,
    GetFeedsPresenter,
    GetNoticesPresenter,
    GetPushFeedPresenter,
)
from app.http.view import api, auth_required
from app.http.view.authentication import current_user
from core.domains.community.use_case.v1.community_use_case import (
    GetPostCategoryUseCase,
    CreatePostUseCase,
    UpdatePostUseCase,
    DeletePostUseCase,
    GetPostUseCase,
    UpdatePostLikeStatusUseCase,
    CreateCommentUseCase,
    UpdateCommentUseCase,
    DeleteCommentUseCase,
    UpdateCommentLikeStatusUseCase,
    GetFeedsUseCase,
    GetNoticesUseCase,
    GetPushFeedUseCase,
)


@api.route("/v1/communities/category", methods=["GET"])
@jwt_required
@auth_required
def get_post_category_view():
    return GetPostCategoryPresenter().transform(GetPostCategoryUseCase().execute())


@api.route("/v1/communities/post", methods=["POST"])
@jwt_required
@auth_required
def create_post():
    dto = CreatePostRequest(
        **request.form.to_dict(),
        files=request.files.getlist("files"),
        user_id=current_user.id
    ).validate_request_and_make_dto()

    return CreatePostPresenter().transform(CreatePostUseCase().execute(dto=dto))


@api.route("/v1/communities/post/<int:post_id>", methods=["PATCH"])
@jwt_required
@auth_required
def update_post(post_id):
    dto = UpdatePostRequest(
        post_category_id=request.form.get("post_category_id"),
        body=request.form.get("body"),
        files=request.files.getlist("files"),
        delete_files=request.form.getlist("delete_files"),
        post_id=post_id,
        user_id=current_user.id,
    ).validate_request_and_make_dto()

    return UpdatePostPresenter().transform(UpdatePostUseCase().execute(dto=dto))


@api.route("/v1/communities/post/<int:post_id>", methods=["DELETE"])
@jwt_required
@auth_required
def delete_post(post_id):
    dto = DeletePostRequest(
        post_id=post_id, user_id=current_user.id,
    ).validate_request_and_make_dto()

    return DeletePostPresenter().transform(DeletePostUseCase().execute(dto=dto))


@api.route("/v1/communities/post", methods=["GET"])
@jwt_required
@auth_required
def get_post():
    dto = GetPostRequest(
        post_id=request.args.get("post_id"), user_id=current_user.id,
    ).validate_request_and_make_dto()

    return GetPostPresenter().transform(GetPostUseCase().execute(dto=dto))


@api.route("/v1/communities/post/<int:post_id>/like", methods=["POST"])
@jwt_required
@auth_required
def update_post_like_status(post_id):
    dto = UpdatePostLikeStatusRequest(
        post_id=post_id, user_id=current_user.id, **request.get_json()
    ).validate_request_and_make_dto()

    return UpdatePostLikeStatusPresenter().transform(
        UpdatePostLikeStatusUseCase().execute(dto=dto)
    )


@api.route("/v1/communities/comment", methods=["POST"])
@jwt_required
@auth_required
def create_comment():
    dto = CreateCommentRequest(
        **request.get_json(), user_id=current_user.id
    ).validate_request_and_make_dto()

    return CreateCommentPresenter().transform(CreateCommentUseCase().execute(dto=dto))


@api.route("/v1/communities/comment/<int:comment_id>", methods=["PATCH"])
@jwt_required
@auth_required
def update_comment(comment_id):
    dto = UpdateCommentRequest(
        **request.get_json(), user_id=current_user.id, comment_id=comment_id
    ).validate_request_and_make_dto()

    return UpdateCommentPresenter().transform(UpdateCommentUseCase().execute(dto=dto))


@api.route("/v1/communities/comment/<int:comment_id>", methods=["DELETE"])
@jwt_required
@auth_required
def delete_comment(comment_id):
    dto = DeleteCommentRequest(
        user_id=current_user.id, comment_id=comment_id
    ).validate_request_and_make_dto()

    return DeleteCommentPresenter().transform(DeleteCommentUseCase().execute(dto=dto))


@api.route("/v1/communities/comment/<int:comment_id>/like", methods=["POST"])
@jwt_required
@auth_required
def update_comment_like_status(comment_id):
    dto = UpdateCommentLikeStatusRequest(
        comment_id=comment_id, user_id=current_user.id, **request.get_json()
    ).validate_request_and_make_dto()

    return UpdateCommentLikeStatusPresenter().transform(
        UpdateCommentLikeStatusUseCase().execute(dto=dto)
    )


@api.route("/v1/communities/feed", methods=["GET"])
@jwt_required
@auth_required
def get_feeds():
    dto = GetFeedsRequest(
        user_id=current_user.id,
        post_category_id=request.args.get("post_category_id"),
        previous_id=request.args.get("previous_id"),
    ).validate_request_and_make_dto()

    return GetFeedsPresenter().transform(GetFeedsUseCase().execute(dto=dto))


@api.route("/v1/communities/notice", methods=["GET"])
@jwt_required
@auth_required
def get_notices():
    dto = GetNoticesRequest(
        user_id=current_user.id, previous_id=request.args.get("previous_id"),
    ).validate_request_and_make_dto()

    return GetNoticesPresenter().transform(GetNoticesUseCase().execute(dto=dto))


@api.route("/v1/communities/push", methods=["GET"])
@jwt_required
@auth_required
def get_push_feed():
    dto = GetPushFeedRequest(
        user_id=current_user.id,
        post_id=request.args.get("post_id"),
        comment_id=request.args.get("comment_id"),
        topic=request.args.get("topic"),
    ).validate_request_and_make_dto()

    return GetPushFeedPresenter().transform(GetPushFeedUseCase().execute(dto=dto))
