# -*- coding: utf-8 -*-
"""STEP 11 tests — DocuSeal e-signature (mocked).

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

DocuSeal API is mocked (patch _create_submission). Proves:
  * only an APPROVED document can be sent for signature (Gate 1 holds);
  * sending records the submission id and flips signature_status to 'sent';
  * the webhook handler flips a sent doc to 'signed' (and declined);
  * a webhook for an unknown submission is a safe no-op.
"""

from unittest.mock import patch

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

DSCLIENT = ("odoo.addons.activeblue_familylaw_v2.models.familylaw_docuseal."
            "FamilyLawDocusealClient")


@tagged("post_install", "-at_install", "familylaw", "familylaw_step11")
class TestStep11Docuseal(TransactionCase):

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.attorney = new_test_user(
            cls.env, login="fl_atty11", name="Attorney 11",
            email="atty11@example.com",
            groups="base.group_user,activeblue_familylaw_v2.group_familylaw_attorney",
        )
        cls.partner = cls.env["res.partner"].create({"name": "Sign Client"})
        cls.case = cls.env["familylaw.case"].create({
            "name": "Sign Matter", "client_id": cls.partner.id,
            "case_type": "dissolution_children",
        })
        cls.proc = cls.case.proceeding_ids[0]
        cls.Doc = cls.env["familylaw.document"]

    def _doc(self, **kw):
        vals = {"name": "Engagement Letter", "proceeding_id": self.proc.id,
                "document_type": "correspondence", "source": "manual",
                "signer_email": "client@example.com"}
        vals.update(kw)
        return self.Doc.create(vals)

    def _approve(self, doc):
        doc.action_submit_for_review()
        doc.with_user(self.attorney).action_approve()

    # --- only approved can send ---------------------------------------------
    def test_01_cannot_send_draft(self):
        doc = self._doc()
        with patch(DSCLIENT + "._create_submission",
                   return_value={"id": "S1", "status": "sent"}):
            with self.assertRaises(UserError):
                doc.with_user(self.attorney).action_send_for_signature()
        self.assertEqual(doc.signature_status, "none")

    def test_02_cannot_send_in_review(self):
        doc = self._doc()
        doc.action_submit_for_review()
        with patch(DSCLIENT + "._create_submission",
                   return_value={"id": "S1", "status": "sent"}):
            with self.assertRaises(UserError):
                doc.with_user(self.attorney).action_send_for_signature()

    # --- approved sends -----------------------------------------------------
    def test_03_approved_sends(self):
        doc = self._doc()
        self._approve(doc)
        with patch(DSCLIENT + "._create_submission",
                   return_value={"id": "SUB-123", "status": "sent"}):
            doc.with_user(self.attorney).action_send_for_signature()
        self.assertEqual(doc.signature_status, "sent")
        self.assertEqual(doc.docuseal_submission_id, "SUB-123")

    def test_04_send_requires_signer_email(self):
        doc = self._doc(signer_email=False)
        self._approve(doc)
        with patch(DSCLIENT + "._create_submission",
                   return_value={"id": "S1", "status": "sent"}):
            with self.assertRaises(UserError):
                doc.with_user(self.attorney).action_send_for_signature()

    def test_05_send_requires_attorney(self):
        doc = self._doc()
        self._approve(doc)
        para = new_test_user(
            self.env, login="fl_para11", name="Para 11", email="p11@example.com",
            groups="base.group_user,activeblue_familylaw_v2.group_familylaw_user",
        )
        with patch(DSCLIENT + "._create_submission",
                   return_value={"id": "S1", "status": "sent"}):
            with self.assertRaises(UserError):
                doc.with_user(para).action_send_for_signature()

    # --- webhook handler ----------------------------------------------------
    def test_06_webhook_marks_signed(self):
        doc = self._doc()
        self._approve(doc)
        with patch(DSCLIENT + "._create_submission",
                   return_value={"id": "SUB-9", "status": "sent"}):
            doc.with_user(self.attorney).action_send_for_signature()
        self.Doc._process_signature_event("SUB-9", "completed")
        self.assertEqual(doc.signature_status, "signed")
        self.assertTrue(doc.signed_date)

    def test_07_webhook_declined(self):
        doc = self._doc()
        self._approve(doc)
        with patch(DSCLIENT + "._create_submission",
                   return_value={"id": "SUB-10", "status": "sent"}):
            doc.with_user(self.attorney).action_send_for_signature()
        self.Doc._process_signature_event("SUB-10", "declined")
        self.assertEqual(doc.signature_status, "declined")

    def test_08_webhook_unknown_submission_noop(self):
        # must not raise
        res = self.Doc._process_signature_event("DOES-NOT-EXIST", "completed")
        self.assertFalse(res)

    def test_09_webhook_signed_alias(self):
        doc = self._doc()
        self._approve(doc)
        with patch(DSCLIENT + "._create_submission",
                   return_value={"id": "SUB-11", "status": "sent"}):
            doc.with_user(self.attorney).action_send_for_signature()
        self.Doc._process_signature_event("SUB-11", "signed")
        self.assertEqual(doc.signature_status, "signed")
