from __future__ import annotations

from unittest.mock import patch

from django.test import TestCase
from django.urls import reverse

from core.models import ContactAvailabilitySettings, ChatSession, ConversationEvent, Person, PersonIdentifier, User


class AvailabilitySettingsPageTests(TestCase):
    def setUp(self):
        self.user = User.objects.create_user("avail-user", "avail@example.com", "x")
        self.client.force_login(self.user)

    def test_get_page_renders(self):
        response = self.client.get(reverse("behavioral_signals_settings"))
        self.assertEqual(200, response.status_code)
        self.assertContains(response, "Behavioral Signals")

    def test_post_updates_settings(self):
        response = self.client.post(
            reverse("behavioral_signals_settings"),
            {
                "enabled": "1",
                "show_in_chat": "1",
                "show_in_groups": "0",
                "inference_enabled": "1",
                "retention_days": "120",
                "fade_threshold_seconds": "300",
            },
        )
        self.assertEqual(200, response.status_code)
        row = ContactAvailabilitySettings.objects.get(user=self.user)
        self.assertTrue(row.enabled)
        self.assertTrue(row.show_in_chat)
        self.assertFalse(row.show_in_groups)
        self.assertTrue(row.inference_enabled)
        self.assertEqual(120, row.retention_days)
        self.assertEqual(300, row.fade_threshold_seconds)

    @patch("core.views.availability.get_behavioral_availability_stats")
    def test_behavioral_manticore_stats_are_in_context(self, mocked_stats):
        person = Person.objects.create(user=self.user, name="Alice")
        mocked_stats.return_value = [
            {
                "person_id": str(person.id),
                "transport": "whatsapp",
                "total_events": 9,
                "presence_events": 2,
                "read_events": 3,
                "typing_events": 2,
                "message_events": 1,
                "abandoned_events": 1,
                "last_event_ts": 5555,
            }
        ]

        response = self.client.get(reverse("behavioral_signals_settings"))

        self.assertEqual(200, response.status_code)
        stats = list(response.context["behavioral_stats"])
        self.assertEqual(1, len(stats))
        self.assertEqual("Alice", stats[0]["person_name"])
        self.assertEqual(1, stats[0]["abandoned_events"])
        self.assertEqual("manticore", response.context["behavioral_stats_source"])
        self.assertContains(response, "Behavioral Event Statistics")
        self.assertNotIn("contact_stats", response.context)
        self.assertNotIn("parity_rows", response.context)

    @patch("core.views.availability.get_behavioral_availability_stats")
    def test_behavioral_stats_fallback_to_conversation_event_shadow(self, mocked_stats):
        person = Person.objects.create(user=self.user, name="Alice")
        identifier = PersonIdentifier.objects.create(
            user=self.user,
            person=person,
            service="signal",
            identifier="+15551230000",
        )
        session = ChatSession.objects.create(user=self.user, identifier=identifier)
        ConversationEvent.objects.create(
            user=self.user,
            session=session,
            ts=1234,
            event_type="presence_available",
            direction="system",
            origin_transport="signal",
        )
        mocked_stats.return_value = []

        response = self.client.get(reverse("behavioral_signals_settings"))

        self.assertEqual(200, response.status_code)
        stats = list(response.context["behavioral_stats"])
        self.assertEqual(1, len(stats))
        self.assertEqual("Alice", stats[0]["person_name"])
        self.assertEqual(1, int(stats[0]["presence_events"]))
        self.assertEqual(
            "conversation_event_shadow", response.context["behavioral_stats_source"]
        )

    def test_legacy_availability_url_redirects(self):
        response = self.client.get(reverse("availability_settings"))
        self.assertEqual(302, response.status_code)
        self.assertIn(
            reverse("behavioral_signals_settings"),
            str(response.headers.get("Location") or ""),
        )
