# -*- coding: utf-8 -*-
"""STEP 14 tests — comms (never auto-send) + AI-assist billing + matter-scoped access.

    odoo -d <db> -u activeblue_familylaw --test-enable \
         --test-tags familylaw_step14 --stop-after-init

Proves:
  * a communication cannot be sent before attorney approval (never auto-send);
  * approval is attorney-only; approved comms can be sent;
  * the AI-assisted time ratio is computed and reportable;
  * matter-scoped access: a staff user cannot see unassigned matters; can see
    assigned ones; an attorney sees all.
"""

from odoo.tests.common import TransactionCase, new_test_user, tagged
from odoo.exceptions import UserError, AccessError


@tagged("post_install", "-at_install", "familylaw", "familylaw_step14")
class TestStep14Comms(TransactionCase):

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.attorney = new_test_user(
            cls.env, login="fl_atty14", name="Attorney 14",
            email="atty14@example.com",
            groups="base.group_user,activeblue_familylaw_v2.group_familylaw_attorney",
        )
        cls.para = new_test_user(
            cls.env, login="fl_para14", name="Para 14", email="para14@example.com",
            groups="base.group_user,activeblue_familylaw_v2.group_familylaw_user",
        )
        cls.para_other = new_test_user(
            cls.env, login="fl_para14b", name="Para 14b", email="para14b@example.com",
            groups="base.group_user,activeblue_familylaw_v2.group_familylaw_user",
        )
        cls.partner = cls.env["res.partner"].create({"name": "Comms Client"})
        cls.case = cls.env["familylaw.case"].create({
            "name": "Comms Matter", "client_id": cls.partner.id,
            "case_type": "dissolution_children",
            "attorney_id": cls.attorney.id, "paralegal_id": cls.para.id,
            "county": "broward",  # avoid AO-13 seeding noise
        })
        cls.Comms = cls.env["familylaw.comms"]

    def _comm(self, **kw):
        vals = {"name": "Status update", "case_id": self.case.id,
                "comm_type": "update"}
        vals.update(kw)
        return self.Comms.create(vals)

    # --- never auto-send ----------------------------------------------------
    def test_01_cannot_send_draft(self):
        c = self._comm()
        with self.assertRaises(UserError):
            c.action_send()
        self.assertEqual(c.state, "draft")

    def test_02_approve_then_send(self):
        c = self._comm()
        c.with_user(self.attorney).action_approve()
        self.assertEqual(c.state, "approved")
        c.action_send()
        self.assertEqual(c.state, "sent")
        self.assertTrue(c.sent_date)

    def test_03_approve_requires_attorney(self):
        c = self._comm()
        with self.assertRaises(UserError):
            c.with_user(self.para).action_approve()

    def test_04_no_auto_send_field_or_cron(self):
        # structural: there is no method that sends without going through approval
        c = self._comm()
        self.assertEqual(c.state, "draft")
        with self.assertRaises(UserError):
            c.action_send()

    # --- AI-assisted billing ratio ------------------------------------------
    def test_05_ai_ratio(self):
        TE = self.env["familylaw.time.entry"]
        TE.create({"case_id": self.case.id, "description": "AI draft",
                   "hours": 2.0, "ai_assisted": True})
        TE.create({"case_id": self.case.id, "description": "Manual review",
                   "hours": 6.0, "ai_assisted": False})
        self.assertEqual(self.case.total_hours, 8.0)
        self.assertEqual(self.case.ai_assisted_hours, 2.0)
        self.assertAlmostEqual(self.case.ai_assisted_ratio, 25.0, places=2)

    def test_06_ratio_zero_when_no_time(self):
        self.assertEqual(self.case.ai_assisted_ratio, 0.0)

    # --- matter-scoped access -----------------------------------------------
    def test_07_staff_sees_assigned(self):
        # para is paralegal_id on cls.case -> visible
        found = self.env["familylaw.case"].with_user(self.para).search(
            [("id", "=", self.case.id)])
        self.assertIn(self.case, found)

    def test_08_staff_cannot_see_unassigned(self):
        other_case = self.env["familylaw.case"].create({
            "name": "Other Matter", "client_id": self.partner.id,
            "case_type": "paternity", "attorney_id": self.attorney.id,
            "paralegal_id": self.para.id, "county": "broward",
        })
        # para_other is not assigned and did not create it -> not visible
        found = self.env["familylaw.case"].with_user(self.para_other).search(
            [("id", "=", other_case.id)])
        self.assertNotIn(other_case, found)

    def test_09_attorney_sees_all(self):
        other_case = self.env["familylaw.case"].create({
            "name": "Unassigned-to-attorney Matter", "client_id": self.partner.id,
            "case_type": "paternity", "county": "broward",
        })
        found = self.env["familylaw.case"].with_user(self.attorney).search(
            [("id", "=", other_case.id)])
        self.assertIn(other_case, found)

    def test_10_staff_read_unassigned_raises(self):
        other_case = self.env["familylaw.case"].create({
            "name": "Secret Matter", "client_id": self.partner.id,
            "case_type": "paternity", "county": "broward",
        })
        with self.assertRaises(AccessError):
            other_case.with_user(self.para_other).read(["name"])
