<reponame>VladimirZubavlenko/ikaf42-app
import logging

from django.core.mail import send_mail
from django.db.models import Max
from django.http import HttpResponse
from minio.error import (ResponseError)
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

import const as CONST
from researchWork.models import ResearchPaper, Feed, ResearchStatus
from researchWork.serializers import ResearchPaperSerializer, NewWorkSerializer, \
    FeedReturnSerializer, FeedReturnSerializer2, WorkUpdate, WorkInfoSerializer, AllStatesSerializer
from user.models import User

# Create your views here.

logger = logging.getLogger(__name__)


class PapersList(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = ResearchPaperSerializer

    def get(self, request):
        logger.warning('IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(
            request.query_params))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            obj = ResearchPaper.objects.filter(author_id=request.user.id, hidden=False).order_by('createdAt')
            response = self.serializer_class(obj, many=True)
            return Response({'type': 'success', 'message': response.data})
        if request.user.role.pk == CONST.TEACHER_ROLE:
            obj = ResearchPaper.objects.filter(advisory_id=request.user.id).order_by('createdAt')
            response = self.serializer_class(obj, many=True)
            return Response({'type': 'success', 'message': response.data})
        if request.user.role.pk == CONST.DEPARTMENT_ROLE:
            obj = ResearchPaper.objects.all().order_by('createdAt')
            response = self.serializer_class(obj, many=True)
            return Response({'type': 'success', 'message': response.data})
        return Response({'type': 'error', 'message': 'Ошибка аутентификации'})


class WorkInfo(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = WorkInfoSerializer

    def get(self, request):
        logger.warning('IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(
            request.query_params))
        workObj = ResearchPaper.objects.get(pk=request.query_params.get('id'))
        if request.user.id == workObj.author_id_id or \
                request.user.id == workObj.advisory_id_id or \
                request.user.id == workObj.consultant_id_id or \
                request.user.role.pk == CONST.DEPARTMENT_ROLE:
            advisoryObj = User.objects.get(pk=workObj.advisory_id_id)
            authorObj = User.objects.get(pk=workObj.author_id_id)
            try:
                consObj = User.objects.get(pk=workObj.consultant_id_id)
            except Exception as err:
                consObj = User()
                consObj.lastName = ''
                consObj.firstName = ''
                consObj.middleName = ''
            response = {'status': workObj.researchStatus_id.pk, 'description': workObj.description, 'theme': workObj.theme,
                        'objective': workObj.objective,
                        'results': workObj.results, 'content': workObj.content, 'sources': workObj.sources,
                        'reportFile': str(workObj.reportFile),
                        'presentationFile': str(workObj.presentationFile),
                        'isNew': workObj.isNew,
                        'review': workObj.review,

                        'authorEmail': authorObj.email,
                        'authorIsActive': authorObj.is_active,
                        'authorLastName': authorObj.lastName,
                        'authorFirstName': authorObj.firstName,
                        'authorMiddleName': authorObj.middleName,
                        'authorPhone': authorObj.phone,
                        'authorGroup': authorObj.studyGroup.name,

                        'advisoryID': advisoryObj.pk,
                        'advisoryEmail': advisoryObj.email,
                        'advisoryIsActive': advisoryObj.is_active,
                        'advisoryLastName': advisoryObj.lastName,
                        'advisoryFirstName': advisoryObj.firstName,
                        'advisoryMiddleName': advisoryObj.middleName,
                        'advisoryPhone': advisoryObj.phone,
                        'advisoryWorkPlace': advisoryObj.workPlace,
                        'advisoryPosition': advisoryObj.position,
                        'advisoryAcademicRank': advisoryObj.academicRank,
                        'advisoryAcademicDegree': advisoryObj.academicDegree,

                        'consultantLastName': consObj.lastName,
                        'consultantFirstName': consObj.firstName,
                        'consultantMiddleName': consObj.middleName
                        }
            return Response({'type': 'success', 'message': response})
        else:
            return Response({'type': 'error', 'message': 'Это не ваша работа!'}, status=status.HTTP_403_FORBIDDEN)
        """
        serializer = self.serializer_class(workObj)
        return Response({'type': 'success', 'message': [serializer.data]})"""


