from django.contrib.auth import get_user_model
from django.test import TestCase, override_settings
from django.urls import reverse
import re

from .models import ContactEnquiry, CustomerReview, VisitorCounter, WebsiteLikeCounter


@override_settings(
    STORAGES={
        "default": {
            "BACKEND": "django.core.files.storage.FileSystemStorage",
        },
        "staticfiles": {
            "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
        },
    },
    SECURE_SSL_REDIRECT=False,
    SESSION_COOKIE_SECURE=False,
    CSRF_COOKIE_SECURE=False,
    ALLOWED_HOSTS=["testserver", "localhost", "127.0.0.1"],
)
class PublicPageTests(TestCase):
    def test_public_pages_load(self):
        url_names = [
            "travel:home",
            "travel:about",
            "travel:packages",
            "travel:cab_services",
            "travel:destinations",
            "travel:gallery",
            "travel:contact",
            "travel:reviews",
        ]

        for url_name in url_names:
            with self.subTest(url_name=url_name):
                response = self.client.get(reverse(url_name))
                self.assertEqual(response.status_code, 200)

    def test_package_detail_pages_load(self):
        package_slugs = [
            "kerala-tour-package",
            "goa-tour-package",
            "coorg-tour-package",
            "chikmagalur-tour-package",
            "andaman-tour-package",
            "bhutan-tour-package",
            "rajasthan-tour-package",
            "himachal-tour-package",
            "hampi-tour-package",
            "mysore-tour-package",
            "ooty-tour-package",
            "dandeli-tour-package",
            "darjeeling-gangtok-tour-package",
            "golden-triangle-tour-package",
            "kashmir-tour-package",
            "thailand-tour-package",
            "singapore-tour-package",
            "malaysia-tour-package",
            "dubai-tour-package",
            "bali-tour-package",
            "karnataka-tour-packages",
            "karnataka-honeymoon-packages",
            "karnataka-hill-station-packages",
            "karnataka-heritage-packages",
            "karnataka-wildlife-packages",
            "karnataka-beach-packages",
            "karnataka-temple-packages",
            "weekend-getaway-packages",
            "pilgrimage-tour-packages",
            "adventure-tour-packages",
            "coffee-plantation-tours",
            "nature-eco-tourism-packages",
            "family-holiday-packages",
            "customized-karnataka-tours",
            "exclusive-cab-packages",
        ]

        for slug in package_slugs:
            with self.subTest(slug=slug):
                response = self.client.get(
                    reverse("travel:package_detail", kwargs={"package_slug": slug})
                )
                self.assertEqual(response.status_code, 200)
                self.assertContains(response, "Package Includes")

    def test_gallery_album_page_loads(self):
        response = self.client.get(
            reverse("travel:gallery_album", kwargs={"album_slug": "kerala"})
        )

        self.assertEqual(response.status_code, 200)
        self.assertContains(response, "galleryLightbox")

    def test_contact_form_saves_enquiry(self):
        response = self.client.post(
            reverse("travel:contact"),
            {
                "name": "Test Traveller",
                "phone": "9000000000",
                "email": "traveller@example.com",
                "city": "Bengaluru",
                "destination": "Coorg",
                "date_of_travel": "2099-12-30",
                "adults": 2,
                "children": 1,
                "children_ages": "8",
                "number_of_nights": 3,
                "hotel_category": "standard_3_star",
                "special_request": "Planning a family trip with sightseeing.",
            },
            follow=True,
        )

        self.assertEqual(response.status_code, 200)
        self.assertEqual(ContactEnquiry.objects.count(), 1)
        self.assertContains(response, "Your enquiry has been submitted successfully")

    def test_visitor_counter_increments_on_page_load(self):
        self.client.get(reverse("travel:home"))
        self.client.get(reverse("travel:home"))

        self.assertEqual(VisitorCounter.load().total_count, 2)

    def test_review_submission_creates_pending_review(self):
        response = self.client.post(
            reverse("travel:submit_review"),
            {
                "name": "Nisha",
                "city": "Bengaluru",
                "email": "nisha@example.com",
                "rating": 5,
                "review": "Our Chikmagalur trip was smooth and very well coordinated.",
            },
            HTTP_X_REQUESTED_WITH="XMLHttpRequest",
        )

        self.assertEqual(response.status_code, 200)
        self.assertEqual(CustomerReview.objects.count(), 1)
        self.assertEqual(CustomerReview.objects.first().status, CustomerReview.Status.PENDING)

    def test_review_and_website_like_endpoints(self):
        review = CustomerReview.objects.create(
            name="Aman",
            city="Mysuru",
            rating=4,
            review="Well planned and easy to coordinate.",
            status=CustomerReview.Status.APPROVED,
        )

        review_like_response = self.client.post(
            reverse("travel:review_like", kwargs={"review_id": review.id}),
            HTTP_X_REQUESTED_WITH="XMLHttpRequest",
        )
        website_like_response = self.client.post(
            reverse("travel:website_like"),
            HTTP_X_REQUESTED_WITH="XMLHttpRequest",
            HTTP_X_VISITOR_LIKE_TOKEN="browser-token-123456",
        )

        self.assertEqual(review_like_response.status_code, 200)
        self.assertEqual(website_like_response.status_code, 200)

        review.refresh_from_db()
        self.assertEqual(review.likes, 1)
        self.assertEqual(WebsiteLikeCounter.load().total_likes, 1)

    def test_website_like_allows_only_one_like_per_token(self):
        url = reverse("travel:website_like")

        first = self.client.post(
            url,
            HTTP_X_REQUESTED_WITH="XMLHttpRequest",
            HTTP_X_VISITOR_LIKE_TOKEN="one-like-token-123",
        )
        second = self.client.post(
            url,
            HTTP_X_REQUESTED_WITH="XMLHttpRequest",
            HTTP_X_VISITOR_LIKE_TOKEN="one-like-token-123",
        )

        self.assertEqual(first.status_code, 200)
        self.assertEqual(second.status_code, 200)
        self.assertEqual(WebsiteLikeCounter.load().total_likes, 1)

    def test_sitemap_and_robots_available(self):
        sitemap_response = self.client.get("/sitemap.xml")
        robots_response = self.client.get("/robots.txt")

        self.assertEqual(sitemap_response.status_code, 200)
        self.assertContains(sitemap_response, "<urlset", status_code=200)

        self.assertEqual(robots_response.status_code, 200)
        self.assertContains(robots_response, "Sitemap: http://testserver/sitemap.xml")

    def test_main_pages_include_canonical_meta(self):
        response = self.client.get(reverse("travel:home"))

        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'rel="canonical"')
        self.assertContains(response, 'property="og:title"')
        self.assertContains(response, 'name="twitter:card"')

    def test_internal_links_on_key_pages(self):
        key_pages = [
            reverse("travel:home"),
            reverse("travel:about"),
            reverse("travel:packages"),
            reverse("travel:cab_services"),
            reverse("travel:destinations"),
            reverse("travel:gallery"),
            reverse("travel:contact"),
            reverse("travel:reviews"),
        ]

        href_pattern = re.compile(r'href=["\']([^"\']+)["\']')

        for page in key_pages:
            response = self.client.get(page)
            self.assertEqual(response.status_code, 200)
            html = response.content.decode("utf-8")
            hrefs = href_pattern.findall(html)

            for href in hrefs:
                if not href.startswith("/"):
                    continue
                if href.startswith("//"):
                    continue

                target = href.split("#", 1)[0]
                if not target:
                    continue

                with self.subTest(page=page, href=target):
                    target_response = self.client.get(target)
                    self.assertLess(target_response.status_code, 400)


