# Familiar - Self-Hosted AI Companion Platform
# Copyright (c) 2026 George Scott Foley
# ORCID: 0009-0006-4957-0540
# Email: Georgescottfoley@proton.me
# Licensed under the MIT License - see LICENSE file for details

"""
Documents Skill

Generate professional documents from structured content.
Thank-you letters, board reports, grant narratives, receipts, newsletters.

Output stored in ~/.familiar/documents/
Templates stored in ~/.familiar/templates/

Dependencies:
  - python-docx (DOCX generation)
  - weasyprint (PDF generation from HTML/CSS) -- optional, falls back to
    basic text-based PDF via reportlab or text file

Both are pip-installable with no system dependencies.
"""

import json
import logging
import re
from datetime import datetime
from pathlib import Path
from typing import Optional

try:
    from familiar.core.utils import generate_id
except ImportError:
    generate_id = None

logger = logging.getLogger(__name__)

DOCUMENTS_DIR = Path.home() / ".familiar" / "documents"
TEMPLATES_DIR = Path.home() / ".familiar" / "templates"

# Try to import document generation libraries (auto-install on first use)
DOCX_AVAILABLE = False
WEASYPRINT_AVAILABLE = False

try:
    from docx import Document as DocxDocument
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    from docx.shared import Inches, Pt

    DOCX_AVAILABLE = True
except ImportError:
    pass

try:
    import weasyprint

    WEASYPRINT_AVAILABLE = True
except ImportError:
    pass


def _ensure_docx():
    global DOCX_AVAILABLE, DocxDocument, WD_ALIGN_PARAGRAPH, Inches, Pt
    if DOCX_AVAILABLE:
        return True
    from familiar.core.deps import DOCX_PACKAGES, ensure_packages

    ok, _ = ensure_packages(DOCX_PACKAGES)
    if ok:
        from docx import Document as _Doc
        from docx.enum.text import WD_ALIGN_PARAGRAPH as _WD
        from docx.shared import Inches as _In
        from docx.shared import Pt as _Pt

        globals().update(
            {"DocxDocument": _Doc, "WD_ALIGN_PARAGRAPH": _WD, "Inches": _In, "Pt": _Pt}
        )
        DOCX_AVAILABLE = True
    return DOCX_AVAILABLE


def _ensure_weasyprint():
    global WEASYPRINT_AVAILABLE, weasyprint
    if WEASYPRINT_AVAILABLE:
        return True
    from familiar.core.deps import WEASYPRINT_PACKAGES, ensure_packages

    ok, _ = ensure_packages(WEASYPRINT_PACKAGES)
    if ok:
        import weasyprint as _wp

        globals()["weasyprint"] = _wp
        WEASYPRINT_AVAILABLE = True
    return WEASYPRINT_AVAILABLE


def _generate_id() -> str:
    if generate_id:
        return generate_id()
    import secrets

    return secrets.token_hex(4)


def _ensure_dirs():
    """Ensure output and template directories exist."""
    DOCUMENTS_DIR.mkdir(parents=True, exist_ok=True)
    TEMPLATES_DIR.mkdir(parents=True, exist_ok=True)


def _get_org_config() -> dict:
    """Load organization config for letterhead/receipt generation."""
    config_file = Path.home() / ".familiar" / "config.yaml"
    org = {
        "name": "",
        "address": "",
        "ein": "",
        "phone": "",
        "email": "",
        "website": "",
    }
    if config_file.exists():
        try:
            import yaml

            with open(config_file) as f:
                data = yaml.safe_load(f) or {}
            org_data = data.get("organization", {})
            org.update({k: v for k, v in org_data.items() if k in org})
        except Exception:
            pass
    return org


def _output_path(name: str, ext: str) -> Path:
    """Generate a timestamped output path."""
    _ensure_dirs()
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    safe_name = re.sub(r"[^\w\-]", "_", name)[:50]
    return DOCUMENTS_DIR / f"{safe_name}_{timestamp}.{ext}"


