"""MCP tools for the missing-precedents log.

When a researcher (or chair) finds a citation in a party brief that
isn't yet in the precedent_library, they record it here so:

1. The gap is visible in the UI (the chair can see all open citations
   that need to be uploaded).
2. The writer agent doesn't try to use a precedent that isn't in the
   corpus — it knows the gap is being tracked.
3. The chair has a clean closing workflow: upload the actual decision
   via the precedent library / internal-decisions, then link it here.

Three tools:
- ``missing_precedent_create`` — log a new gap (researcher / chair).
- ``missing_precedent_list`` — list open gaps (optionally filtered).
- ``missing_precedent_close`` — close a gap (chair workflow).
"""

from __future__ import annotations

from uuid import UUID

from legal_mcp.services import db
from legal_mcp.tools.envelope import err as _err, ok as _ok  # GAP-48: SSoT envelope


async def _resolve_case_id(case_number: str) -> UUID | None:
    """Translate a human case_number (e.g. '1017-03-26') to a UUID."""
    if not case_number or not case_number.strip():
        return None
    row = await db.get_case_by_number(case_number.strip())
    if not row:
        return None
    return UUID(row["id"])


async def missing_precedent_create(
    citation: str,
    case_number: str = "",
    cited_in_document_id: str = "",
    cited_by_party: str = "unknown",
    cited_by_party_name: str = "",
    legal_topic: str = "",
    legal_issue: str = "",
    claim_quote: str = "",
    case_name: str = "",
    notes: str = "",
) -> str:
    """תיעוד פסיקה שצוטטה אך אינה בקורפוס. הסוכן יוצר רשומה כשהוא מזהה ציטוט
    שלא ניתן לאמת מול הקורפוס; היו"ר יסגור אותה לאחר העלאת המסמך.

    Args:
        citation: מראה המקום המלא (חובה).
        case_number: מספר תיק הערר שבו צוטטה הפסיקה (לדוגמה '1017-03-26').
        cited_in_document_id: UUID של המסמך שבו הציטוט מופיע (אופציונלי).
        cited_by_party: appellant / respondent / committee / permit_applicant / unknown.
        cited_by_party_name: שם הצד (כדי שיהיה ברור מי ציטט).
        legal_topic: נושא משפטי קצר (לדוגמה "זכות עמידה").
        legal_issue: שאלה משפטית מפורטת.
        claim_quote: הציטוט בכתב הטענות.
        case_name: שם קצר של פסק הדין החסר.
        notes: הערות חופשיות.

    Returns: JSON של הרשומה שנוצרה (כולל id) או error.
    """
    if not citation.strip():
        return _err("citation חובה")

    case_id = None
    if case_number:
        case_id = await _resolve_case_id(case_number)
        if case_id is None:
            return _err(f"תיק לא נמצא: {case_number}")

    doc_uuid: UUID | None = None
    if cited_in_document_id.strip():
        try:
            doc_uuid = UUID(cited_in_document_id.strip())
        except ValueError:
            return _err("cited_in_document_id לא תקין")

    party = cited_by_party.strip() or "unknown"
    if party not in db.ALLOWED_MP_PARTIES:
        return _err(
            f"cited_by_party לא תקין. ערכים תקפים: "
            f"{', '.join(sorted(db.ALLOWED_MP_PARTIES))}"
        )

    # Deduplication: if a row already exists for the same citation in
    # the same case, return that one rather than creating a duplicate.
    existing = await db.find_missing_precedent_by_citation(
        citation=citation.strip(),
        case_id=case_id,
    )
    if existing:
        return _ok({**existing, "_duplicate": True})

    try:
        row = await db.create_missing_precedent(
            citation=citation.strip(),
            case_name=case_name.strip() or None,
            cited_in_case_id=case_id,
            cited_in_document_id=doc_uuid,
            cited_by_party=party,
            cited_by_party_name=cited_by_party_name.strip() or None,
            legal_topic=legal_topic.strip() or None,
            legal_issue=legal_issue.strip() or None,
            claim_quote=claim_quote.strip() or None,
            notes=notes.strip() or None,
        )
    except Exception as e:
        return _err(str(e))
    return _ok(row)


async def missing_precedent_list(
    case_number: str = "",
    status: str = "open",
    legal_topic: str = "",
    limit: int = 50,
) -> str:
    """רשימת פסיקות חסרות. ברירת מחדל = פתוחות בלבד.

    Args:
        case_number: סינון לפי תיק הערר שבו צוטטו.
        status: open / uploaded / closed / irrelevant (ריק = הכל).
        legal_topic: סינון לפי נושא משפטי (substring).
        limit: מספר תוצאות מקסימלי.

    Returns: JSON עם רשימת רשומות + linked_case_law_number אם נסגרו.
    """
    case_id = None
    if case_number:
        case_id = await _resolve_case_id(case_number)
        if case_id is None:
            return _err(f"תיק לא נמצא: {case_number}")

    s = status.strip() or None
    if s and s not in db.ALLOWED_MP_STATUS:
        return _err(
            f"status לא תקין. ערכים תקפים: "
            f"{', '.join(sorted(db.ALLOWED_MP_STATUS))}"
        )
    try:
        rows = await db.list_missing_precedents(
            status=s,
            case_id=case_id,
            legal_topic=legal_topic.strip() or None,
            limit=max(1, min(int(limit), 500)),
        )
    except Exception as e:
        return _err(str(e))
    return _ok({"items": rows, "count": len(rows)})


async def missing_precedent_close(
    id: str,
    linked_case_law_id: str = "",
    notes: str = "",
    status: str = "closed",
) -> str:
    """סגירת רשומת פסיקה חסרה. ברירת מחדל = 'closed' + קישור ל-case_law.

    Args:
        id: UUID של הרשומה.
        linked_case_law_id: UUID של הפסיקה שהועלתה ב-precedent_library / internal_decisions.
        notes: הערות סגירה (לדוגמה "אינו רלוונטי" ל-status='irrelevant').
        status: closed / uploaded / irrelevant.

    Returns: JSON של הרשומה המעודכנת.
    """
    try:
        mp_id = UUID(id.strip())
    except ValueError:
        return _err("id לא תקין")

    cl_uuid: UUID | None = None
    if linked_case_law_id.strip():
        try:
            cl_uuid = UUID(linked_case_law_id.strip())
        except ValueError:
            return _err("linked_case_law_id לא תקין")

    status_clean = status.strip() or "closed"
    if status_clean not in db.ALLOWED_MP_STATUS:
        return _err(
            f"status לא תקין. ערכים תקפים: "
            f"{', '.join(sorted(db.ALLOWED_MP_STATUS))}"
        )

    try:
        row = await db.close_missing_precedent(
            mp_id=mp_id,
            linked_case_law_id=cl_uuid,
            notes=notes.strip() or None,
            status=status_clean,
        )
    except Exception as e:
        return _err(str(e))
    if row is None:
        return _err("רשומה לא נמצאה")
    return _ok(row)