@override_settings(
    STORAGES={
        "default": {
            "BACKEND": "django.core.files.storage.FileSystemStorage",
        },
        "staticfiles": {
            "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
        },
    },
    SECURE_SSL_REDIRECT=False,
    SESSION_COOKIE_SECURE=False,
    CSRF_COOKIE_SECURE=False,
    ALLOWED_HOSTS=["testserver", "localhost", "127.0.0.1"],
)
class DashboardVisitorCounterTests(TestCase):
    def setUp(self):
        user_model = get_user_model()
        self.user = user_model.objects.create_user(
            username="dashboard-admin",
            password="safe-password-123",
            is_staff=True,
        )
        self.client.force_login(self.user)

    def test_dashboard_reset_counter(self):
        VisitorCounter.increment_total()
        VisitorCounter.increment_total()

        response = self.client.post(
            reverse("dashboard"),
            {"action": "reset_visitor_counter"},
        )

        self.assertEqual(response.status_code, 302)
        self.assertEqual(VisitorCounter.load().total_count, 0)

    def test_dashboard_reviews_page_loads(self):
        response = self.client.get(reverse("dashboard_reviews"))
        self.assertEqual(response.status_code, 200)

    def test_dashboard_like_management_reset(self):
        WebsiteLikeCounter.register_visitor_like("reset-like-token-123")
        before = WebsiteLikeCounter.load()

        response = self.client.post(
            reverse("dashboard_likes"),
            {"action": "reset_website_likes"},
        )

        self.assertEqual(response.status_code, 302)

        after = WebsiteLikeCounter.load()
        self.assertEqual(after.total_likes, 0)
        self.assertGreater(after.like_version, before.like_version)

    def test_dashboard_like_management_page_loads(self):
        response = self.client.get(reverse("dashboard_likes"))
        self.assertEqual(response.status_code, 200)