def _build_docx(
    title: str,
    sections: list,
    letterhead: bool = False,
    date_str: str = "",
    recipient: str = "",
    signature: str = "",
    subject: str = "",
) -> Path:
    """Build a DOCX document from structured content."""
    if not _ensure_docx():
        # Fallback: write as markdown
        path = _output_path(title, "md")
        lines = [f"# {title}\n"]
        if date_str:
            lines.append(f"**Date:** {date_str}\n")
        if recipient:
            lines.append(f"**To:** {recipient}\n")
        lines.append("")
        for section in sections:
            if isinstance(section, dict):
                if section.get("heading"):
                    lines.append(f"## {section['heading']}\n")
                if section.get("body"):
                    lines.append(section["body"] + "\n")
            elif isinstance(section, str):
                lines.append(section + "\n")
        if signature:
            lines.append(f"\n---\n{signature}")
        path.write_text("\n".join(lines), encoding="utf-8")
        return path

    doc = DocxDocument()

    # Set default font
    style = doc.styles["Normal"]
    font = style.font
    font.name = "Calibri"
    font.size = Pt(11)

    # Letterhead
    if letterhead:
        org = _get_org_config()
        logo_path = TEMPLATES_DIR / "letterhead.png"
        if logo_path.exists():
            try:
                header = doc.sections[0].header
                header_para = header.paragraphs[0]
                run = header_para.add_run()
                run.add_picture(str(logo_path), width=Inches(1.5))
            except Exception as e:
                logger.warning(f"Could not add letterhead logo: {e}")
        if org["name"]:
            header = doc.sections[0].header
            p = header.add_paragraph()
            p.alignment = WD_ALIGN_PARAGRAPH.CENTER
            run = p.add_run(org["name"])
            run.bold = True
            run.font.size = Pt(14)
            if org["address"]:
                p2 = header.add_paragraph()
                p2.alignment = WD_ALIGN_PARAGRAPH.CENTER
                p2.add_run(org["address"]).font.size = Pt(9)
            contact_parts = []
            if org["phone"]:
                contact_parts.append(org["phone"])
            if org["email"]:
                contact_parts.append(org["email"])
            if org["website"]:
                contact_parts.append(org["website"])
            if contact_parts:
                p3 = header.add_paragraph()
                p3.alignment = WD_ALIGN_PARAGRAPH.CENTER
                p3.add_run(" | ".join(contact_parts)).font.size = Pt(9)

    # Date
    if date_str:
        p = doc.add_paragraph()
        p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
        p.add_run(date_str)

    # Recipient block
    if recipient:
        doc.add_paragraph("")
        doc.add_paragraph(recipient)
        doc.add_paragraph("")

    # Title
    if title:
        doc.add_heading(title, level=1)

    # Sections
    for section in sections:
        if isinstance(section, dict):
            if section.get("heading"):
                doc.add_heading(section["heading"], level=2)
            if section.get("body"):
                for para_text in section["body"].split("\n\n"):
                    if para_text.strip():
                        doc.add_paragraph(para_text.strip())
            if section.get("table"):
                _add_table(doc, section["table"])
        elif isinstance(section, str):
            for para_text in section.split("\n\n"):
                if para_text.strip():
                    doc.add_paragraph(para_text.strip())

    # Signature block
    if signature:
        doc.add_paragraph("")
        doc.add_paragraph("")
        for line in signature.split("\n"):
            doc.add_paragraph(line)

    path = _output_path(title, "docx")
    doc.save(str(path))
    return path


def _add_table(doc, table_data: dict):
    """Add a table to a docx document."""
    headers = table_data.get("headers", [])
    rows = table_data.get("rows", [])

    if not headers and not rows:
        return

    num_cols = len(headers) if headers else (len(rows[0]) if rows else 0)
    table = doc.add_table(rows=1 if headers else 0, cols=num_cols)
    table.style = "Table Grid"

    if headers:
        for i, header in enumerate(headers):
            cell = table.rows[0].cells[i]
            cell.text = str(header)
            for paragraph in cell.paragraphs:
                for run in paragraph.runs:
                    run.bold = True

    for row_data in rows:
        row = table.add_row()
        for i, cell_val in enumerate(row_data):
            if i < num_cols:
                row.cells[i].text = str(cell_val)


