from datetime import date

from django.contrib.auth import get_user_model
from django.test import TestCase
from django.urls import reverse

from crm.forms import ContactForm
from crm.models import Activity, Lead
from schools.models import School


class LeadTimelineTests(TestCase):
    def setUp(self):
        self.admin = get_user_model().objects.create_superuser(username="crm-admin", password="test")
        self.client.force_login(self.admin)
        self.school = School.objects.create(
            organization_id=876543,
            name="Timeline School",
            data={"organizationName": "Timeline School"},
        )
        self.lead = Lead.objects.create(school=self.school)

    def lead_payload(self, **overrides):
        payload = {
            "stage": "interested",
            "priority": "high",
            "owner": "",
            "next_followup": "2026-10-20",
            "next_action": "Prepare enrollment proposal",
            "deal_value": "1250.00",
            "lost_reason": "",
            "activity_kind": "",
            "activity_outcome": "",
            "activity_occurred_at": "",
            "activity_notes": "",
        }
        payload.update(overrides)
        return payload

    def test_one_submission_updates_lead_and_logs_visit(self):
        page = self.client.get(reverse("school_crm", kwargs={"org_id": self.school.organization_id}))
        self.assertContains(page, "Lead status &amp; activity")
        self.assertContains(page, "Save lead and activity")
        self.assertNotContains(page, "Log an activity")

        response = self.client.post(
            reverse("crm_save_lead", kwargs={"org_id": self.school.organization_id}),
            self.lead_payload(
                activity_kind="visit",
                activity_outcome="connected",
                activity_occurred_at="2026-10-09T10:30",
                activity_notes="Met the head teacher",
            ),
        )

        self.assertEqual(response.status_code, 302)
        self.lead.refresh_from_db()
        self.assertEqual(self.lead.stage, "interested")
        self.assertEqual(self.lead.deal_value, 1250)
        self.assertEqual(self.lead.next_action, "Prepare enrollment proposal")
        self.assertEqual(self.lead.next_followup, date(2026, 10, 20))
        visit = Activity.objects.get(lead=self.lead, kind="visit")
        self.assertEqual(visit.notes, "Met the head teacher")
        summary = Activity.objects.get(lead=self.lead, kind="stage")
        self.assertIn("Deal value", summary.notes)
        self.assertIn("What to do next", summary.notes)
        self.assertIn("Next follow-up", summary.notes)

    def test_notes_without_type_become_a_note(self):
        response = self.client.post(
            reverse("crm_save_lead", kwargs={"org_id": self.school.organization_id}),
            self.lead_payload(activity_notes="Spoke with the office"),
        )
        self.assertEqual(response.status_code, 302)
        note = Activity.objects.get(lead=self.lead, kind="note")
        self.assertEqual(note.notes, "Spoke with the office")

    def test_terminal_stage_clears_and_logs_followup(self):
        self.lead.next_followup = date(2026, 10, 15)
        self.lead.next_action = "Call back"
        self.lead.save()

        response = self.client.post(
            reverse("crm_save_lead", kwargs={"org_id": self.school.organization_id}),
            self.lead_payload(
                stage="won",
                next_followup="2026-10-20",
                next_action="A value cleared for terminal stages",
            ),
        )

        self.assertEqual(response.status_code, 302)
        self.lead.refresh_from_db()
        self.assertIsNone(self.lead.next_followup)
        self.assertEqual(self.lead.next_action, "")
        timeline = Activity.objects.get(lead=self.lead, kind="stage")
        self.assertIn("Next follow-up: 2026-10-15 → -", timeline.notes)
        self.assertIn("What to do next: Call back → -", timeline.notes)

    def test_dnc_rejects_contact_activity_without_saving_lead(self):
        response = self.client.post(
            reverse("crm_save_lead", kwargs={"org_id": self.school.organization_id}),
            self.lead_payload(stage="dnc", lost_reason="Asked not to be contacted", activity_kind="visit"),
        )

        self.assertEqual(response.status_code, 400)
        self.lead.refresh_from_db()
        self.assertEqual(self.lead.stage, "new")
        self.assertFalse(Activity.objects.filter(lead=self.lead).exists())

    def test_negative_deal_value_is_rejected(self):
        response = self.client.post(
            reverse("crm_save_lead", kwargs={"org_id": self.school.organization_id}),
            self.lead_payload(deal_value="-1"),
        )

        self.assertEqual(response.status_code, 400)
        self.lead.refresh_from_db()
        self.assertIsNone(self.lead.deal_value)

    def test_my_leads_rows_have_full_row_navigation(self):
        self.lead.owner = self.admin
        self.lead.save(update_fields=["owner"])

        response = self.client.get(reverse("crm_myleads"))

        self.assertContains(response, 'class="lead-row"')
        self.assertContains(response, 'data-href="/school/876543/"')
        self.assertContains(response, 'tabindex="0"')

    def test_followup_rows_have_full_row_navigation(self):
        self.lead.owner = self.admin
        self.lead.next_followup = date(2026, 10, 10)
        self.lead.next_action = "Prepare the enrollment figures"
        self.lead.save(update_fields=["owner", "next_followup", "next_action"])

        response = self.client.get(reverse("crm_followups"))

        self.assertContains(response, 'class="lead-row"')
        self.assertContains(response, 'data-href="/school/876543/"')
        self.assertContains(response, "Prepare the enrollment figures")

    def test_contact_form_accepts_supported_phone_formats_and_rejects_other_lengths(self):
        for number in ("12345", "9812345678", "987-1234567", "+9779812345678"):
            with self.subTest(number=number):
                form = ContactForm(data={"name": "Contact", "phone": number})
                self.assertTrue(form.is_valid(), form.errors)

        invalid = ContactForm(data={"name": "Contact", "phone": "1234"})
        self.assertFalse(invalid.is_valid())
        self.assertIn("phone", invalid.errors)