"""Tests for the new Terms, Support, Favorites/Stores, and Shop Profile endpoints."""

from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.test import APITestCase

from apps.core.models import SupportContact, TermsPage
from apps.engagement.models import Favorite
from apps.stores.models import Store

User = get_user_model()

API = "/api/v1"


class TermsEndpointTests(APITestCase):
    def test_get_returns_404_when_not_configured(self):
        resp = self.client.get(f"{API}/terms/")
        self.assertEqual(resp.status_code, status.HTTP_404_NOT_FOUND)

    def test_get_returns_localized_content(self):
        TermsPage.objects.create(
            content_en="EN terms", content_ar="AR terms", version_label="1.0"
        )
        resp = self.client.get(f"{API}/terms/", HTTP_ACCEPT_LANGUAGE="en")
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.data["content"], "EN terms")
        self.assertEqual(resp.data["content_en"], "EN terms")
        self.assertEqual(resp.data["content_ar"], "AR terms")
        self.assertEqual(resp.data["version_label"], "1.0")

    def test_update_requires_admin(self):
        resp = self.client.put(f"{API}/terms/update/", {"content_en": "x"}, format="json")
        self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)

        user = User.objects.create_user(username="u1", password="p", email="u1@x.test")
        self.client.force_authenticate(user=user)
        resp = self.client.put(f"{API}/terms/update/", {"content_en": "x"}, format="json")
        self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)

    def test_update_creates_singleton(self):
        admin = User.objects.create_superuser(username="admin", password="p", email="admin@x.test")
        self.client.force_authenticate(user=admin)
        resp = self.client.put(
            f"{API}/terms/update/",
            {"content_en": "EN", "content_ar": "AR", "version_label": "1.1"},
            format="json",
        )
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(TermsPage.objects.count(), 1)
        terms = TermsPage.objects.get(pk=1)
        self.assertEqual(terms.content_en, "EN")
        self.assertEqual(terms.version_label, "1.1")


class SupportEndpointTests(APITestCase):
    def test_get_returns_blank_singleton_when_not_configured(self):
        resp = self.client.get(f"{API}/support/")
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        for field in ("whatsapp_number", "instagram_handle", "chat_url", "phone_number", "email"):
            self.assertIn(field, resp.data)

    def test_get_returns_configured_handles(self):
        SupportContact.objects.create(
            whatsapp_number="+971501234567",
            instagram_handle="rofoof_app",
            phone_number="+97140000000",
            email="support@rfoof.online",
        )
        resp = self.client.get(f"{API}/support/")
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(resp.data["whatsapp_number"], "+971501234567")
        self.assertEqual(resp.data["instagram_handle"], "rofoof_app")
        self.assertEqual(resp.data["phone_number"], "+97140000000")
        self.assertEqual(resp.data["email"], "support@rfoof.online")

    def test_update_requires_admin(self):
        resp = self.client.put(
            f"{API}/support/update/", {"whatsapp_number": "+971501234567"}, format="json"
        )
        self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)

        user = User.objects.create_user(username="u1", password="p", email="u1@x.test")
        self.client.force_authenticate(user=user)
        resp = self.client.put(
            f"{API}/support/update/", {"whatsapp_number": "+971501234567"}, format="json"
        )
        self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)

    def test_admin_can_update(self):
        admin = User.objects.create_superuser(username="admin", password="p", email="admin@x.test")
        self.client.force_authenticate(user=admin)
        resp = self.client.put(
            f"{API}/support/update/",
            {
                "whatsapp_number": "+971500000000",
                "instagram_handle": "rofoof_app",
                "chat_url": "https://rfoof.online/chat",
                "phone_number": "+97140000000",
                "email": "support@rfoof.online",
            },
            format="json",
        )
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(SupportContact.objects.count(), 1)
        contact = SupportContact.objects.get(pk=1)
        self.assertEqual(contact.whatsapp_number, "+971500000000")
        self.assertEqual(contact.chat_url, "https://rfoof.online/chat")