def _build_html_pdf(
    title: str,
    sections: list,
    letterhead: bool = False,
    date_str: str = "",
    recipient: str = "",
    signature: str = "",
    subject: str = "",
) -> Optional[Path]:
    """Build PDF from HTML using weasyprint. Returns None if unavailable."""
    if not _ensure_weasyprint():
        return None

    org = _get_org_config() if letterhead else {}

    html_parts = [
        '<!DOCTYPE html><html><head><meta charset="utf-8">',
        "<style>",
        "body { font-family: Calibri, Arial, sans-serif; font-size: 11pt; margin: 1in; line-height: 1.5; }",
        "h1 { font-size: 16pt; margin-top: 0.5em; }",
        "h2 { font-size: 13pt; margin-top: 1em; }",
        ".letterhead { text-align: center; margin-bottom: 2em; border-bottom: 1px solid #ccc; padding-bottom: 1em; }",
        ".letterhead .org-name { font-size: 18pt; font-weight: bold; }",
        ".letterhead .org-detail { font-size: 9pt; color: #555; }",
        ".date { text-align: right; margin-bottom: 1em; }",
        ".recipient { margin-bottom: 1.5em; }",
        ".signature { margin-top: 3em; }",
        "table { border-collapse: collapse; width: 100%; margin: 1em 0; }",
        "th, td { border: 1px solid #ccc; padding: 6px 10px; text-align: left; }",
        "th { background: #f0f0f0; font-weight: bold; }",
        "</style></head><body>",
    ]

    if letterhead and org.get("name"):
        html_parts.append('<div class="letterhead">')
        logo_path = TEMPLATES_DIR / "letterhead.png"
        if logo_path.exists():
            import base64

            logo_data = base64.b64encode(logo_path.read_bytes()).decode()
            html_parts.append(
                f'<img src="data:image/png;base64,{logo_data}" style="max-height:80px;"><br>'
            )
        html_parts.append(f'<div class="org-name">{_html_escape(org["name"])}</div>')
        if org.get("address"):
            html_parts.append(f'<div class="org-detail">{_html_escape(org["address"])}</div>')
        contact = " | ".join(filter(None, [org.get("phone"), org.get("email"), org.get("website")]))
        if contact:
            html_parts.append(f'<div class="org-detail">{_html_escape(contact)}</div>')
        html_parts.append("</div>")

    if date_str:
        html_parts.append(f'<div class="date">{_html_escape(date_str)}</div>')
    if recipient:
        html_parts.append(
            f'<div class="recipient">{_html_escape(recipient).replace(chr(10), "<br>")}</div>'
        )
    if title:
        html_parts.append(f"<h1>{_html_escape(title)}</h1>")

    for section in sections:
        if isinstance(section, dict):
            if section.get("heading"):
                html_parts.append(f"<h2>{_html_escape(section['heading'])}</h2>")
            if section.get("body"):
                for para in section["body"].split("\n\n"):
                    if para.strip():
                        html_parts.append(f"<p>{_html_escape(para.strip())}</p>")
            if section.get("table"):
                html_parts.append(_table_to_html(section["table"]))
        elif isinstance(section, str):
            for para in section.split("\n\n"):
                if para.strip():
                    html_parts.append(f"<p>{_html_escape(para.strip())}</p>")

    if signature:
        html_parts.append('<div class="signature">')
        for line in signature.split("\n"):
            html_parts.append(f"{_html_escape(line)}<br>")
        html_parts.append("</div>")

    html_parts.append("</body></html>")
    html_content = "\n".join(html_parts)

    path = _output_path(title, "pdf")
    weasyprint.HTML(string=html_content).write_pdf(str(path))
    return path


def _html_escape(text: str) -> str:
    """Basic HTML escaping."""
    return (
        text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace('"', "&quot;")
    )


def _table_to_html(table_data: dict) -> str:
    """Convert table dict to HTML table."""
    headers = table_data.get("headers", [])
    rows = table_data.get("rows", [])
    parts = ["<table>"]
    if headers:
        parts.append(
            "<tr>" + "".join(f"<th>{_html_escape(str(h))}</th>" for h in headers) + "</tr>"
        )
    for row in rows:
        parts.append("<tr>" + "".join(f"<td>{_html_escape(str(c))}</td>" for c in row) + "</tr>")
    parts.append("</table>")
    return "\n".join(parts)


# === Tool Handlers ===


def create_document(data: dict) -> str:
    """Generate a DOCX or PDF from structured content."""
    title = data.get("title", "Untitled Document").strip()
    fmt = data.get("format", "docx").lower()
    sections = data.get("sections", [])
    letterhead = data.get("letterhead", False)

    if not sections:
        body = data.get("body", "")
        if body:
            sections = [body]
        else:
            return "Please provide sections or body content."

    if fmt == "pdf":
        path = _build_html_pdf(title, sections, letterhead=letterhead)
        if path:
            return f"✅ Document created: {path}"
        # Fallback to docx if PDF generation unavailable
        logger.info("PDF generation unavailable, falling back to DOCX")
        fmt = "docx"

    path = _build_docx(title, sections, letterhead=letterhead)
    return f"✅ Document created: {path}"


