import datetime

from apps.crm.models import Customer
from apps.modules import services as modules
from apps.tasks.models import Task
from infrastructure.models import Attendance, Holiday, LeaveRequest
from tests.base import CoreTestCase

URL = "/api/v1/dashboard/summary/"


class DashboardSummaryTests(CoreTestCase):
    def setUp(self):
        super().setUp()
        for code in ("tasks", "personnel", "crm"):
            modules.enable_module(actor=self.root, organization=self.org_a, module_code=code)
        self.today = datetime.date.today()

    def test_counts_for_the_manager(self):
        Attendance.objects.create(organization=self.org_a, user=self.employee_a, date=self.today, check_in=datetime.time(8))
        Attendance.objects.create(organization=self.org_a, user=self.manager_a, date=self.today, check_in=datetime.time(8),
                                  check_out=datetime.time(12), is_default_checkout=False)
        LeaveRequest.objects.create(organization=self.org_a, user=self.manager_a2, date=self.today, type="daily", status="approved")
        Task.objects.create(organization=self.org_a, title="t", created_by=self.manager_a, status="in_progress")
        Task.objects.create(organization=self.org_a, title="o", created_by=self.manager_a, due_date=self.today - datetime.timedelta(days=1))
        Customer.objects.create(organization=self.org_a, name="c", status="active", created_by=self.manager_a)
        Task.objects.create(organization=self.org_b, title="other", created_by=self.manager_b, status="in_progress")
        d = self.api(self.manager_a, self.org_a).get(URL).data
        self.assertEqual(d["personnel"]["total"], 4)  # manager_a, manager_a2, employee_a, multi
        self.assertEqual(d["tasks"], {"in_progress": 1, "todo": 1, "review": 0, "overdue": 1})
        self.assertEqual(d["customers"]["active"], 1)
        att = d["attendance"]
        self.assertEqual((att["present"], att["finished"], att["on_leave"], att["not_arrived"]), (2, 1, 1, 1))

    def test_holiday_means_nobody_is_missing(self):
        Holiday.objects.create(organization=self.org_a, date=self.today, title="Fest")
        att = self.api(self.manager_a, self.org_a).get(URL).data["attendance"]
        self.assertTrue(att["is_holiday"])
        self.assertEqual(att["not_arrived"], 0)

    def test_sections_follow_modules_and_permissions(self):
        modules.disable_module(actor=self.root, organization=self.org_a, module_code="crm")
        d = self.api(self.manager_a, self.org_a).get(URL).data
        self.assertNotIn("customers", d)
        self.assertIn("tasks", d)

    def test_super_admin_dashboard_counts_organizations_and_users(self):
        from infrastructure.models import User

        d = self.api(self.root, self.platform).get(URL).data
        self.assertEqual(d["platform"]["organizations"], {"total": 2, "active": 2})
        self.assertEqual(d["platform"]["users"]["total"], User.objects.count())
        self.assertNotIn("tasks", d)
        self.assertEqual(d["platform"]["module_requests"], {"pending": 0})
        self.api(self.manager_a, self.org_a).post(f"/api/v1/organizations/{self.org_a.pk}/modules/finance/request/")  # crm is already enabled for org A in setUp
        self.assertEqual(self.api(self.root, self.platform).get(URL).data["platform"]["module_requests"], {"pending": 1})
        self.assertNotIn("platform", self.api(self.manager_a, self.org_a).get(URL).data)

    def test_organizations_menu_only_inside_the_platform_organization(self):
        def keys(user, org):
            return {i["key"] for i in self.api(user, org).get("/api/v1/me/").data["context"]["navigation"]}

        self.assertIn("organizations", keys(self.root, self.platform))
        self.assertNotIn("organizations", keys(self.root, self.org_a))

    def test_employee_and_other_tenants_are_denied(self):
        self.assertEqual(self.api(self.employee_a, self.org_a).get(URL).status_code, 403)
        self.assertEqual(self.api(self.manager_b, self.org_a).get(URL).status_code, 403)
        self.assertEqual(self.api().get(URL).status_code, 401)

    def test_other_org_data_never_counted(self):
        Task.objects.create(organization=self.org_b, title="x", created_by=self.manager_b, status="in_progress")
        d = self.api(self.manager_a, self.org_a).get(URL).data
        self.assertEqual(d["tasks"]["in_progress"], 0)
