from django.test import override_settings
from rest_framework.test import APITestCase

from vbv_lernwelt.core.create_default_users import create_default_users
from vbv_lernwelt.core.models import User
from vbv_lernwelt.course.consts import COURSE_TEST_ID
from vbv_lernwelt.course.creators.test_course import create_test_course
from vbv_lernwelt.course.models import CircleDocument, CourseSession, CourseSessionUser
from vbv_lernwelt.files.models import UploadFile
from vbv_lernwelt.learnpath.models import Circle, LearningSequence


class DocumentUploadApiTestCase(APITestCase):
    def setUp(self) -> None:
        create_default_users()
        create_test_course()

        self.user = User.objects.get(username="student")
        self.expert = User.objects.get(
            username="patrizia.huggel@eiger-versicherungen.ch"
        )

        self.course_session = CourseSession.objects.create(
            course_id=COURSE_TEST_ID,
            title="Test Lehrgang Session",
        )

        csu = CourseSessionUser.objects.create(
            course_session=self.course_session,
            user=User.objects.get(username="patrizia.huggel@eiger-versicherungen.ch"),
            role=CourseSessionUser.Role.EXPERT,
        )
        csu.expert.add(Circle.objects.get(slug="test-lehrgang-lp-circle-fahrzeug"))

        _csu = CourseSessionUser.objects.create(
            course_session=self.course_session,
            user=self.user,
            role=CourseSessionUser.Role.MEMBER,
        )

        self.test_data = {
            "file_name": "test.pdf",
            "file_type": "application/pdf",
            "name": "Test",
            "course_session": self.course_session.id,
        }

        self.client.login(
            username="patrizia.huggel@eiger-versicherungen.ch", password="myvbv1234"
        )

    @override_settings(FILE_UPLOAD_STORAGE="s3")
    def test_can_start_upload(self):
        ls = LearningSequence.objects.get(
            slug="test-lehrgang-lp-circle-fahrzeug-ls-vorbereitung"
        )

        self.test_data["learning_sequence"] = ls.id
        response = self.client.post(f"/api/core/document/start/", self.test_data)

        self.assertEqual(response.status_code, 200)
        self.assertNotEqual(response.data["url"], "")

        self.assertTrue(response.data["url"].startswith("https://"))
        self.assertEqual(
            response.data["fields"]["Content-Type"], self.test_data["file_type"]
        )

        self.assertEqual(
            response.data["fields"]["Content-Disposition"],
            f"attachment; filename={self.test_data['file_name']}",
        )

        file_id = response.data["file_id"]
        file = UploadFile.objects.get(id=file_id)

        self.assertIsNone(file.upload_finished_at)

    def test_cannot_start_upload_in_other_circle(self):
        ls = LearningSequence.objects.get(
            slug="test-lehrgang-lp-circle-reisen-ls-analyse"
        )
        self.test_data["learning_sequence"] = ls.id
        response = self.client.post(f"/api/core/document/start/", self.test_data)

        self.assertEqual(response.status_code, 403)

    def test_student_cannot_start_uploads(self):
        self.client.login(username="student", password="test")
        ls = LearningSequence.objects.get(
            slug="test-lehrgang-lp-circle-fahrzeug-ls-vorbereitung"
        )
        self.test_data["learning_sequence"] = ls.id
        response = self.client.post(f"/api/core/document/start/", self.test_data)

        self.assertEqual(response.status_code, 403)

    def test_expert_can_finish_own_upload(self):
        ls = LearningSequence.objects.get(
            slug="test-lehrgang-lp-circle-fahrzeug-ls-vorbereitung"
        )
        self.test_data["learning_sequence"] = ls.id
        response = self.client.post(f"/api/core/document/start/", self.test_data)

        self.assertEqual(response.status_code, 200)
        file_id = response.data["file_id"]

        response = self.client.post(
            f"/api/core/file/finish/",
            {
                "file_id": file_id,
            },
        )

        self.assertEqual(response.status_code, 200)
        self.assertNotEqual(response.data["url"], "")

        file = UploadFile.objects.get(id=file_id)
        self.assertIsNotNone(file.upload_finished_at)

    def test_can_only_finish_own_files(self):
        file = UploadFile(
            original_file_name="test.pdf",
            file_name="test.pdf",
            file_type="application/pdf",
            uploaded_by=self.user,
            file=None,
        )
        file.full_clean()
        file.save()

        response = self.client.post(f"/api/core/file/finish/", {"file_id": file.id})

        self.assertEqual(response.status_code, 403)

    def test_can_delete_document(self):
        ls = LearningSequence.objects.get(
            slug="test-lehrgang-lp-circle-fahrzeug-ls-vorbereitung"
        )
        file = UploadFile(
            original_file_name="test.pdf",
            file_name="test.pdf",
            file_type="application/pdf",
            uploaded_by=self.expert,
            file=None,
        )
        file.full_clean()
        file.save()

        document = CircleDocument.objects.create(
            file=file,
            name="Test",
            learning_sequence=ls,
            course_session=self.course_session,
        )

        response = self.client.delete(f"/api/core/document/{document.id}/")
        self.assertEqual(response.status_code, 200)

        try:
            CircleDocument.objects.get(id=document.id)
            self.fail("Document was not deleted")
        except CircleDocument.DoesNotExist:
            pass

        file = UploadFile.objects.get(id=file.id)
        self.assertIsNone(file.upload_finished_at)

    def test_student_cannot_delete_document(self):
        self.client.login(username="student", password="test")
        ls = LearningSequence.objects.get(
            slug="test-lehrgang-lp-circle-fahrzeug-ls-vorbereitung"
        )
        file = UploadFile(
            original_file_name="test.pdf",
            file_name="test.pdf",
            file_type="application/pdf",
            uploaded_by=self.expert,
            file=None,
        )
        file.full_clean()
        file.save()

        document = CircleDocument.objects.create(
            file=file,
            name="Test",
            learning_sequence=ls,
            course_session=self.course_session,
        )

        response = self.client.delete(f"/api/core/document/{document.id}/")
        self.assertEqual(response.status_code, 403)


# expert cannot upload in other course
# expert cannot delete other upload
# exper cannot change course