def create_letter(data: dict) -> str:
    """Generate a formal letter with letterhead, date, recipient, body, signature block."""
    recipient = data.get("recipient", "").strip()
    subject = data.get("subject", "Letter").strip()
    body = data.get("body", "").strip()
    signature = data.get("signature", "").strip()
    fmt = data.get("format", "docx").lower()

    if not body:
        return "Please provide the letter body."

    date_str = data.get("date", datetime.now().strftime("%B %d, %Y"))
    sections = [body]

    if fmt == "pdf":
        path = _build_html_pdf(
            title="",  # Letters typically don't have a title heading
            sections=sections,
            letterhead=True,
            date_str=date_str,
            recipient=recipient,
            signature=signature,
            subject=subject,
        )
        if path:
            return f"✅ Letter created: {path}"
        fmt = "docx"

    path = _build_docx(
        title="",
        sections=sections,
        letterhead=True,
        date_str=date_str,
        recipient=recipient,
        signature=signature,
        subject=subject,
    )
    return f"✅ Letter created: {path}"


def create_report(data: dict) -> str:
    """Generate a formatted report with headings, tables, and optional TOC."""
    title = data.get("title", "Report").strip()
    sections = data.get("sections", [])
    fmt = data.get("format", "docx").lower()
    letterhead = data.get("letterhead", False)

    if not sections:
        return "Please provide report sections. Each section should have a 'heading' and 'body'."

    if fmt == "pdf":
        path = _build_html_pdf(
            title, sections, letterhead=letterhead, date_str=datetime.now().strftime("%B %d, %Y")
        )
        if path:
            return f"✅ Report created: {path}"
        fmt = "docx"

    path = _build_docx(
        title, sections, letterhead=letterhead, date_str=datetime.now().strftime("%B %d, %Y")
    )
    return f"✅ Report created: {path}"


def create_receipt(data: dict) -> str:
    """Generate an IRS-compliant donation receipt / tax acknowledgment."""
    donor_name = data.get("donor_name", "").strip()
    amount = data.get("amount")
    date_of_gift = data.get("date_of_gift", datetime.now().strftime("%B %d, %Y"))
    description = data.get("description", "Cash/check donation")
    fmt = data.get("format", "pdf").lower()

    if not donor_name or not amount:
        return "Please provide donor_name and amount."

    org = _get_org_config()
    org_name = org.get("name", "[Organization Name]")
    ein = org.get("ein", "[EIN]")

    sections = [
        {
            "heading": "Donation Receipt",
            "body": (
                f"This letter acknowledges that {donor_name} made a charitable contribution "
                f"to {org_name} (EIN: {ein}) in the amount of ${float(amount):,.2f}.\n\n"
                f"Date of Contribution: {date_of_gift}\n"
                f"Description: {description}\n\n"
                f"No goods or services were provided in exchange for this contribution, "
                f"unless otherwise noted above.\n\n"
                f"This receipt is provided for tax purposes. {org_name} is a tax-exempt "
                f"organization under Section 501(c)(3) of the Internal Revenue Code. "
                f"Contributions are deductible to the extent allowed by law.\n\n"
                f"Please retain this receipt for your tax records."
            ),
        }
    ]

    signature = f"Sincerely,\n\n\n{org_name}\nAuthorized Representative"

    if fmt == "pdf":
        path = _build_html_pdf(
            title="",
            sections=sections,
            letterhead=True,
            date_str=datetime.now().strftime("%B %d, %Y"),
            recipient=donor_name,
            signature=signature,
        )
        if path:
            return f"✅ Receipt created: {path}"
        fmt = "docx"

    path = _build_docx(
        title="",
        sections=sections,
        letterhead=True,
        date_str=datetime.now().strftime("%B %d, %Y"),
        recipient=donor_name,
        signature=signature,
    )
    return f"✅ Receipt created: {path}"


