# -*- coding: utf-8 -*-
"""STEP 3 — Documents + THE REVIEW GATE (Gate 1).

familylaw.document is every piece of work product on a matter. It is attached to a
PROCEEDING (not directly to the case — see the locked proceeding decision), and it
carries the review-gate state machine:

    ai_draft -> attorney_review -> approved

Plus terminal/outbound states (rejected, filed, sent). The non-negotiable rule
enforced here in code (not policy):

    Nothing can be filed or sent unless it is APPROVED, and only a licensed
    attorney can approve.

This is Gate 1. Step 7 adds the second gate (no unverified citation in a filing) on
top of the same outbound guard.
"""

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

ATTORNEY_GROUP = "activeblue_familylaw_v2.group_familylaw_attorney"


class FamilyLawDocument(models.Model):
    _name = "familylaw.document"
    _description = "Case Document (review-gated)"
    _inherit = ["mail.thread", "mail.activity.mixin"]
    _order = "create_date desc"

    name = fields.Char(string="Title", required=True, tracking=True)
    proceeding_id = fields.Many2one(
        "familylaw.proceeding",
        string="Proceeding",
        required=True,
        ondelete="cascade",
        index=True,
        tracking=True,
        help="Documents attach to a proceeding, not directly to the case.",
    )
    case_id = fields.Many2one(
        "familylaw.case",
        string="Matter",
        related="proceeding_id.case_id",
        store=True,
        index=True,
    )
    document_type = fields.Selection(
        selection=[
            ("pleading", "Pleading / Motion"),
            ("form", "Florida Supreme Court Form"),
            ("affidavit", "Affidavit"),
            ("order", "Proposed Order"),
            ("correspondence", "Correspondence"),
            ("notice", "Notice"),
            ("other", "Other"),
        ],
        string="Type",
        required=True,
        default="pleading",
        tracking=True,
    )
    source = fields.Selection(
        selection=[
            ("ai", "AI-Assembled"),
            ("manual", "Manually Drafted"),
            ("uploaded", "Uploaded"),
        ],
        string="Source",
        required=True,
        default="manual",
        tracking=True,
        help="AI-assembled documents are born in the ai_draft state and must pass "
             "attorney review before they can be filed or sent.",
    )
    body = fields.Html(string="Body", sanitize=True)
    privilege = fields.Selection(
        selection=[
            ("none", "Not Privileged"),
            ("attorney_client", "Attorney-Client Privileged"),
            ("work_product", "Work Product"),
        ],
        string="Privilege",
        default="work_product",
    )

    state = fields.Selection(
        selection=[
            ("ai_draft", "Draft"),
            ("attorney_review", "In Attorney Review"),
            ("approved", "Approved"),
            ("rejected", "Rejected"),
            ("filed", "Filed"),
            ("sent", "Sent"),
        ],
        string="Status",
        default="ai_draft",
        required=True,
        copy=False,
        tracking=True,
    )
    approved_by_id = fields.Many2one(
        "res.users", string="Approved By", readonly=True, copy=False, tracking=True,
    )
    approved_date = fields.Datetime(
        string="Approved On", readonly=True, copy=False, tracking=True,
    )
    citation_ids = fields.One2many(
        "familylaw.citation", "document_id", string="Citations",
    )
    unverified_citation_count = fields.Integer(
        compute="_compute_unverified_citation_count",
        string="Unverified Citations",
    )

    @api.depends("citation_ids.status")
    def _compute_unverified_citation_count(self):
        for doc in self:
            doc.unverified_citation_count = len(
                doc.citation_ids.filtered(lambda c: c.status != "verified")
            )

    # --- gate helpers -------------------------------------------------------
    def _ensure_attorney(self):
        if not self.env.user.has_group(ATTORNEY_GROUP):
            raise UserError(
                _("Only a licensed attorney may approve, reject, file, or send a "
                  "document. This is the review gate — it cannot be bypassed.")
            )

    def _ensure_approved(self):
        """Gate 1: refuse any outbound action unless the document is approved."""
        not_approved = self.filtered(lambda d: d.state not in ("approved",))
        if not_approved:
            raise UserError(
                _("Document '%(name)s' is not approved (status: %(state)s). "
                  "An attorney must approve it before it can be filed or sent. "
                  "Nothing reaches a clerk, court, or client unapproved.",
                  name=not_approved[0].name,
                  state=not_approved[0].state)
            )

    def _ensure_citations_verified(self):
        """Gate 2: refuse filing/sending if ANY citation is not verified.

        Born-unverified, fail-closed verification (Step 7) makes an AI-hallucinated
        cite mechanically unable to reach a filing."""
        for doc in self:
            bad = doc.citation_ids.filtered(lambda c: c.status != "verified")
            if bad:
                raise UserError(
                    _("Document '%(name)s' has %(n)d unverified citation(s). Every "
                      "citation must be verified against a real reporter before the "
                      "document can be filed or sent (the citation gate). Unverified: "
                      "%(list)s",
                      name=doc.name, n=len(bad),
                      list="; ".join(bad.mapped("citation_text")))
                )

    def action_verify_citations(self):
        """Run the fail-closed verifier over every citation on this document."""
        for doc in self:
            doc.citation_ids.action_verify()
        return True

    def action_request_filing(self):
        """Validate BOTH gates and flag the document ready for filing prep.
        Available to staff to assemble; the actual filing (action_mark_filed) stays
        attorney-only."""
        self._ensure_approved()
        self._ensure_citations_verified()
        for doc in self:
            doc.message_post(
                body=_("Filing requested — review gate and citation gate both passed.")
            )
        return True

    # --- review workflow ----------------------------------------------------
    def action_submit_for_review(self):
        for doc in self:
            if doc.state not in ("ai_draft", "rejected"):
                raise UserError(
                    _("Only a draft or rejected document can be submitted for review.")
                )
            doc.state = "attorney_review"
            doc.message_post(body=_("Submitted for attorney review."))
        return True

    def action_approve(self):
        self._ensure_attorney()
        for doc in self:
            if doc.state != "attorney_review":
                raise UserError(
                    _("Only a document in attorney review can be approved.")
                )
            doc.write({
                "state": "approved",
                "approved_by_id": self.env.user.id,
                "approved_date": fields.Datetime.now(),
            })
            doc.message_post(body=_("Approved by %s.") % self.env.user.name)
        return True

    def action_reject(self):
        self._ensure_attorney()
        for doc in self:
            if doc.state not in ("attorney_review", "approved"):
                raise UserError(
                    _("Only a document in review or approved can be rejected.")
                )
            doc.write({
                "state": "rejected",
                "approved_by_id": False,
                "approved_date": False,
            })
            doc.message_post(body=_("Rejected by %s.") % self.env.user.name)
        return True

    def action_reset_to_draft(self):
        for doc in self:
            doc.write({
                "state": "ai_draft",
                "approved_by_id": False,
                "approved_date": False,
            })
            doc.message_post(body=_("Reset to draft."))
        return True

    # --- AI drafting agent (Step 6) -----------------------------------------
    @api.model
    def ai_assemble(self, proceeding, document_type, instruction, *,
                    name=None, confidential=True):
        """Single-shot AI assembly of a draft document.

        Produces a document BORN IN ai_draft (never auto-approved) and records the
        proposed citations BORN UNVERIFIED. The legal content is NOT authoritative
        until an attorney reviews and approves it (Gate 1) and every citation is
        verified (Gate 2, Step 7). Returns the new document.

        The Claude call is routed + logged through familylaw.ai.client (mocked in
        tests). In production this method is wrapped in queue_job (with_delay).
        """
        proceeding = proceeding if hasattr(proceeding, "id") else \
            self.env["familylaw.proceeding"].browse(proceeding)
        system = (
            "You are a paralegal assistant assembling a DRAFT for licensed-attorney "
            "review. You do not give legal advice or final opinions. Surface "
            "authority for the attorney to verify; never assert a citation is good "
            "law yourself."
        )
        messages = [{"role": "user", "content": instruction}]
        result, task = self.env["familylaw.ai.client"].generate(
            "draft_document", messages, system=system,
            case=proceeding.case_id, proceeding=proceeding,
            confidential=confidential,
            name=_("Draft: %s") % (name or document_type),
        )

        doc = self.create({
            "name": name or _("AI Draft — %s") % document_type,
            "proceeding_id": proceeding.id,
            "document_type": document_type,
            "source": "ai",
            "state": "ai_draft",
            "body": result.get("text") or "",
        })
        task.document_id = doc.id

        # Citations proposed by the AI are born UNVERIFIED.
        Cit = self.env["familylaw.citation"]
        for c in (result.get("citations") or []):
            Cit.create({
                "document_id": doc.id,
                "citation_text": c.get("citation_text") or c.get("text") or _("(unparsed)"),
                "case_name": c.get("case_name"),
                "reporter": c.get("reporter"),
                "court": c.get("court"),
                "year": c.get("year"),
                "proposition": c.get("proposition"),
                "status": "unverified",
                "source_ai_task_id": task.id,
            })
        return doc

    # --- outbound actions (Gate 1 enforced) ---------------------------------
    def action_mark_filed(self):
        self._ensure_attorney()
        self._ensure_approved()           # Gate 1
        self._ensure_citations_verified()  # Gate 2
        for doc in self:
            doc.state = "filed"
            doc.message_post(body=_("Marked as filed by %s.") % self.env.user.name)
        return True

    def action_mark_sent(self):
        self._ensure_attorney()
        self._ensure_approved()           # Gate 1
        self._ensure_citations_verified()  # Gate 2
        for doc in self:
            doc.state = "sent"
            doc.message_post(body=_("Marked as sent by %s.") % self.env.user.name)
        return True
