import pytest
from django.contrib.auth import get_user_model
from model_bakery import baker
from products.models import NewsAndPressReleases
import json, uuid
from django.core.files.uploadedfile import SimpleUploadedFile
from unittest.mock import patch

Users = get_user_model()


@pytest.mark.django_db()
class TestNewsAndPressReleasesModel:
    def test_return_str_model(self):
        modified_description = json.dumps({"delta": "", "html": "Hello World"})

        news_press_release = baker.make(
            NewsAndPressReleases,
            short_description=modified_description,
            long_description=modified_description,
            type="news",
        )
        assert (
            str(news_press_release)
            == f"{news_press_release.title} - {news_press_release.type.upper()}"
        )


@pytest.mark.django_db()
class TestNewsAndPressReleasesFetch:
    def setup_method(self):
        self.modified_description = json.dumps({"delta": "", "html": "Hello World"})

        self.news_press_release_1 = baker.make(
            NewsAndPressReleases,
            short_description=self.modified_description,
            long_description=self.modified_description,
            type="news",
        )
        self.news_press_release_2 = baker.make(
            NewsAndPressReleases,
            short_description=self.modified_description,
            long_description=self.modified_description,
            type="press",
        )

    def test_fetch_news_and_press_releases_by_any_user_return_200(
        self, authenticate_user
    ):
        api_client = authenticate_user()

        response = api_client.get("/api/products/news-and-press/")

        assert response.status_code == 200
        assert response.data["count"] == 2

    def test_fetch_news_only_by_any_user_return_200(self, authenticate_user):
        api_client = authenticate_user()

        response = api_client.get("/api/products/news-and-press/?type=news")

        assert response.status_code == 200
        assert response.data["count"] == 1

    def test_fetch_press_releases_only_by_any_user_return_200(self, authenticate_user):
        api_client = authenticate_user()

        response = api_client.get("/api/products/news-and-press/?type=press")

        assert response.status_code == 200
        assert response.data["count"] == 1


@pytest.mark.django_db()
class TestNewsAndPressReleasesCreate:
    def setup_method(self):
        self.admin = baker.make(Users, is_staff=True)

        self.modified_description = json.dumps({"delta": "", "html": "Hello World"})

        self.news_1 = baker.make(
            NewsAndPressReleases,
            title="News 1",
            short_description=self.modified_description,
            long_description=self.modified_description,
            type="news",
        )

        self.press_release_1 = baker.make(
            NewsAndPressReleases,
            title="Press 1",
            short_description=self.modified_description,
            long_description=self.modified_description,
            type="press",
        )

    def test_create_news_or_press_release_by_non_admin_return_403(
        self, authenticate_user
    ):
        api_client = authenticate_user()

        data = {
            "title": "Test News or Press Release",
            "short_description": "<p>Test SD</p>",
            "long_description": "<b>Test LD</b>",
            "type": "news",
        }

        response = api_client.post("/api/products/news-and-press/", data=data)

        assert response.status_code == 403

    @patch("products.views.R2")
    def test_create_news_or_press_release_by_admin_return_201(
        self, mock_r2, authenticate_user
    ):
        api_client = authenticate_user(user=self.admin)

        mock_r2_instance = mock_r2.return_value
        mock_r2_instance.upload_fileobj.return_value = "/news_images/image.jpg"

        mock_image = SimpleUploadedFile(
            "main-image.jpg", b"mock-image-content", content_type="image/jpeg"
        )

        mock_news_image_1 = SimpleUploadedFile(
            "img1.jpg", b"mock-image-content", content_type="image/jpeg"
        )
        mock_news_image_2 = SimpleUploadedFile(
            "img2.jpg", b"mock-image-content", content_type="image/jpeg"
        )

        data = {
            "title": "Test News",
            "short_description": self.modified_description,
            "long_description": self.modified_description,
            "type": "news",
            "link": "www.example.com",
            "image_path": mock_image,
            "news_images[]": [mock_news_image_1, mock_news_image_2],
        }

        response = api_client.post("/api/products/news-and-press/", data=data)

        assert response.status_code == 201
        assert response.data["id"] is not None

    def test_create_news_with_existing_title_by_admin_return_400(
        self, authenticate_user
    ):
        api_client = authenticate_user(user=self.admin)

        mock_image = SimpleUploadedFile(
            "main-image.jpg", b"mock-image-content", content_type="image/jpeg"
        )

        mock_news_image_1 = SimpleUploadedFile(
            "img1.jpg", b"mock-image-content", content_type="image/jpeg"
        )
        mock_news_image_2 = SimpleUploadedFile(
            "img2.jpg", b"mock-image-content", content_type="image/jpeg"
        )

        data = {
            "title": "News 1",
            "short_description": self.modified_description,
            "long_description": self.modified_description,
            "type": "news",
            "link": "www.example.com",
            "image_path": mock_image,
            "news_images[]": [mock_news_image_1, mock_news_image_2],
        }

        response = api_client.post("/api/products/news-and-press/", data=data)

        assert response.status_code == 400
        assert (
            response.data["message"]
            == f"Title {data['title']} under {data['type'].upper()} already exists."
        )

    def test_create_press_release_with_existing_title_by_admin_return_400(
        self, authenticate_user
    ):
        api_client = authenticate_user(user=self.admin)

        mock_image = SimpleUploadedFile(
            "main-image.jpg", b"mock-image-content", content_type="image/jpeg"
        )

        data = {
            "title": "Press 1",
            "short_description": self.modified_description,
            "long_description": self.modified_description,
            "type": "press",
            "link": "www.example.com",
            "image_path": mock_image,
        }

        response = api_client.post("/api/products/news-and-press/", data=data)

        assert response.status_code == 400
        assert (
            response.data["message"]
            == f"Title {data['title']} under {data['type'].upper()} already exists."
        )


