"""University Analytics tests (verification dashboard enhancement)."""

import os
import unittest

os.environ["TEST_DATABASE_URL"] = "sqlite:///:memory:"

from werkzeug.security import generate_password_hash

from app import create_app
from app.auth import verification as v
from app.extensions import db
from app.models import StudentVerificationStatus, User, UserProfile, UserRole

S = StudentVerificationStatus


class UniversityAnalyticsTests(unittest.TestCase):
    def setUp(self):
        self.app = create_app("testing")
        self.ctx = self.app.app_context()
        self.ctx.push()
        db.create_all()
        self.admin = self._user("admin@c.edu", UserRole.SUPER_ADMIN, "Admin")

    def tearDown(self):
        db.session.remove()
        db.drop_all()
        self.ctx.pop()

    def _user(self, email, role=UserRole.STUDENT, name="Student"):
        u = User(email=email, password_hash=generate_password_hash("Passw0rd!"), is_verified=True, role=role)
        u.profile = UserProfile(full_name=name)
        db.session.add(u)
        db.session.commit()
        return u

    def _mk(self, email, university, outcome):
        """Create a student from ``university`` in a given verification state."""
        u = self._user(email)
        v.submit_verification(u, "9876543210", university, "ID-" + email)
        if outcome == "verified":
            v.approve_verification(u, self.admin)
        elif outcome == "rejected":
            v.reject_verification(u, self.admin, "no")
        return u

    # --- top verified + percentage --------------------------------------------
    def test_top_ordering_and_percentage(self):
        for i in range(3):
            self._mk(f"d{i}@c.edu", "Delhi University", "verified")
        for i in range(2):
            self._mk(f"a{i}@c.edu", "Anna University", "verified")
        self._mk("iit@c.edu", "IIT Bombay", "verified")

        top = v.get_top_verified_universities()
        self.assertEqual([t["university"] for t in top],
                         ["Delhi University", "Anna University", "IIT Bombay"])
        self.assertEqual([t["rank"] for t in top], [1, 2, 3])
        self.assertEqual(top[0]["verified"], 3)
        self.assertEqual(top[0]["pct"], round(3 / 6 * 100, 1))   # 50.0
        self.assertEqual(top[1]["pct"], round(2 / 6 * 100, 1))   # 33.3

    def test_top_respects_limit(self):
        for i in range(12):
            self._mk(f"u{i}@c.edu", f"University {i:02d}", "verified")
        self.assertEqual(len(v.get_top_verified_universities(limit=10)), 10)

    # --- breakdown counts ------------------------------------------------------
    def test_breakdown_counts(self):
        self._mk("p@c.edu", "Delhi University", "pending")
        self._mk("v1@c.edu", "Delhi University", "verified")
        self._mk("v2@c.edu", "Delhi University", "verified")
        self._mk("r@c.edu", "Delhi University", "rejected")
        row = next(x for x in v.get_university_breakdown() if x["university"] == "Delhi University")
        self.assertEqual(row["pending"], 1)
        self.assertEqual(row["verified"], 2)
        self.assertEqual(row["rejected"], 1)
        self.assertEqual(row["total"], 4)

    def test_breakdown_ordered_by_total_desc(self):
        for i in range(3):
            self._mk(f"b{i}@c.edu", "Big Uni", "verified")
        self._mk("s@c.edu", "Small Uni", "pending")
        names = [r["university"] for r in v.get_university_breakdown()]
        self.assertEqual(names[0], "Big Uni")

    # --- growth insights -------------------------------------------------------
    def test_largest_smallest_total(self):
        for i in range(3):
            self._mk(f"d{i}@c.edu", "Delhi University", "verified")
        self._mk("a@c.edu", "Anna University", "verified")
        self._mk("p@c.edu", "Pending Only Uni", "pending")   # submitted, not verified

        self.assertEqual(v.get_largest_university(), {"university": "Delhi University", "verified": 3})
        self.assertEqual(v.get_smallest_active_university(), {"university": "Anna University", "verified": 1})
        # distinct submitters (any state): Delhi, Anna, Pending Only Uni
        self.assertEqual(v.get_total_universities(), 3)

    def test_ignores_null_and_empty_university(self):
        self._mk("d@c.edu", "Delhi University", "verified")
        # Defensive: craft verified profiles with no university (bypassing submit).
        x = self._user("x@c.edu"); x.profile.verification_status = S.VERIFIED; x.profile.university_name = None
        y = self._user("y@c.edu"); y.profile.verification_status = S.VERIFIED; y.profile.university_name = ""
        db.session.commit()

        self.assertEqual([t["university"] for t in v.get_top_verified_universities()], ["Delhi University"])
        self.assertEqual([r["university"] for r in v.get_university_breakdown()], ["Delhi University"])
        self.assertEqual(v.get_total_universities(), 1)

    # --- search + queue filter -------------------------------------------------
    def test_search_filtering(self):
        self._mk("d@c.edu", "Delhi University", "verified")
        self._mk("a@c.edu", "Anna University", "verified")
        res = v.get_university_breakdown(search="anna")
        self.assertEqual([r["university"] for r in res], ["Anna University"])

    def test_pending_queue_university_filter(self):
        self._mk("d@c.edu", "Delhi University", "pending")
        self._mk("a@c.edu", "Anna University", "pending")
        delhi = v.get_pending_verifications(university="Delhi University")
        self.assertEqual(len(delhi), 1)
        self.assertEqual(delhi[0].profile.university_name, "Delhi University")
        self.assertEqual(len(v.get_pending_verifications()), 2)

    # --- empty state -----------------------------------------------------------
    def test_empty_state(self):
        stats = v.get_university_statistics()
        self.assertEqual(stats["top_verified"], [])
        self.assertEqual(stats["breakdown"], [])
        self.assertEqual(stats["total_universities"], 0)
        self.assertIsNone(stats["largest"])
        self.assertIsNone(stats["smallest_active"])

    # --- route -----------------------------------------------------------------
    def _login_admin(self):
        client = self.app.test_client()
        client.post("/login", data={"email": "admin@c.edu", "password": "Passw0rd!"})
        return client

    def test_route_renders_analytics_and_queue_filter(self):
        self._mk("d@c.edu", "Delhi University", "verified")
        self._mk("p@c.edu", "Delhi University", "pending")
        self._mk("a@c.edu", "Anna University", "verified")   # ≥2 universities → full analytics
        client = self._login_admin()
        html = client.get("/admin/verifications").get_data(as_text=True)
        self.assertIn("University Analytics", html)
        self.assertIn("Top Verified Universities", html)
        self.assertIn("University Verification Breakdown", html)
        self.assertIn("Delhi University", html)
        self.assertIn("verifications/university/Delhi", html)   # name → Campus Overview

        filtered = client.get("/admin/verifications?university=Delhi University").get_data(as_text=True)
        self.assertIn("View All Universities", filtered)     # clear-filter button

    # --- UX polish -------------------------------------------------------------
    def test_ui_subtitle_present(self):
        self._mk("d@c.edu", "Delhi University", "verified")
        html = self._login_admin().get("/admin/verifications").get_data(as_text=True)
        self.assertIn("Insights into verification activity across participating universities", html)

    def test_ui_empty_state(self):
        html = self._login_admin().get("/admin/verifications").get_data(as_text=True)
        self.assertIn("No university verification data yet", html)
        self.assertNotIn("Top Verified Universities", html)
        self.assertNotIn("University Verification Breakdown", html)

    def test_ui_single_university_informational_state(self):
        self._mk("d@c.edu", "Sharda University", "verified")
        html = self._login_admin().get("/admin/verifications").get_data(as_text=True)
        self.assertIn("University analytics will become more meaningful", html)
        self.assertIn("Sharda University", html)
        self.assertNotIn("Top Verified Universities", html)     # ranking hidden
        self.assertNotIn("Largest Campus", html)
        self.assertNotIn("Smallest Active Campus", html)
        self.assertIn("Total Universities", html)              # still shown
        self.assertIn("University Verification Breakdown", html)  # still shown

    def test_ui_university_names_link_to_campus_overview(self):
        self._mk("d@c.edu", "Delhi University", "verified")
        self._mk("a@c.edu", "Anna University", "verified")
        html = self._login_admin().get("/admin/verifications").get_data(as_text=True)
        self.assertIn("View Campus Overview", html)                # updated tooltip
        self.assertIn("verifications/university/Delhi", html)      # campus link
        self.assertNotIn("is-active-university", html)             # nothing highlighted unfiltered

    def test_ui_active_filter_highlight_banner_button(self):
        self._mk("d@c.edu", "Delhi University", "verified")
        self._mk("p@c.edu", "Delhi University", "pending")
        self._mk("a@c.edu", "Anna University", "verified")
        html = self._login_admin().get(
            "/admin/verifications?university=Delhi University").get_data(as_text=True)
        self.assertIn("is-active-university", html)                # filtered row highlighted
        self.assertIn("View Campus Overview", html)                # names link to campus overview
        self.assertIn("Showing verification requests for", html)   # informative banner
        self.assertIn("View All Universities", html)               # clear-filter button

    def test_ui_medals_for_top_three(self):
        for i in range(3):
            self._mk(f"a{i}@c.edu", "Alpha University", "verified")
        for i in range(2):
            self._mk(f"b{i}@c.edu", "Beta University", "verified")
        self._mk("g@c.edu", "Gamma University", "verified")
        html = self._login_admin().get("/admin/verifications").get_data(as_text=True)
        self.assertIn("🥇", html)
        self.assertIn("🥈", html)
        self.assertIn("🥉", html)

    def test_ui_breadcrumb_present(self):
        self._mk("d@c.edu", "Delhi University", "verified")
        html = self._login_admin().get("/admin/verifications").get_data(as_text=True)
        self.assertIn("breadcrumb", html)


if __name__ == "__main__":
    unittest.main()