def list_templates(data: dict) -> str:
    """List available document templates."""
    _ensure_dirs()

    # Built-in templates
    builtins = [
        {"name": "letter", "description": "Formal letter with letterhead and signature block"},
        {"name": "report", "description": "Formatted report with headings and optional tables"},
        {"name": "receipt", "description": "IRS-compliant donation receipt / tax acknowledgment"},
        {"name": "memo", "description": "Internal memo format"},
        {"name": "newsletter", "description": "Newsletter with sections and optional images"},
        {"name": "agenda", "description": "Meeting agenda with time slots and topics"},
    ]

    # User templates from filesystem
    user_templates = []
    if TEMPLATES_DIR.exists():
        for f in TEMPLATES_DIR.glob("*.json"):
            try:
                with open(f) as fh:
                    tmpl = json.load(fh)
                user_templates.append(
                    {"name": f.stem, "description": tmpl.get("description", "Custom template")}
                )
            except (json.JSONDecodeError, IOError):
                pass

    lines = ["📄 Document Templates:\n"]
    lines.append("  Built-in:")
    for t in builtins:
        lines.append(f"    • {t['name']}: {t['description']}")

    if user_templates:
        lines.append("\n  Custom:")
        for t in user_templates:
            lines.append(f"    • {t['name']}: {t['description']}")
    else:
        lines.append("\n  No custom templates. Add JSON templates to ~/.familiar/templates/")

    # Check for letterhead
    logo_path = TEMPLATES_DIR / "letterhead.png"
    if logo_path.exists():
        lines.append(f"\n  ✅ Letterhead logo found: {logo_path}")
    else:
        lines.append(f"\n  ⚠️  No letterhead logo. Place image at {logo_path}")

    return "\n".join(lines)


def fill_template(data: dict) -> str:
    """Fill a template with provided data (mail merge style)."""
    template_name = data.get("template", "").strip()
    fields = data.get("fields", {})
    fmt = data.get("format", "docx").lower()

    if not template_name:
        return "Please provide a template name."

    # Check for custom template file
    template_file = TEMPLATES_DIR / f"{template_name}.json"
    if template_file.exists():
        try:
            with open(template_file) as f:
                template = json.load(f)
        except (json.JSONDecodeError, IOError) as e:
            return f"Error reading template: {e}"

        # Replace placeholders in template content
        content = json.dumps(template.get("content", {}))
        for key, value in fields.items():
            content = content.replace(f"{{{{{key}}}}}", str(value))
            content = content.replace(f"{{{{ {key} }}}}", str(value))
        filled = json.loads(content)

        title = filled.get("title", template_name)
        sections = filled.get("sections", [])
        letterhead = filled.get("letterhead", False)

        if fmt == "pdf":
            path = _build_html_pdf(
                title,
                sections,
                letterhead=letterhead,
                date_str=datetime.now().strftime("%B %d, %Y"),
            )
            if path:
                return f"✅ Document created from template '{template_name}': {path}"

        path = _build_docx(
            title, sections, letterhead=letterhead, date_str=datetime.now().strftime("%B %d, %Y")
        )
        return f"✅ Document created from template '{template_name}': {path}"

    # Handle built-in template names
    if template_name == "letter":
        return create_letter(fields)
    elif template_name == "report":
        return create_report(fields)
    elif template_name == "receipt":
        return create_receipt(fields)
    else:
        return (
            f"Template '{template_name}' not found. Use list_templates to see available templates."
        )