@pytest.mark.django_db()
class TestNewsAndPressReleasesUpdate:
    def setup_method(self):
        self.admin = baker.make(Users, is_staff=True)

        self.modified_description = json.dumps({"delta": "", "html": "Hello World"})

        self.news_1 = baker.make(
            NewsAndPressReleases,
            title="News 1",
            short_description=self.modified_description,
            long_description=self.modified_description,
            type="news",
        )

        self.news_2 = baker.make(
            NewsAndPressReleases,
            title="News 2",
            short_description=self.modified_description,
            long_description=self.modified_description,
            type="news",
        )

        self.press_release_1 = baker.make(
            NewsAndPressReleases,
            title="Press 1",
            short_description=self.modified_description,
            long_description=self.modified_description,
            type="press",
        )

    def test_update_news_or_press_release_by_non_admin_return_403(
        self, authenticate_user
    ):
        api_client = authenticate_user()

        data = {
            "title": "Test News or Press Release",
            "short_description": "<p>Test SD</p>",
            "long_description": "<b>Test LD</b>",
            "type": "news",
        }

        response = api_client.put(
            f"/api/products/news-and-press/{self.news_1.id}/", data=data
        )

        assert response.status_code == 403

    @patch("products.views.R2")
    def test_update_news_or_press_release_by_admin_return_200(
        self, mock_r2, authenticate_user
    ):
        api_client = authenticate_user(user=self.admin)

        mock_r2_instance = mock_r2.return_value
        mock_r2_instance.upload_fileobj.return_value = "/news_images/image.jpg"

        mock_image = SimpleUploadedFile(
            "main-image.jpg", b"mock-image-content", content_type="image/jpeg"
        )

        data = {
            "title": "Test News",
            "short_description": self.modified_description,
            "long_description": self.modified_description,
            "type": "news",
            "link": "www.example.com",
            "image_path": mock_image,
        }

        response = api_client.put(
            f"/api/products/news-and-press/{self.news_1.id}/", data=data
        )

        assert response.status_code == 200
        assert response.data["id"] is not None

    def test_update_news_with_existing_title_by_admin_return_400(
        self, authenticate_user
    ):
        api_client = authenticate_user(user=self.admin)

        data = {
            "title": "News 2",
            "short_description": self.modified_description,
            "long_description": self.modified_description,
            "type": "news",
            "link": "www.example.com",
        }

        response = api_client.put(
            f"/api/products/news-and-press/{self.news_1.id}/", data=data
        )

        assert response.status_code == 400
        assert (
            response.data["message"]
            == f"Title {data['title']} under {data['type'].upper()} already exists."
        )