class NewWork(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = NewWorkSerializer

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            json = request.data
            json.update({'author_id': str(request.user.pk)})
            serializer = self.serializer_class(data=json)
            serializer.is_valid(raise_exception=True)
            serializer.save()

            obj = ResearchPaper.objects.filter(author_id=request.user.pk).latest('id')
            objStatus = ResearchStatus.objects.get(id=1)
            Feed.objects.create(researchPaper_id=obj, user=request.user, text='Задание создано')
            obj.researchStatus_id = objStatus
            obj.save()
            print(obj.author_id.email)
            send_mail('Изменение статуса работы',
                      'Статус работы ' + obj.description + ' изменен на ' + objStatus.name + '.',
                      '<EMAIL>',
                      [obj.author_id.email],
                      fail_silently=False)
            return Response(
                {
                    'type': 'success', 'message': 'Задание создано'  # + serializer.data.get('theme', None)
                },
            )
        else:
            return Response({'type': 'error', 'message': 'Вы не студент.'}, status=status.HTTP_403_FORBIDDEN)


class FeedReturn(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = FeedReturnSerializer

    def get(self, request):
        logger.warning('IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(
            request.query_params))
        obj = ResearchPaper.objects.get(pk=request.query_params.get('id'))
        if obj.author_id.pk == request.user.pk or obj.advisory_id.pk == request.user.pk or request.user.role.pk == CONST.DEPARTMENT_ROLE:
            feeds = Feed.objects.filter(researchPaper_id=request.query_params.get('id'))
            serializer = self.serializer_class(feeds, many=True)
            # response = self.checkObjects(serializer, request.user.id, request.user.role.id, len(serializer.data))
            return Response({'type': 'success', 'message': serializer.data})
        else:
            return Response({'type': 'error', 'message': 'Это не ваша работа.'}, status=status.HTTP_403_FORBIDDEN)


class FeedWorkComment(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = FeedReturnSerializer2

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        obj = ResearchPaper.objects.get(pk=request.data['researchPaper_id'])
        if obj.author_id.pk == request.user.pk or obj.advisory_id.pk == request.user.pk or request.user.role.pk == CONST.DEPARTMENT_ROLE:
            json = request.data
            json.update({'user': str(request.user.id)})
            serializer = self.serializer_class(data=json)
            serializer.is_valid(raise_exception=True)
            serializer.save()

            return Response(
                {
                    'type': 'success',
                    'message': 'Создан комментарий ' + serializer.data.get('text', None) + " пользователем - " + str(
                        serializer.data.get('user', None)) + " в " + str(serializer.data.get('date', None))
                }
            )
        else:
            return Response({'type': 'error', 'message': 'Вы не имеете доступ к данной работе'},
                            status=status.HTTP_403_FORBIDDEN)


class DeleteWork(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            obj = ResearchPaper.objects.get(pk=request.data['id'])
            if obj.author_id.pk == request.user.pk and obj.researchStatus_id.pk == 1:
                obj.hidden = True
                obj.save()
                return Response(
                    {
                        'type': 'success', 'message': 'Работа ' + str(request.data['id']) + ' удалена'
                    }
                )
            else:
                return Response({'type': 'error', 'message': 'Невозможно удалить работу'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response({'type': 'error', 'message': 'А вы точно студент?'}, status=status.HTTP_403_FORBIDDEN)


class UpdateWork(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = WorkUpdate

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            serializer = self.serializer_class(data=request.data)
            serializer.is_valid(raise_exception=True)
            if serializer.data['theme'] == '' or serializer.data['objective'] == '' or serializer.data['content'] == '':
                return Response({'type': 'error', 'message': 'Тема, цель и содержание должны быть заполнены!'})
            else:
                obj = ResearchPaper.objects.get(pk=request.data['pk'])
                if obj.researchStatus_id.pk == 1:
                    serializer.update(obj, serializer.validated_data)
                    objStatus = ResearchStatus.objects.get(id=2)
                    obj.researchStatus_id = objStatus
                    obj.isNew = False
                    Feed.objects.create(researchPaper_id=obj, user=request.user, text='Задание отправлено на проверку научному руководителю')
                    obj.save()
                    send_mail('Подтвердите задание на НИР!',
                              'Задание на НИР студента ' + obj.author_id.lastName + ' ' + obj.author_id.firstName +
                              ' на тему: "' + obj.theme + '" ожидает Вашего подтверждения.',
                              '<EMAIL>',
                              [obj.advisory_id.email],
                              fail_silently=False)
                    return Response(
                        {
                            'type': 'success', 'message': 'Задание отправлено на проверку научному руководителю'
                        },
                        status=status.HTTP_200_OK,
                    )
                else:
                    return Response({'type': 'error', 'message': 'Информация о задании не может быть изменена'})
        else:
            return Response({'type': 'error', 'message': 'А вы точно студент?'}, status=status.HTTP_403_FORBIDDEN)


class WorkPush(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        obj = ResearchPaper.objects.get(id=request.data['id'])
        state = obj.researchStatus_id.pk
        user_id = request.user.pk
        role = request.user.role.pk
        if state == 2 and user_id == obj.advisory_id.pk:
            return self.saveState(obj, 3, request, 'Задание одобрено научным руководителем')
        elif state == 3 and role == CONST.DEPARTMENT_ROLE:
            return self.saveState(obj, 4, request, 'Задание одобрено кафедрой. Ожидается загрузка отчета о работе')
        elif state == 5 and user_id == obj.advisory_id.pk:
            return self.saveState(obj, 6, request, 'Отчет одобрен научным руководителем')
        elif state == 6 and role == CONST.DEPARTMENT_ROLE:
            return self.saveState(obj, 7, request, 'Отчет одобрен кафедрой. Студент допущен к защите, ожидается презентация к защите')
        else:
            return Response({'type': 'error', 'message': 'Статус не может быть изменен'})

    def saveState(self, obj, pk_status, request, msg):
        newState = ResearchStatus.objects.get(id=pk_status)
        obj.researchStatus_id = newState
        Feed.objects.create(researchPaper_id=obj, user=request.user, text=msg)
        obj.save()
        self.sendEmail(obj, [obj.author_id.email])
        if newState == 3 or newState == 6:
            self.sendDepEmail(obj, [User.objects.get(role_id=CONST.DEPARTMENT_ROLE)])
        return Response(
            {'type': 'success', 'message': str(msg)})

    def sendEmail(self, obj, receivers):
        send_mail('Изменение статуса работы',
                  'Статус работы ' + obj.theme + ' изменен на ' + obj.researchStatus_id.name + '.',
                  '<EMAIL>',
                  receivers,
                  fail_silently=False)

    def sendDepEmail(self, obj, receivers):
        send_mail('Изменение статуса работы',
                  'Работа "' + obj.theme + '" студента ' + obj.author_id.lastName + ' ' + obj.author_id.firstName + ' пришла на проверку.',
                  '<EMAIL>',
                  receivers,
                  fail_silently=False)


class WorkPop(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        obj = ResearchPaper.objects.get(id=request.data['id'])
        state = obj.researchStatus_id.pk
        user_id = request.user.pk
        role = request.user.role.pk

        if state == 2 and user_id == obj.advisory_id.pk:
            return self.saveState(obj, 1, request, 'Задание отправлено на доработку научным руководителем')
        elif state == 3 and role == CONST.DEPARTMENT_ROLE:
            return self.saveState(obj, 1, request, 'Задание отправлено на доработку кафедрой')
        elif state == 5 and user_id == obj.advisory_id.pk:
            return self.saveState(obj, 4, request, 'Отчет отправлен на доработку научным руководителем')
        elif state == 6 and role == CONST.DEPARTMENT_ROLE:
            return self.saveState(obj, 4, request, 'Отчет отправлен на доработку кафедрой')
        else:
            return Response({'type': 'error', 'message': 'Статус не может быть изменен'})

    def saveState(self, obj, pk_status, request, msg):
        newState = ResearchStatus.objects.get(id=pk_status)
        obj.researchStatus_id = newState
        Feed.objects.create(researchPaper_id=obj, user=request.user, text=msg)
        obj.save()
        self.sendEmail(obj, [obj.author_id.email])
        return Response(
            {'type': 'success', 'message': str(msg)})

    def sendEmail(self, obj, receivers):
        send_mail('Изменение статуса работы',
                  'Статус работы ' + obj.description + ' изменен на ' + obj.researchStatus_id.name + '.',
                  '<EMAIL>',
                  receivers,
                  fail_silently=False)


class StudentWorkReturn(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            obj = ResearchPaper.objects.get(id=request.data['id'])
            if request.user.id == obj.author_id.id:
                state = obj.researchStatus_id.pk
                if state == 2 or state == 3 or state == 4:
                    newState = ResearchStatus.objects.get(id=1)
                    obj.researchStatus_id = newState
                    Feed.objects.create(researchPaper_id=obj, user=request.user, text='Студент вернул задание на доработку')
                    obj.save()
                    return Response({'type': 'success',
                                     'message': 'Работа возвращена на доработку'})
                else:
                    return Response({'type': 'error', 'message': 'Статус не может быть изменен'})
            else:
                return Response({'type': 'error', 'message': 'Статус не может быть изменен'},
                                status=status.HTTP_403_FORBIDDEN)
        else:
            return Response({'type': 'error', 'message': 'Статус не может быть изменен'}, status=status.HTTP_403_FORBIDDEN)


class StudentReportReturn(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            obj = ResearchPaper.objects.get(id=request.data['id'])
            if request.user.id == obj.author_id.id:
                state = obj.researchStatus_id.pk
                if state == 5 or state == 6:
                    newState = ResearchStatus.objects.get(id=4)
                    obj.researchStatus_id = newState
                    Feed.objects.create(researchPaper_id=obj, user=request.user, text='Студент вернул отчет на доработку')
                    obj.save()
                    return Response({'type': 'success',
                                     'message': 'Отчет возвращён на доработку'})
                else:
                    return Response({'type': 'error', 'message': 'Статус не может быть изменен'})
            else:
                return Response({'type': 'error', 'message': 'Статус не может быть изменен'},
                                status=status.HTTP_403_FORBIDDEN)
        else:
            return Response({'type': 'error', 'message': 'Статус не может быть изменен'})


class AllStates(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = AllStatesSerializer

    def get(self, request):
        logger.warning('IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(
            request.query_params))
        obj = ResearchStatus.objects.all()
        response = self.serializer_class(obj, many=True)
        return Response({'type': 'success', 'message': response.data})


class PresUpload(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request):
        if request.user.role.pk == CONST.STUDENT_ROLE:
            paper = ResearchPaper.objects.get(pk=request.data['id'])
            if paper.author_id.pk == request.user.pk and paper.researchStatus_id.pk == 7:
                obj = request.FILES['file']
                paper.presentationFile = obj
                Feed.objects.create(researchPaper_id=paper, user=request.user, text='Презентация к защите загружена студентом')
                paper.save()
                return Response({'type': 'success', 'message': 'Файл ' + str(request.FILES['file']) + 'загружен'})
            else:
                return Response({'type': 'error', 'message': 'Невозможно загрузить файл'})


class ReportUpload(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request):
        if request.user.role.pk == CONST.STUDENT_ROLE:
            paper = ResearchPaper.objects.get(pk=request.data['id'])
            if paper.author_id.pk == request.user.pk:
                obj = request.FILES['file']
                if paper.researchStatus_id.pk == 4:
                    newState = ResearchStatus.objects.get(id=5)
                    paper.researchStatus_id = newState
                    paper.reportFile = obj
                    Feed.objects.create(researchPaper_id=paper, user=request.user, text='Отчет отправлен на проверку научному руководителю')
                    paper.save()
                    return Response({'type': 'success', 'message': 'Отчет отправлен на проверку научному руководителю'})
                else:
                    return Response({'type': 'error', 'message': 'Статус не позволяет загрузить отчет'})
            else:
                return Response({'type': 'error', 'message': 'Невозможно загрузить файл'})


class PresReturn(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        paper = ResearchPaper.objects.get(pk=request.query_params.get('id'))
        # minioClient = CONST.minioClient()
        s3 = CONST.s3()
        if paper.author_id.pk == request.user.pk or paper.advisory_id.pk == request.user.pk or request.user.role.pk == CONST.DEPARTMENT_ROLE:
            path = paper.presentationFile.name.split('/')
            try:
                # data = minioClient.fget_object('presentations', '/' + paper.presentationFile.name, path[1])
                s3.Bucket('presentations').download_file('/' + paper.presentationFile.name, 'tmp/' + path[1])
                with open('tmp/' + path[1], 'rb') as f:
                    file_data = f.read()
            except ResponseError as err:
                print(err)
            response = HttpResponse(file_data, content_type='application/octet-stream')
            response['Content-Disposition'] = 'attachment; filename=' + paper.presentationFile.name
            return response
        else:
            return Response({'type': 'error', 'message': 'У вас нет прав!'}, status=status.HTTP_403_FORBIDDEN)


class ReportReturn(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        paper = ResearchPaper.objects.get(pk=request.query_params.get('id'))
        # minioClient = CONST.minioClient()
        s3 = CONST.s3()
        if paper.author_id.pk == request.user.pk or paper.advisory_id.pk == request.user.pk or request.user.role.pk == CONST.DEPARTMENT_ROLE:
            path = paper.reportFile.name.split('/')
            try:
                # data = minioClient.fget_object('reports', '/' + paper.reportFile.name, path[1])
                s3.Bucket('reports').download_file('/' + paper.reportFile.name, 'tmp/' + path[1])
                with open('tmp/' + path[1], 'rb') as f:
                    file_data = f.read()
            except ResponseError as err:
                print(err)
            response = HttpResponse(file_data, content_type='application/octet-stream')
            response['Content-Disposition'] = 'attachment; filename=' + paper.reportFile.name
            return response
        else:
            return Response({'type': 'error', 'message': 'У вас нет прав!'}, status=status.HTTP_403_FORBIDDEN)


class SetMark(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        if request.user.role.pk == CONST.DEPARTMENT_ROLE:
            obj = ResearchPaper.objects.get(pk=request.data['id'])
            if obj.researchStatus_id.pk == 7:
                obj.mark = request.data['markToSend']
                msg = 'Выставлена оценка ' + str(obj.mark)
                if request.data['markToSend'][0] == 'F':
                    newState = ResearchStatus.objects.get(id=4)
                    msg += '. Ожидается загрузка нового отчета'
                else:
                    newState = ResearchStatus.objects.get(id=8)
                    msg += '. Работа закрыта'
                obj.researchStatus_id = newState
                Feed.objects.create(researchPaper_id=obj, user=request.user, text=msg)
                obj.save()
                return Response({'type': 'success', 'message': 'Выставлена оценка ' + str(obj.mark)})
            else:
                return Response({'type': 'error', 'message': 'Неверный статус работы'})
        else:
            return Response({'type': 'error', 'message': 'Только кафедра выставляет оценки'}, status=status.HTTP_403_FORBIDDEN)


class SetReview(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        obj = ResearchPaper.objects.get(pk=request.data['id'])
        if request.user.pk == obj.advisory_id.pk and obj.researchStatus_id.pk == 5:
            obj.review = request.data['review']
            newState = ResearchStatus.objects.get(pk=6)
            obj.researchStatus_id = newState
            msg = 'Научный руководитель добавил отзыв о работе'
            Feed.objects.create(researchPaper_id=obj, user=request.user, text=msg)
            obj.save()
            return Response({'type': 'success', 'message': msg})
        else:
            return Response({'type': 'error', 'message': 'Только научный руководитель этой работы может оставлять отзыв'},
                            status=status.HTTP_403_FORBIDDEN)
import logging

from django.core.mail import send_mail
from django.db.models import Max
from django.http import HttpResponse
from minio.error import (ResponseError)
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

import const as CONST
from researchWork.models import ResearchPaper, Feed, ResearchStatus
from researchWork.serializers import ResearchPaperSerializer, NewWorkSerializer, \
    FeedReturnSerializer, FeedReturnSerializer2, WorkUpdate, WorkInfoSerializer, AllStatesSerializer
from user.models import User

# Create your views here.

logger = logging.getLogger(__name__)


class PapersList(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = ResearchPaperSerializer

    def get(self, request):
        logger.warning('IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(
            request.query_params))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            obj = ResearchPaper.objects.filter(author_id=request.user.id, hidden=False).order_by('createdAt')
            response = self.serializer_class(obj, many=True)
            return Response({'type': 'success', 'message': response.data})
        if request.user.role.pk == CONST.TEACHER_ROLE:
            obj = ResearchPaper.objects.filter(advisory_id=request.user.id).order_by('createdAt')
            response = self.serializer_class(obj, many=True)
            return Response({'type': 'success', 'message': response.data})
        if request.user.role.pk == CONST.DEPARTMENT_ROLE:
            obj = ResearchPaper.objects.all().order_by('createdAt')
            response = self.serializer_class(obj, many=True)
            return Response({'type': 'success', 'message': response.data})
        return Response({'type': 'error', 'message': 'Ошибка аутентификации'})


class WorkInfo(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = WorkInfoSerializer

    def get(self, request):
        logger.warning('IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(
            request.query_params))
        workObj = ResearchPaper.objects.get(pk=request.query_params.get('id'))
        if request.user.id == workObj.author_id_id or \
                request.user.id == workObj.advisory_id_id or \
                request.user.id == workObj.consultant_id_id or \
                request.user.role.pk == CONST.DEPARTMENT_ROLE:
            advisoryObj = User.objects.get(pk=workObj.advisory_id_id)
            authorObj = User.objects.get(pk=workObj.author_id_id)
            try:
                consObj = User.objects.get(pk=workObj.consultant_id_id)
            except Exception as err:
                consObj = User()
                consObj.lastName = ''
                consObj.firstName = ''
                consObj.middleName = ''
            response = {'status': workObj.researchStatus_id.pk, 'description': workObj.description, 'theme': workObj.theme,
                        'objective': workObj.objective,
                        'results': workObj.results, 'content': workObj.content, 'sources': workObj.sources,
                        'reportFile': str(workObj.reportFile),
                        'presentationFile': str(workObj.presentationFile),
                        'isNew': workObj.isNew,
                        'review': workObj.review,

                        'authorEmail': authorObj.email,
                        'authorIsActive': authorObj.is_active,
                        'authorLastName': authorObj.lastName,
                        'authorFirstName': authorObj.firstName,
                        'authorMiddleName': authorObj.middleName,
                        'authorPhone': authorObj.phone,
                        'authorGroup': authorObj.studyGroup.name,

                        'advisoryID': advisoryObj.pk,
                        'advisoryEmail': advisoryObj.email,
                        'advisoryIsActive': advisoryObj.is_active,
                        'advisoryLastName': advisoryObj.lastName,
                        'advisoryFirstName': advisoryObj.firstName,
                        'advisoryMiddleName': advisoryObj.middleName,
                        'advisoryPhone': advisoryObj.phone,
                        'advisoryWorkPlace': advisoryObj.workPlace,
                        'advisoryPosition': advisoryObj.position,
                        'advisoryAcademicRank': advisoryObj.academicRank,
                        'advisoryAcademicDegree': advisoryObj.academicDegree,

                        'consultantLastName': consObj.lastName,
                        'consultantFirstName': consObj.firstName,
                        'consultantMiddleName': consObj.middleName
                        }
            return Response({'type': 'success', 'message': response})
        else:
            return Response({'type': 'error', 'message': 'Это не ваша работа!'}, status=status.HTTP_403_FORBIDDEN)
        """
        serializer = self.serializer_class(workObj)
        return Response({'type': 'success', 'message': [serializer.data]})"""


class NewWork(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = NewWorkSerializer

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            json = request.data
            json.update({'author_id': str(request.user.pk)})
            serializer = self.serializer_class(data=json)
            serializer.is_valid(raise_exception=True)
            serializer.save()

            obj = ResearchPaper.objects.filter(author_id=request.user.pk).latest('id')
            objStatus = ResearchStatus.objects.get(id=1)
            Feed.objects.create(researchPaper_id=obj, user=request.user, text='Задание создано')
            obj.researchStatus_id = objStatus
            obj.save()
            print(obj.author_id.email)
            send_mail('Изменение статуса работы',
                      'Статус работы ' + obj.description + ' изменен на ' + objStatus.name + '.',
                      '<EMAIL>',
                      [obj.author_id.email],
                      fail_silently=False)
            return Response(
                {
                    'type': 'success', 'message': 'Задание создано'  # + serializer.data.get('theme', None)
                },
            )
        else:
            return Response({'type': 'error', 'message': 'Вы не студент.'}, status=status.HTTP_403_FORBIDDEN)


class FeedReturn(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = FeedReturnSerializer

    def get(self, request):
        logger.warning('IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(
            request.query_params))
        obj = ResearchPaper.objects.get(pk=request.query_params.get('id'))
        if obj.author_id.pk == request.user.pk or obj.advisory_id.pk == request.user.pk or request.user.role.pk == CONST.DEPARTMENT_ROLE:
            feeds = Feed.objects.filter(researchPaper_id=request.query_params.get('id'))
            serializer = self.serializer_class(feeds, many=True)
            # response = self.checkObjects(serializer, request.user.id, request.user.role.id, len(serializer.data))
            return Response({'type': 'success', 'message': serializer.data})
        else:
            return Response({'type': 'error', 'message': 'Это не ваша работа.'}, status=status.HTTP_403_FORBIDDEN)


class FeedWorkComment(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = FeedReturnSerializer2

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        obj = ResearchPaper.objects.get(pk=request.data['researchPaper_id'])
        if obj.author_id.pk == request.user.pk or obj.advisory_id.pk == request.user.pk or request.user.role.pk == CONST.DEPARTMENT_ROLE:
            json = request.data
            json.update({'user': str(request.user.id)})
            serializer = self.serializer_class(data=json)
            serializer.is_valid(raise_exception=True)
            serializer.save()

            return Response(
                {
                    'type': 'success',
                    'message': 'Создан комментарий ' + serializer.data.get('text', None) + " пользователем - " + str(
                        serializer.data.get('user', None)) + " в " + str(serializer.data.get('date', None))
                }
            )
        else:
            return Response({'type': 'error', 'message': 'Вы не имеете доступ к данной работе'},
                            status=status.HTTP_403_FORBIDDEN)


class DeleteWork(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            obj = ResearchPaper.objects.get(pk=request.data['id'])
            if obj.author_id.pk == request.user.pk and obj.researchStatus_id.pk == 1:
                obj.hidden = True
                obj.save()
                return Response(
                    {
                        'type': 'success', 'message': 'Работа ' + str(request.data['id']) + ' удалена'
                    }
                )
            else:
                return Response({'type': 'error', 'message': 'Невозможно удалить работу'}, status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response({'type': 'error', 'message': 'А вы точно студент?'}, status=status.HTTP_403_FORBIDDEN)


class UpdateWork(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = WorkUpdate

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            serializer = self.serializer_class(data=request.data)
            serializer.is_valid(raise_exception=True)
            if serializer.data['theme'] == '' or serializer.data['objective'] == '' or serializer.data['content'] == '':
                return Response({'type': 'error', 'message': 'Тема, цель и содержание должны быть заполнены!'})
            else:
                obj = ResearchPaper.objects.get(pk=request.data['pk'])
                if obj.researchStatus_id.pk == 1:
                    serializer.update(obj, serializer.validated_data)
                    objStatus = ResearchStatus.objects.get(id=2)
                    obj.researchStatus_id = objStatus
                    obj.isNew = False
                    Feed.objects.create(researchPaper_id=obj, user=request.user, text='Задание отправлено на проверку научному руководителю')
                    obj.save()
                    send_mail('Подтвердите задание на НИР!',
                              'Задание на НИР студента ' + obj.author_id.lastName + ' ' + obj.author_id.firstName +
                              ' на тему: "' + obj.theme + '" ожидает Вашего подтверждения.',
                              '<EMAIL>',
                              [obj.advisory_id.email],
                              fail_silently=False)
                    return Response(
                        {
                            'type': 'success', 'message': 'Задание отправлено на проверку научному руководителю'
                        },
                        status=status.HTTP_200_OK,
                    )
                else:
                    return Response({'type': 'error', 'message': 'Информация о задании не может быть изменена'})
        else:
            return Response({'type': 'error', 'message': 'А вы точно студент?'}, status=status.HTTP_403_FORBIDDEN)


class WorkPush(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        obj = ResearchPaper.objects.get(id=request.data['id'])
        state = obj.researchStatus_id.pk
        user_id = request.user.pk
        role = request.user.role.pk
        if state == 2 and user_id == obj.advisory_id.pk:
            return self.saveState(obj, 3, request, 'Задание одобрено научным руководителем')
        elif state == 3 and role == CONST.DEPARTMENT_ROLE:
            return self.saveState(obj, 4, request, 'Задание одобрено кафедрой. Ожидается загрузка отчета о работе')
        elif state == 5 and user_id == obj.advisory_id.pk:
            return self.saveState(obj, 6, request, 'Отчет одобрен научным руководителем')
        elif state == 6 and role == CONST.DEPARTMENT_ROLE:
            return self.saveState(obj, 7, request, 'Отчет одобрен кафедрой. Студент допущен к защите, ожидается презентация к защите')
        else:
            return Response({'type': 'error', 'message': 'Статус не может быть изменен'})

    def saveState(self, obj, pk_status, request, msg):
        newState = ResearchStatus.objects.get(id=pk_status)
        obj.researchStatus_id = newState
        Feed.objects.create(researchPaper_id=obj, user=request.user, text=msg)
        obj.save()
        self.sendEmail(obj, [obj.author_id.email])
        if newState == 3 or newState == 6:
            self.sendDepEmail(obj, [User.objects.get(role_id=CONST.DEPARTMENT_ROLE)])
        return Response(
            {'type': 'success', 'message': str(msg)})

    def sendEmail(self, obj, receivers):
        send_mail('Изменение статуса работы',
                  'Статус работы ' + obj.theme + ' изменен на ' + obj.researchStatus_id.name + '.',
                  '<EMAIL>',
                  receivers,
                  fail_silently=False)

    def sendDepEmail(self, obj, receivers):
        send_mail('Изменение статуса работы',
                  'Работа "' + obj.theme + '" студента ' + obj.author_id.lastName + ' ' + obj.author_id.firstName + ' пришла на проверку.',
                  '<EMAIL>',
                  receivers,
                  fail_silently=False)


class WorkPop(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        obj = ResearchPaper.objects.get(id=request.data['id'])
        state = obj.researchStatus_id.pk
        user_id = request.user.pk
        role = request.user.role.pk

        if state == 2 and user_id == obj.advisory_id.pk:
            return self.saveState(obj, 1, request, 'Задание отправлено на доработку научным руководителем')
        elif state == 3 and role == CONST.DEPARTMENT_ROLE:
            return self.saveState(obj, 1, request, 'Задание отправлено на доработку кафедрой')
        elif state == 5 and user_id == obj.advisory_id.pk:
            return self.saveState(obj, 4, request, 'Отчет отправлен на доработку научным руководителем')
        elif state == 6 and role == CONST.DEPARTMENT_ROLE:
            return self.saveState(obj, 4, request, 'Отчет отправлен на доработку кафедрой')
        else:
            return Response({'type': 'error', 'message': 'Статус не может быть изменен'})

    def saveState(self, obj, pk_status, request, msg):
        newState = ResearchStatus.objects.get(id=pk_status)
        obj.researchStatus_id = newState
        Feed.objects.create(researchPaper_id=obj, user=request.user, text=msg)
        obj.save()
        self.sendEmail(obj, [obj.author_id.email])
        return Response(
            {'type': 'success', 'message': str(msg)})

    def sendEmail(self, obj, receivers):
        send_mail('Изменение статуса работы',
                  'Статус работы ' + obj.description + ' изменен на ' + obj.researchStatus_id.name + '.',
                  '<EMAIL>',
                  receivers,
                  fail_silently=False)


class StudentWorkReturn(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            obj = ResearchPaper.objects.get(id=request.data['id'])
            if request.user.id == obj.author_id.id:
                state = obj.researchStatus_id.pk
                if state == 2 or state == 3 or state == 4:
                    newState = ResearchStatus.objects.get(id=1)
                    obj.researchStatus_id = newState
                    Feed.objects.create(researchPaper_id=obj, user=request.user, text='Студент вернул задание на доработку')
                    obj.save()
                    return Response({'type': 'success',
                                     'message': 'Работа возвращена на доработку'})
                else:
                    return Response({'type': 'error', 'message': 'Статус не может быть изменен'})
            else:
                return Response({'type': 'error', 'message': 'Статус не может быть изменен'},
                                status=status.HTTP_403_FORBIDDEN)
        else:
            return Response({'type': 'error', 'message': 'Статус не может быть изменен'}, status=status.HTTP_403_FORBIDDEN)


class StudentReportReturn(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        logger.warning(
            'IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(request.data))
        if request.user.role.pk == CONST.STUDENT_ROLE:
            obj = ResearchPaper.objects.get(id=request.data['id'])
            if request.user.id == obj.author_id.id:
                state = obj.researchStatus_id.pk
                if state == 5 or state == 6:
                    newState = ResearchStatus.objects.get(id=4)
                    obj.researchStatus_id = newState
                    Feed.objects.create(researchPaper_id=obj, user=request.user, text='Студент вернул отчет на доработку')
                    obj.save()
                    return Response({'type': 'success',
                                     'message': 'Отчет возвращён на доработку'})
                else:
                    return Response({'type': 'error', 'message': 'Статус не может быть изменен'})
            else:
                return Response({'type': 'error', 'message': 'Статус не может быть изменен'},
                                status=status.HTTP_403_FORBIDDEN)
        else:
            return Response({'type': 'error', 'message': 'Статус не может быть изменен'})


class AllStates(APIView):
    permission_classes = [IsAuthenticated]
    serializer_class = AllStatesSerializer

    def get(self, request):
        logger.warning('IP: ' + CONST.get_client_ip(request) + '  USER:' + str(request.user) + '  REQUEST:' + str(
            request.query_params))
        obj = ResearchStatus.objects.all()
        response = self.serializer_class(obj, many=True)
        return Response({'type': 'success', 'message': response.data})


class PresUpload(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request):
        if request.user.role.pk == CONST.STUDENT_ROLE:
            paper = ResearchPaper.objects.get(pk=request.data['id'])
            if paper.author_id.pk == request.user.pk and paper.researchStatus_id.pk == 7:
                obj = request.FILES['file']
                paper.presentationFile = obj
                Feed.objects.create(researchPaper_id=paper, user=request.user, text='Презентация к защите загружена студентом')
                paper.save()
                return Response({'type': 'success', 'message': 'Файл ' + str(request.FILES['file']) + 'загружен'})
            else:
                return Response({'type': 'error', 'message': 'Невозможно загрузить файл'})


class ReportUpload(APIView):
    permission_classes = [IsAuthenticated]

    def put(self, request):
        if request.user.role.pk == CONST.STUDENT_ROLE:
            paper = ResearchPaper.objects.get(pk=request.data['id'])
            if paper.author_id.pk == request.user.pk:
                obj = request.FILES['file']
                if paper.researchStatus_id.pk == 4:
                    newState = ResearchStatus.objects.get(id=5)
                    paper.researchStatus_id = newState
                    paper.reportFile = obj
                    Feed.objects.create(researchPaper_id=paper, user=request.user, text='Отчет отправлен на проверку научному руководителю')
                    paper.save()
                    return Response({'type': 'success', 'message': 'Отчет отправлен на проверку научному руководителю'})
                else:
                    return Response({'type': 'error', 'message': 'Статус не позволяет загрузить отчет'})
            else:
                return Response({'type': 'error', 'message': 'Невозможно загрузить файл'})


class PresReturn(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        paper = ResearchPaper.objects.get(pk=request.query_params.get('id'))
        # minioClient = CONST.minioClient()
        s3 = CONST.s3()
        if paper.author_id.pk == request.user.pk or paper.advisory_id.pk == request.user.pk or request.user.role.pk == CONST.DEPARTMENT_ROLE:
            path = paper.presentationFile.name.split('/')
            try:
                # data = minioClient.fget_object('presentations', '/' + paper.presentationFile.name, path[1])
                s3.Bucket('presentations').download_file('/' + paper.presentationFile.name, 'tmp/' + path[1])
                with open('tmp/' + path[1], 'rb') as f:
                    file_data = f.read()
            except ResponseError as err:
                print(err)
            response = HttpResponse(file_data, content_type='application/octet-stream')
            response['Content-Disposition'] = 'attachment; filename=' + paper.presentationFile.name
            return response
        else:
            return Response({'type': 'error', 'message': 'У вас нет прав!'}, status=status.HTTP_403_FORBIDDEN)


class ReportReturn(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        paper = ResearchPaper.objects.get(pk=request.query_params.get('id'))
        # minioClient = CONST.minioClient()
        s3 = CONST.s3()
        if paper.author_id.pk == request.user.pk or paper.advisory_id.pk == request.user.pk or request.user.role.pk == CONST.DEPARTMENT_ROLE:
            path = paper.reportFile.name.split('/')
            try:
                # data = minioClient.fget_object('reports', '/' + paper.reportFile.name, path[1])
                s3.Bucket('reports').download_file('/' + paper.reportFile.name, 'tmp/' + path[1])
                with open('tmp/' + path[1], 'rb') as f:
                    file_data = f.read()
            except ResponseError as err:
                print(err)
            response = HttpResponse(file_data, content_type='application/octet-stream')
            response['Content-Disposition'] = 'attachment; filename=' + paper.reportFile.name
            return response
        else:
            return Response({'type': 'error', 'message': 'У вас нет прав!'}, status=status.HTTP_403_FORBIDDEN)


class SetMark(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        if request.user.role.pk == CONST.DEPARTMENT_ROLE:
            obj = ResearchPaper.objects.get(pk=request.data['id'])
            if obj.researchStatus_id.pk == 7:
                obj.mark = request.data['markToSend']
                msg = 'Выставлена оценка ' + str(obj.mark)
                if request.data['markToSend'][0] == 'F':
                    newState = ResearchStatus.objects.get(id=4)
                    msg += '. Ожидается загрузка нового отчета'
                else:
                    newState = ResearchStatus.objects.get(id=8)
                    msg += '. Работа закрыта'
                obj.researchStatus_id = newState
                Feed.objects.create(researchPaper_id=obj, user=request.user, text=msg)
                obj.save()
                return Response({'type': 'success', 'message': 'Выставлена оценка ' + str(obj.mark)})
            else:
                return Response({'type': 'error', 'message': 'Неверный статус работы'})
        else:
            return Response({'type': 'error', 'message': 'Только кафедра выставляет оценки'}, status=status.HTTP_403_FORBIDDEN)


class SetReview(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        obj = ResearchPaper.objects.get(pk=request.data['id'])
        if request.user.pk == obj.advisory_id.pk and obj.researchStatus_id.pk == 5:
            obj.review = request.data['review']
            newState = ResearchStatus.objects.get(pk=6)
            obj.researchStatus_id = newState
            msg = 'Научный руководитель добавил отзыв о работе'
            Feed.objects.create(researchPaper_id=obj, user=request.user, text=msg)
            obj.save()
            return Response({'type': 'success', 'message': msg})
        else:
            return Response({'type': 'error', 'message': 'Только научный руководитель этой работы может оставлять отзыв'},
                            status=status.HTTP_403_FORBIDDEN)
# Create your views here. serializer = self.serializer_class(workObj)         return Response({'type': 'success', 'message': [serializer.data]}) # + serializer.data.get('theme', None) # response = self.checkObjects(serializer, request.user.id, request.user.role.id, len(serializer.data)) # minioClient = CONST.minioClient() # data = minioClient.fget_object('presentations', '/' + paper.presentationFile.name, path[1]) # minioClient = CONST.minioClient() # data = minioClient.fget_object('reports', '/' + paper.reportFile.name, path[1])