def export_document(data: dict) -> str:
    """Convert between document formats (DOCX→PDF, Markdown→DOCX)."""
    source = data.get("source", "").strip()
    target_format = data.get("target_format", "pdf").lower()

    if not source:
        return "Please provide a source file path."

    source_path = Path(source).expanduser()
    if not source_path.exists():
        return f"Source file not found: {source}"

    ext = source_path.suffix.lower()

    if ext == ".md" and target_format == "docx":
        if not _ensure_docx():
            return "⚠️ DOCX conversion unavailable — python-docx could not be installed."

        content = source_path.read_text(encoding="utf-8")
        # Parse markdown into sections (basic parser)
        sections = []
        current_heading = None
        current_body = []

        for line in content.split("\n"):
            if line.startswith("# "):
                if current_heading or current_body:
                    sections.append(
                        {"heading": current_heading or "", "body": "\n".join(current_body)}
                    )
                current_heading = line[2:].strip()
                current_body = []
            elif line.startswith("## "):
                if current_heading or current_body:
                    sections.append(
                        {"heading": current_heading or "", "body": "\n".join(current_body)}
                    )
                current_heading = line[3:].strip()
                current_body = []
            else:
                current_body.append(line)

        if current_heading or current_body:
            sections.append({"heading": current_heading or "", "body": "\n".join(current_body)})

        title = source_path.stem.replace("_", " ").title()
        path = _build_docx(title, sections)
        return f"✅ Converted to DOCX: {path}"

    elif ext == ".docx" and target_format == "pdf":
        if not _ensure_weasyprint():
            return "⚠️ PDF conversion unavailable — weasyprint could not be installed."

        # Read DOCX, extract text, render as PDF
        if _ensure_docx():
            doc = DocxDocument(str(source_path))
            sections = []
            for para in doc.paragraphs:
                if para.style.name.startswith("Heading"):
                    sections.append({"heading": para.text, "body": ""})
                else:
                    if sections and not sections[-1].get("body"):
                        sections[-1]["body"] = para.text
                    else:
                        sections.append(para.text)

            title = source_path.stem.replace("_", " ").title()
            path = _build_html_pdf(title, sections)
            if path:
                return f"✅ Converted to PDF: {path}"

        return "Could not convert DOCX to PDF."

    return f"Unsupported conversion: {ext} → {target_format}. Supported: .md→.docx, .docx→.pdf"


# === Tool Definitions ===