class FavoritesFilterTests(APITestCase):
    def setUp(self):
        self.user = User.objects.create_user(username="shopper", password="p", email="shopper@x.test")
        self.client.force_authenticate(user=self.user)

        self.deals_store = Store.objects.create(
            name_en="Deals Store", name_ar="متجر العروض",
            has_deals=True, supports_installments=False,
            is_online=True, is_in_store=False,
        )
        self.installments_store = Store.objects.create(
            name_en="Installments Store", name_ar="متجر التقسيط",
            has_deals=False, supports_installments=True,
            is_online=True, is_in_store=True,
        )
        self.plain_store = Store.objects.create(
            name_en="Plain Store", name_ar="متجر عادي",
            has_deals=False, supports_installments=False,
            is_online=False, is_in_store=True,
        )
        for s in (self.deals_store, self.installments_store, self.plain_store):
            Favorite.objects.create(user=self.user, store=s)

    def _names(self, resp):
        data = resp.data["results"] if isinstance(resp.data, dict) and "results" in resp.data else resp.data
        return sorted(item["store"]["name_en"] for item in data)

    def test_no_filter_returns_all(self):
        resp = self.client.get(f"{API}/favorites/")
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertEqual(len(self._names(resp)), 3)

    def test_search_filter(self):
        resp = self.client.get(f"{API}/favorites/?search=deals")
        self.assertEqual(self._names(resp), ["Deals Store"])

    def test_search_is_case_insensitive_and_matches_arabic(self):
        resp = self.client.get(f"{API}/favorites/?search=التقسيط")
        self.assertEqual(self._names(resp), ["Installments Store"])

    def test_deals_filter(self):
        resp = self.client.get(f"{API}/favorites/?deals=true")
        self.assertEqual(self._names(resp), ["Deals Store"])

    def test_installments_filter(self):
        resp = self.client.get(f"{API}/favorites/?installments=true")
        self.assertEqual(self._names(resp), ["Installments Store"])

    def test_online_filter(self):
        resp = self.client.get(f"{API}/favorites/?online=true")
        self.assertEqual(self._names(resp), ["Deals Store", "Installments Store"])

    def test_in_store_filter(self):
        resp = self.client.get(f"{API}/favorites/?in_store=true")
        self.assertEqual(self._names(resp), ["Installments Store", "Plain Store"])

    def test_combined_filters(self):
        resp = self.client.get(f"{API}/favorites/?installments=true&in_store=true")
        self.assertEqual(self._names(resp), ["Installments Store"])


class StoreIsFavoritedTests(APITestCase):
    def setUp(self):
        self.user = User.objects.create_user(username="shopper", password="p", email="shopper@x.test")
        self.fav_store = Store.objects.create(name_en="Fav", name_ar="مفضل")
        self.other_store = Store.objects.create(name_en="Other", name_ar="آخر")
        Favorite.objects.create(user=self.user, store=self.fav_store)

    def test_anonymous_sees_false(self):
        resp = self.client.get(f"{API}/stores/{self.fav_store.pk}/")
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertFalse(resp.data["is_favorited"])

    def test_authenticated_sees_true_for_favorited(self):
        self.client.force_authenticate(user=self.user)
        resp = self.client.get(f"{API}/stores/{self.fav_store.pk}/")
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertTrue(resp.data["is_favorited"])

    def test_authenticated_sees_false_for_non_favorited(self):
        self.client.force_authenticate(user=self.user)
        resp = self.client.get(f"{API}/stores/{self.other_store.pk}/")
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        self.assertFalse(resp.data["is_favorited"])


class StoreListSerializerFieldsTests(APITestCase):
    """Screen 2 (My Registered shops) needs is_online / is_in_store on the list payload."""

    def test_list_includes_online_and_in_store_flags(self):
        Store.objects.create(name_en="A", name_ar="A", is_online=True, is_in_store=False)
        Store.objects.create(name_en="B", name_ar="B", is_online=False, is_in_store=True)
        resp = self.client.get(f"{API}/stores/")
        self.assertEqual(resp.status_code, status.HTTP_200_OK)
        results = resp.data["results"] if isinstance(resp.data, dict) else resp.data
        self.assertGreaterEqual(len(results), 2)
        for item in results:
            self.assertIn("is_online", item)
            self.assertIn("is_in_store", item)
            self.assertIn("is_recently_added", item)
            self.assertIn("is_trending", item)


