# -*- coding: utf-8 -*-
"""STEP 11 — DocuSeal e-signature for CLIENT-FACING documents.

Court filings use the /s/ convention via the FL E-Filing Portal — NOT DocuSeal.
DocuSeal is only for client-facing docs (engagement letters, consents, etc.).

Two material caveats (design facts, surfaced not buried):
  * the API/embedding needed for this integration requires DocuSeal PRO (~$200/yr);
    the free tier signs but does not expose the programmatic API.
  * the DocuSeal signing host must be INTERNET-FACING, unlike the rest of the
    NetBird-internal stack — so it must be isolated and hardened (its Postgres not
    exposed, audit trail backed up).

Only an APPROVED document can be sent for signature — the review gate (Gate 1) holds
here too. The real API call lives only in _create_submission (the mock point).
"""

import logging

from odoo import api, fields, models, _
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)

PARAM_URL = "familylaw.docuseal_url"
PARAM_KEY = "familylaw.docuseal_api_key"
PARAM_TEMPLATE = "familylaw.docuseal_template_id"


class FamilyLawDocusealClient(models.AbstractModel):
    _name = "familylaw.docuseal.client"
    _description = "DocuSeal API client"

    def _icp(self):
        return self.env["ir.config_parameter"].sudo()

    def _create_submission(self, document, signer_email):
        """Create a DocuSeal submission (Pro API). MOCK THIS IN TESTS.
        Returns a normalised dict: {"id": <submission id>, "status": "sent"}."""
        import requests
        base = self._icp().get_param(PARAM_URL)
        key = self._icp().get_param(PARAM_KEY)
        if not base or not key:
            raise UserError(_("DocuSeal is not configured (URL / API key)."))
        resp = requests.post(
            base.rstrip("/") + "/api/submissions",
            headers={"X-Auth-Token": key, "content-type": "application/json"},
            json={
                "template_id": self._icp().get_param(PARAM_TEMPLATE),
                "send_email": True,
                "submitters": [{"email": signer_email, "role": "Client"}],
            },
            timeout=60,
        )
        resp.raise_for_status()
        data = resp.json()
        sub_id = (data[0]["submission_id"] if isinstance(data, list) and data
                  else data.get("id"))
        return {"id": str(sub_id), "status": "sent"}

    def send(self, document, signer_email):
        res = self._create_submission(document, signer_email)
        document.write({
            "docuseal_submission_id": res["id"],
            "signature_status": "sent",
            "signer_email": signer_email,
        })
        document.message_post(
            body=_("Sent to %s for e-signature (DocuSeal submission %s).")
            % (signer_email, res["id"])
        )
        return res


class FamilyLawDocumentSignature(models.Model):
    _inherit = "familylaw.document"

    signature_status = fields.Selection(
        selection=[
            ("none", "Not Sent"),
            ("sent", "Sent for Signature"),
            ("signed", "Signed"),
            ("declined", "Declined"),
        ],
        default="none",
        copy=False,
        tracking=True,
    )
    docuseal_submission_id = fields.Char(readonly=True, copy=False)
    signer_email = fields.Char(string="Signer Email")
    signed_date = fields.Datetime(readonly=True, copy=False)

    def action_send_for_signature(self):
        """Send a CLIENT-FACING approved document for e-signature. Attorney-only;
        requires approval (Gate 1)."""
        self._ensure_attorney()
        self._ensure_approved()
        for doc in self:
            if not doc.signer_email:
                raise UserError(
                    _("Set the signer's email before sending '%s' for signature.")
                    % doc.name
                )
            self.env["familylaw.docuseal.client"].send(doc, doc.signer_email)
        return True

    @api.model
    def _process_signature_event(self, submission_id, status):
        """Webhook handler core: flip a document's signature status. Idempotent;
        unknown submissions are a no-op (never raises for stray events)."""
        if not submission_id:
            return False
        doc = self.search(
            [("docuseal_submission_id", "=", str(submission_id))], limit=1)
        if not doc:
            _logger.info("DocuSeal event for unknown submission %s — ignored.",
                         submission_id)
            return False
        status = (status or "").lower()
        if status in ("completed", "signed"):
            doc.write({"signature_status": "signed",
                       "signed_date": fields.Datetime.now()})
            doc.message_post(body=_("E-signature COMPLETED (DocuSeal)."))
        elif status in ("declined", "cancelled", "canceled", "expired"):
            doc.write({"signature_status": "declined"})
            doc.message_post(body=_("E-signature declined/cancelled (DocuSeal)."))
        return doc