TOOLS = [
    {
        "name": "create_document",
        "description": (
            "Generate a DOCX or PDF document from structured content with sections, headings, body text, and tables. "
            "Supports optional organization letterhead pulled from ~/.familiar/config.yaml and a logo image. "
            "Falls back to Markdown output if python-docx is unavailable, and to DOCX if weasyprint is unavailable for PDF. "
            "Each section can include a heading, body paragraphs, and tabular data with headers and rows."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string", "description": "Document title"},
                "sections": {
                    "type": "array",
                    "description": "Array of sections. Each can be a string (plain text) or object with 'heading', 'body', and optional 'table' (with 'headers' and 'rows').",
                    "items": {
                        "type": "object",
                        "properties": {
                            "heading": {"type": "string", "description": "Section heading text"},
                            "body": {
                                "type": "string",
                                "description": "Section body text or paragraph content",
                            },
                            "headers": {
                                "type": "array",
                                "items": {"type": "string"},
                                "description": "Column headers for the table",
                            },
                            "rows": {
                                "type": "array",
                                "items": {"type": "array"},
                                "description": "Table data rows, each row is an array of cell values",
                            },
                        },
                    },
                },
                "body": {
                    "type": "string",
                    "description": "Simple body text (alternative to sections)",
                },
                "format": {"type": "string", "enum": ["docx", "pdf"], "default": "docx"},
                "letterhead": {
                    "type": "boolean",
                    "default": False,
                    "description": "Include organization letterhead",
                },
            },
            "required": ["title"],
        },
        "input_examples": [
            {
                "title": "Monthly Report",
                "format": "docx",
                "sections": [
                    {"heading": "Summary", "body": "Q1 revenue increased 15%."},
                    {
                        "heading": "Data",
                        "headers": ["Month", "Revenue"],
                        "rows": [["Jan", "$10k"], ["Feb", "$12k"]],
                    },
                ],
            },
        ],
        "handler": create_document,
        "category": "documents",
    },
    {
        "name": "create_letter",
        "description": (
            "Generate a formal letter with organization letterhead, date, recipient address, and signature block. "
            "The letterhead is automatically pulled from organization config in ~/.familiar/config.yaml. "
            "Supports both DOCX and PDF output formats with professional formatting. "
            "If no date is specified, today's date is used automatically."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "recipient": {"type": "string", "description": "Recipient name and address"},
                "subject": {"type": "string", "description": "Letter subject"},
                "body": {"type": "string", "description": "Letter body text"},
                "signature": {"type": "string", "description": "Signature block (name, title)"},
                "date": {"type": "string", "description": "Letter date (default: today)"},
                "format": {"type": "string", "enum": ["docx", "pdf"], "default": "docx"},
            },
            "required": ["body"],
        },
        "handler": create_letter,
        "category": "documents",
    },
    {
        "name": "create_report",
        "description": (
            "Generate a formatted report with structured headings, body text, optional tables, and a date stamp. "
            "Each section supports a heading, body content, and an embedded table with headers and data rows. "
            "The report date defaults to today and organization letterhead can be optionally included. "
            "Outputs in DOCX or PDF format with professional styling and consistent formatting."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "title": {"type": "string", "description": "Report title"},
                "sections": {
                    "type": "array",
                    "description": "Array of section objects, each with 'heading' and 'body' (and optional 'table')",
                    "items": {
                        "type": "object",
                        "properties": {
                            "heading": {"type": "string", "description": "Section heading text"},
                            "body": {
                                "type": "string",
                                "description": "Section body text or paragraph content",
                            },
                            "table": {
                                "type": "object",
                                "description": "Optional embedded table for the section",
                                "properties": {
                                    "headers": {
                                        "type": "array",
                                        "items": {"type": "string"},
                                        "description": "Column headers for the table",
                                    },
                                    "rows": {
                                        "type": "array",
                                        "items": {"type": "array"},
                                        "description": "Table data rows, each row is an array of cell values",
                                    },
                                },
                            },
                        },
                    },
                },
                "format": {"type": "string", "enum": ["docx", "pdf"], "default": "docx"},
                "letterhead": {
                    "type": "boolean",
                    "default": False,
                    "description": "Include organization letterhead",
                },
            },
            "required": ["title", "sections"],
        },
        "input_examples": [
            {
                "title": "Q1 Financial Summary",
                "sections": [
                    {"heading": "Revenue", "content": "Total: $125,000"},
                    {"heading": "Expenses", "content": "Total: $98,000"},
                ],
            },
        ],
        "handler": create_report,
        "category": "documents",
    },
    {
        "name": "create_receipt",
        "description": (
            "Generate an IRS-compliant donation receipt and tax acknowledgment letter with organization letterhead. "
            "Includes required 501(c)(3) language, donor name, contribution amount, and goods/services disclosure. "
            "Organization details are pulled from ~/.familiar/config.yaml including name, EIN, and address. "
            "Defaults to PDF format for print-ready output suitable for mailing to donors."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "donor_name": {"type": "string", "description": "Donor full name"},
                "amount": {"type": "number", "description": "Donation amount"},
                "date_of_gift": {"type": "string", "description": "Date of gift (default: today)"},
                "description": {
                    "type": "string",
                    "description": "Description of contribution (default: Cash/check donation)",
                },
                "format": {"type": "string", "enum": ["docx", "pdf"], "default": "pdf"},
            },
            "required": ["donor_name", "amount"],
        },
        "handler": create_receipt,
        "category": "documents",
    },
    {
        "name": "list_templates",
        "description": (
            "List all available document templates including built-in and custom user-defined templates. "
            "Built-in templates include letter, report, receipt, memo, newsletter, and agenda formats. "
            "Custom templates are loaded from JSON files in ~/.familiar/templates/. "
            "Also checks for the presence of a letterhead logo image for document branding."
        ),
        "input_schema": {"type": "object", "properties": {}},
        "handler": list_templates,
        "category": "documents",
    },
    {
        "name": "fill_template",
        "description": (
            "Fill a document template with provided field data using mail-merge style placeholder replacement. "
            "Works with both built-in templates (letter, report, receipt) and custom JSON templates from ~/.familiar/templates/. "
            "Placeholders use {{field_name}} syntax and are replaced with the corresponding field values. "
            "Outputs the completed document in DOCX or PDF format with all formatting preserved."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "template": {
                    "type": "string",
                    "description": "Template name (e.g. 'letter', 'receipt', or custom template name)",
                },
                "fields": {
                    "type": "object",
                    "description": "Key-value pairs to fill in the template",
                },
                "format": {"type": "string", "enum": ["docx", "pdf"], "default": "docx"},
            },
            "required": ["template", "fields"],
        },
        "handler": fill_template,
        "category": "documents",
    },
    {
        "name": "export_document",
        "description": (
            "Convert between document formats, supporting Markdown to DOCX and DOCX to PDF conversions. "
            "Markdown files are parsed for headings and body content then rendered into structured DOCX. "
            "DOCX to PDF conversion uses weasyprint for high-quality HTML-based PDF rendering. "
            "Falls back gracefully with an error message if required libraries are unavailable."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "source": {"type": "string", "description": "Source file path"},
                "target_format": {
                    "type": "string",
                    "enum": ["docx", "pdf"],
                    "description": "Target format",
                },
            },
            "required": ["source", "target_format"],
        },
        "handler": export_document,
        "category": "documents",
    },
]