class StoreWriteSerializerTests(APITestCase):
    """Screen 4 (Shop info edit form) — write serializer must accept all editable fields."""

    def setUp(self):
        self.owner = User.objects.create_user(username="merchant", password="p", email="merchant@x.test")
        self.client.force_authenticate(user=self.owner)

    def _payload(self, **overrides):
        data = {
            "name_en": "El7eeb",
            "name_ar": "الحبيب",
            "description_en": "Best perfumes",
            "description_ar": "أفضل العطور",
            "is_online": True,
            "is_in_store": True,
            "whatsapp_link": "https://wa.me/971500000000",
            "instagram_link": "https://instagram.com/el7eeb",
        }
        data.update(overrides)
        return data

    def test_create_accepts_full_form_payload(self):
        resp = self.client.post(f"{API}/stores/", self._payload(), format="json")
        self.assertEqual(resp.status_code, status.HTTP_201_CREATED, resp.data)
        store = Store.objects.get(pk=resp.data["id"])
        self.assertEqual(store.owner, self.owner)
        self.assertEqual(store.description_en, "Best perfumes")
        self.assertTrue(store.is_online)
        self.assertTrue(store.is_in_store)
        self.assertEqual(store.whatsapp_link, "https://wa.me/971500000000")
        self.assertEqual(store.instagram_link, "https://instagram.com/el7eeb")
        # Response uses StoreDetailSerializer
        self.assertIn("branches", resp.data)
        self.assertIn("payment_methods", resp.data)

    def test_create_requires_name_description_whatsapp_instagram(self):
        for missing in ("name_en", "description_en", "whatsapp_link", "instagram_link"):
            data = self._payload()
            data.pop(missing)
            resp = self.client.post(f"{API}/stores/", data, format="json")
            self.assertEqual(
                resp.status_code,
                status.HTTP_400_BAD_REQUEST,
                f"expected 400 when {missing} missing",
            )
            self.assertIn(missing, resp.data)

    def test_create_requires_at_least_one_type(self):
        data = self._payload(is_online=False, is_in_store=False)
        resp = self.client.post(f"{API}/stores/", data, format="json")
        self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn("type", resp.data)

    def test_partial_update_allows_owner(self):
        store = Store.objects.create(
            owner=self.owner,
            name_en="Old", name_ar="قديم",
            description_en="x", description_ar="x",
            is_online=True, is_in_store=False,
            whatsapp_link="https://wa.me/971500000000",
            instagram_link="https://instagram.com/old",
        )
        resp = self.client.patch(
            f"{API}/stores/{store.pk}/", {"name_en": "New"}, format="json"
        )
        self.assertEqual(resp.status_code, status.HTTP_200_OK, resp.data)
        store.refresh_from_db()
        self.assertEqual(store.name_en, "New")

    def test_partial_update_blocked_for_non_owner(self):
        other = User.objects.create_user(username="other", password="p", email="other@x.test")
        store = Store.objects.create(
            owner=other,
            name_en="Other", name_ar="آخر",
            description_en="x", description_ar="x",
            is_online=True, is_in_store=False,
            whatsapp_link="https://wa.me/971500000000",
            instagram_link="https://instagram.com/other",
        )
        resp = self.client.patch(
            f"{API}/stores/{store.pk}/", {"name_en": "Hacked"}, format="json"
        )
        self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)


class StoreOwnerCanDeleteTests(APITestCase):
    """Screen 4 trash icon — owners must be able to delete their own store."""

    def test_owner_can_delete(self):
        owner = User.objects.create_user(username="merchant", password="p", email="merchant@x.test")
        store = Store.objects.create(owner=owner, name_en="Mine", name_ar="لي")
        self.client.force_authenticate(user=owner)
        resp = self.client.delete(f"{API}/stores/{store.pk}/")
        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)
        self.assertFalse(Store.objects.filter(pk=store.pk).exists())

    def test_non_owner_cannot_delete(self):
        owner = User.objects.create_user(username="merchant", password="p", email="merchant@x.test")
        intruder = User.objects.create_user(username="intruder", password="p", email="intruder@x.test")
        store = Store.objects.create(owner=owner, name_en="Mine", name_ar="لي")
        self.client.force_authenticate(user=intruder)
        resp = self.client.delete(f"{API}/stores/{store.pk}/")
        self.assertEqual(resp.status_code, status.HTTP_403_FORBIDDEN)
        self.assertTrue(Store.objects.filter(pk=store.pk).exists())

    def test_admin_can_delete(self):
        owner = User.objects.create_user(username="merchant", password="p", email="merchant@x.test")
        admin = User.objects.create_superuser(username="admin", password="p", email="admin@x.test")
        store = Store.objects.create(owner=owner, name_en="Mine", name_ar="لي")
        self.client.force_authenticate(user=admin)
        resp = self.client.delete(f"{API}/stores/{store.pk}/")
        self.assertEqual(resp.status_code, status.HTTP_204_NO_CONTENT)


class MerchantBannerPlacementTests(APITestCase):
    """Screen 1 & 2 promo banner — merchant_join placement should be valid."""

    def test_merchant_join_is_a_valid_placement(self):
        from apps.content.models import Banner

        banner = Banner.objects.create(
            title_en="Join Rofoof",
            placement="merchant_join",
            is_active=True,
        )
        self.assertEqual(banner.placement, "merchant_join")
