from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from rest_framework import status
from rest_framework.test import APITestCase
from rest_framework_simplejwt.tokens import RefreshToken
from .models import MasterSkill

User = get_user_model()


class MasterSkillWorkflowTests(APITestCase):
    def setUp(self):
        # Create user
        self.user = User.objects.create_user(
            email="testuser@ta-ats.local",
            password="testpassword",
            first_name="Test",
            last_name="User"
        )
        # Assign permissions (or make admin to simplify, since permissions map checks for view/add/change)
        self.user.role = "ADMIN"
        self.user.is_superuser = True
        self.user.is_staff = True
        self.user.save()

        # Generate JWT and apply to client
        token = RefreshToken.for_user(self.user)
        self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token.access_token}")

    def test_download_template(self):
        url = reverse("master-skill-download-template")
        response = self.client.get(url)
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response["Content-Type"], "text/csv")
        self.assertIn("attachment; filename=\"master-skills.csv\"", response["Content-Disposition"])
        content = response.content.decode("utf-8")
        self.assertIn("Skill Name", content)

    def test_import_csv_success(self):
        csv_data = "Skill Name\nJava\nPython\nReact\n"
        csv_file = SimpleUploadedFile("master-skills.csv", csv_data.encode("utf-8"), content_type="text/csv")

        url = reverse("master-skill-import-csv")
        response = self.client.post(url, {"file": csv_file}, format="multipart")

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertTrue(response.data["success"])
        self.assertEqual(response.data["data"]["imported"], 3)
        self.assertEqual(response.data["data"]["skipped"], 0)
        self.assertEqual(len(response.data["data"]["errors"]), 0)

        # Check in DB
        skills = MasterSkill.objects.all()
        self.assertEqual(skills.count(), 3)
        for skill in skills:
            self.assertEqual(skill.status, "DRAFT")

    def test_import_csv_validation_and_skips(self):
        # Pre-create "Java" in DB
        MasterSkill.objects.create(
            name="Java",
            status="ACTIVE",
            created_by=self.user,
            updated_by=self.user
        )

        # CSV contains:
        # Row 2: "Java" -> existing in DB
        # Row 3: "" (empty skill name) -> invalid
        # Row 4: "Python" -> valid
        # Row 5: "python" -> duplicate in CSV (case-insensitive)
        # Row 6: "  " (spaces) -> invalid/empty
        # Row 7: "React" -> valid
        # Row 8: completely empty row -> should be ignored, not counted as error
        csv_data = (
            "Skill Name\n"
            "Java\n"
            "\n"
            "Python\n"
            "python\n"
            "  \n"
            "React\n"
            ",\n"
        )
        csv_file = SimpleUploadedFile("master-skills.csv", csv_data.encode("utf-8"), content_type="text/csv")

        url = reverse("master-skill-import-csv")
        response = self.client.post(url, {"file": csv_file}, format="multipart")

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data["data"]["imported"], 2)  # Python, React
        self.assertEqual(response.data["data"]["skipped"], 2)   # Row 2 (exists), Row 5 (duplicate in CSV)
        # Row 3, 6, 8 are completely empty so they are ignored and do not raise errors.
        
        errors = response.data["data"]["errors"]
        self.assertIn("Row 2 : Skill already exists", errors)
        self.assertIn("Row 5 : Duplicate skill in CSV", errors)

        # Verify only Python and React were inserted
        inserted = MasterSkill.objects.filter(status="DRAFT").order_by("name")
        self.assertEqual(inserted.count(), 2)
        self.assertEqual(inserted[0].name, "Python")
        self.assertEqual(inserted[1].name, "React")

    def test_import_csv_invalid_file_type(self):
        file = SimpleUploadedFile("test.txt", b"some text", content_type="text/plain")
        url = reverse("master-skill-import-csv")
        response = self.client.post(url, {"file": file}, format="multipart")
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertFalse(response.data["success"])

    def test_bulk_approve_success(self):
        # Create draft skills
        skill1 = MasterSkill.objects.create(name="S1", status="DRAFT", created_by=self.user, updated_by=self.user)
        skill2 = MasterSkill.objects.create(name="S2", status="DRAFT", created_by=self.user, updated_by=self.user)
        skill3 = MasterSkill.objects.create(name="S3", status="ACTIVE", created_by=self.user, updated_by=self.user) # already active

        url = reverse("master-skill-bulk-approve")
        response = self.client.patch(url, {"skillIds": [skill1.id, skill2.id, skill3.id]}, format="json")

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data["data"]["updated_count"], 2) # only s1 and s2 should be updated from DRAFT to ACTIVE

        # Check DB
        skill1.refresh_from_db()
        skill2.refresh_from_db()
        self.assertEqual(skill1.status, "ACTIVE")
        self.assertEqual(skill2.status, "ACTIVE")
        self.assertEqual(skill1.updated_by, self.user)

    def test_bulk_delete_success(self):
        # Create draft skills and active skills
        skill1 = MasterSkill.objects.create(name="S1", status="DRAFT", created_by=self.user, updated_by=self.user)
        skill2 = MasterSkill.objects.create(name="S2", status="DRAFT", created_by=self.user, updated_by=self.user)
        skill3 = MasterSkill.objects.create(name="S3", status="ACTIVE", created_by=self.user, updated_by=self.user)

        url = reverse("master-skill-bulk-delete")
        response = self.client.delete(url, {"skillIds": [skill1.id, skill2.id, skill3.id]}, format="json")

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data["data"]["deleted_count"], 2) # only s1 and s2 (DRAFT) should be deleted

        # Verify DB
        self.assertFalse(MasterSkill.objects.filter(id=skill1.id).exists())
        self.assertFalse(MasterSkill.objects.filter(id=skill2.id).exists())
        self.assertTrue(MasterSkill.objects.filter(id=skill3.id).exists())
