import pytest
from django.contrib.auth import get_user_model
from model_bakery import baker
from inquiry.models import Inquiries
from products.models import Products
import json
from unittest.mock import patch

Users = get_user_model()


@pytest.mark.django_db()
class TestInquiryModel:
    def test_return_str_model(self):
        inquiry = baker.make(Inquiries)
        assert (
            str(inquiry)
            == f"Inquiry by {inquiry.email} submitted on {inquiry.created_at.strftime('%B %d, %Y')} | {inquiry.status}"
        )


# Create your tests here.
@pytest.mark.django_db()
class TestInquiriesFetch:
    def setup_method(self):
        self.admin = baker.make(Users, is_staff=True)
        self.user = baker.make(Users, is_staff=False)

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

        self.product_1 = baker.make(
            Products, name="Sample Product 1", description=modified_description
        )

        self.inq_1 = baker.make(Inquiries, product=self.product_1)
        self.inq_2 = baker.make(Inquiries)

    def test_fetch_inquiries_by_non_admin_return_403(self, authenticate_user):
        api_client = authenticate_user()
        response = api_client.get("/api/inquiry/inquire/")

        assert response.status_code == 403

    def test_fetch_inquiries_by_admin_return_200(self, authenticate_user):
        api_client = authenticate_user(user=self.admin)
        response = api_client.get("/api/inquiry/inquire/")

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

    def test_fetch_inquiries_with_search_by_admin_return_200(self, authenticate_user):
        api_client = authenticate_user(user=self.admin)
        response = api_client.get(f"/api/inquiry/inquire/?search=Sample")

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

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

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

        self.product_1 = baker.make(
            Products, name="Sample Product 1", description=modified_description
        )

    @patch("inquiry.views.send_emails.delay")
    def test_create_inquiries_by_non_admin_return_201(
        self, mock_send_emails, authenticate_user
    ):
        api_client = authenticate_user(user=self.user)

        data = {
            "first_name": "John",
            "last_name": "Doe",
            "email": "johndoe@gmail.com",
            "contact_number": "00912345678",
            "inquiry": "Sample Inquiry Text",
            "product": self.product_1.id,
        }

        response = api_client.post("/api/inquiry/inquire/", data=data)

        assert response.status_code == 201
        assert response.data["message"] == "Inquiry was created successfully."
        mock_send_emails.assert_called_once()

    def test_create_inquiries_without_product_by_non_admin_return_400(
        self, authenticate_user
    ):
        api_client = authenticate_user(user=self.user)

        data = {
            "first_name": "John",
            "last_name": "Doe",
            "email": "johndoe@gmail.com",
            "contact_number": "00912345678",
            "inquiry": "Sample Inquiry Text",
        }

        response = api_client.post("/api/inquiry/inquire/", data=data)

        assert response.status_code == 400
        assert response.data["message"] == "Inquiry must include a product to inquire."


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

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

        self.product_1 = baker.make(
            Products, name="Sample Product 1", description=modified_description
        )

        self.inq_1 = baker.make(Inquiries, product=self.product_1)
        self.inq_2 = baker.make(Inquiries)

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

        response = api_client.post(
            f"/api/inquiry/mark-status/", data={"status": "spam"}
        )

        assert response.status_code == 403

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

        data = {
            "inquiry_id": self.inq_1.id,
            "status": "solved",
        }

        response = api_client.post(f"/api/inquiry/mark-status/", data=data)

        assert response.status_code == 400
        assert (
            response.data["message"]
            == f"'{data['status']}' is not a valid option. Choose between 'pending', 'endorsed', and 'spam' only."
        )

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

        data = {
            "inquiry_id": "73ee87a3-a145-443f-a205-8f92f4bd6905",
            "status": "spam",
        }

        response = api_client.post(f"/api/inquiry/mark-status/", data=data)

        assert response.status_code == 404
        assert response.data["message"] == "Inquiry not found."

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

        data = {
            "inquiry_id": self.inq_1.id,
            "status": "endorsed",
        }

        response = api_client.post(f"/api/inquiry/mark-status/", data=data)

        assert response.status_code == 200
        assert response.data["message"] == "Inquiry status was updated successfully."
