# -*- coding: utf-8 -*-
"""STEP 8 tests — discovery + Rule 12.351 subpoena (objection-window gate + routing).

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

Objection-window math uses FIXED notice dates safely in the past/future. Proves:
  * a non-party subpoena cannot issue before the objection window elapses;
  * it cannot issue while an objection is pending;
  * it can issue once the window has elapsed with no objection;
  * issuance serves the Notice of Issuance the SAME DAY;
  * issuance routing follows representation (attorney direct vs clerk);
  * party discovery (non-12.351) is not blocked by the window.
"""

from datetime import date

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


@tagged("post_install", "-at_install", "familylaw", "familylaw_step8")
class TestStep8Discovery(TransactionCase):

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.partner = cls.env["res.partner"].create({"name": "Disc8 Client"})
        cls.case = cls.env["familylaw.case"].create({
            "name": "Discovery Matter", "client_id": cls.partner.id,
            "case_type": "support_modification", "representation": "attorney",
        })
        cls.proc = cls.case.proceeding_ids[0]
        cls.case_prose = cls.env["familylaw.case"].create({
            "name": "Pro Se Matter", "client_id": cls.partner.id,
            "case_type": "support_modification", "representation": "pro_se",
        })
        cls.proc_prose = cls.case_prose.proceeding_ids[0]
        cls.Req = cls.env["familylaw.discovery.request"]

    def _nonparty(self, proc=None, **kw):
        vals = {
            "name": "Subpoena to Employer",
            "proceeding_id": (proc or self.proc).id,
            "discovery_type": "nonparty_production",
            "nonparty_name": "Acme Corp",
        }
        vals.update(kw)
        return self.Req.create(vals)

    # --- objection window gate ----------------------------------------------
    def test_01_cannot_issue_before_notice(self):
        req = self._nonparty()
        with self.assertRaises(UserError):
            req.action_issue()

    def test_02_cannot_issue_before_window_elapses(self):
        # notice served in the future -> window not elapsed
        req = self._nonparty(notice_served_date=date(2999, 1, 1),
                             state="notice_served")
        with self.assertRaises(UserError):
            req.action_issue()
        self.assertNotEqual(req.state, "issued")

    def test_03_can_issue_after_window(self):
        req = self._nonparty(notice_served_date=date(2000, 1, 1),
                             state="notice_served")
        req.action_issue()
        self.assertEqual(req.state, "issued")

    def test_04_pending_objection_blocks_issue(self):
        req = self._nonparty(notice_served_date=date(2000, 1, 1),
                             state="notice_served")
        req.action_record_objection()
        self.assertEqual(req.state, "objected")
        with self.assertRaises(UserError):
            req.action_issue()

    # --- objection deadline math --------------------------------------------
    def test_05_objection_deadline_10_days(self):
        # 2025-01-01 (Wed) + 10 = 2025-01-11 (Sat) -> 2025-01-13 (Mon)
        req = self._nonparty(notice_served_date=date(2025, 1, 1))
        self.assertEqual(req.objection_deadline, date(2025, 1, 13))

    # --- same-day notice of issuance ----------------------------------------
    def test_06_notice_of_issuance_same_day(self):
        req = self._nonparty(notice_served_date=date(2000, 1, 1),
                             state="notice_served")
        req.action_issue()
        self.assertTrue(req.issuance_date)
        self.assertEqual(req.notice_of_issuance_date, req.issuance_date)

    def test_07_response_due_30_days(self):
        req = self._nonparty(notice_served_date=date(2000, 1, 1),
                             state="notice_served")
        req.action_issue()
        self.assertTrue(req.response_due_date)

    # --- routing ------------------------------------------------------------
    def test_08_attorney_route(self):
        req = self._nonparty()
        self.assertEqual(req.issuance_route, "attorney_direct")

    def test_09_prose_route_clerk(self):
        req = self._nonparty(proc=self.proc_prose)
        self.assertEqual(req.issuance_route, "clerk")

    # --- party discovery is not gated by 12.351 -----------------------------
    def test_10_party_production_issues_freely(self):
        req = self.Req.create({
            "name": "RFP to opposing party",
            "proceeding_id": self.proc.id,
            "discovery_type": "production",
        })
        req.action_issue()  # no window required
        self.assertEqual(req.state, "issued")

    # --- serve notice sets date + state -------------------------------------
    def test_11_serve_notice(self):
        req = self._nonparty()
        req.action_serve_notice()
        self.assertEqual(req.state, "notice_served")
        self.assertTrue(req.notice_served_date)
        self.assertTrue(req.objection_deadline)

    # --- isolation ----------------------------------------------------------
    def test_12_discovery_listed_on_proceeding(self):
        req = self._nonparty()
        self.assertIn(req, self.proc.discovery_ids)
