#!/usr/bin/env python3
"""
DocuSign Template Builder — Non-Employee Agreement (DOCX, 2 pages)

Fields (coordinate-based, confirmed from DocuSign template editor by Adner 2026-02-22):
  Page 1: Date Signed  x=100, y=88   (auto-fills on signing)
  Page 1: Name of User x=140, y=110  (text, required)
  Page 2: Sign Here    x=112, y=476  (no date)
  Page 3: removed from document
"""

import sys, json, time, base64, requests
import jwt as pyjwt

# ── Config ────────────────────────────────────────────────────────────────────
CLIENT_ID    = "33016b18-9008-4a83-bfdd-be58593465a6"
USER_ID      = "f95937b1-587c-4515-b6c5-1116d32a8922"
ACCOUNT_ID   = "45807776"
BASE_URI     = "https://demo.docusign.net"
AUTH_HOST    = "account-d.docusign.com"
PRIVATE_KEY  = "/home/isthekid/.openclaw/workspace/secrets/docusign_demo_private.key"

TEMPLATE_NAME = "Non-Employee IT Agreement"
DOCX_PATH     = "/home/isthekid/.openclaw/workspace/forms/Non_Employee_Agreement_2page.docx"
TEMPLATE_ID   = "a3674be2-e232-4258-8571-71cdaf3b93c4"


# ── Auth ──────────────────────────────────────────────────────────────────────
def get_access_token():
    with open(PRIVATE_KEY) as f:
        pk = f.read()
    now = int(time.time())
    payload = {
        "iss": CLIENT_ID, "sub": USER_ID, "aud": AUTH_HOST,
        "iat": now, "exp": now + 3600,
        "scope": "signature impersonation",
    }
    token = pyjwt.encode(payload, pk, algorithm="RS256")
    resp = requests.post(
        f"https://{AUTH_HOST}/oauth/token",
        data={"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer", "assertion": token},
    )
    resp.raise_for_status()
    return resp.json()["access_token"]


# ── Tabs ──────────────────────────────────────────────────────────────────────
def non_employee_tabs():
    return {
        # Page 1 — auto-fills with signing date
        "dateSignedTabs": [
            {
                "documentId":  "1",
                "pageNumber":  "1",
                "tabLabel":    "DateSigned",
                "xPosition":   "100",
                "yPosition":   "88",
            },
        ],
        # Page 1 — Name of User (signer fills in)
        "textTabs": [
            {
                "documentId":  "1",
                "pageNumber":  "1",
                "tabLabel":    "NameOfUser",
                "xPosition":   "140",
                "yPosition":   "110",
                "width":       "250",
                "height":      "20",
                "required":    "true",
                "locked":      "false",
            },
        ],
        # Page 2 — Signature only, no date
        "signHereTabs": [
            {
                "documentId":  "1",
                "pageNumber":  "2",
                "tabLabel":    "NonEmployeeSignature",
                "xPosition":   "112",
                "yPosition":   "476",
            },
        ],
    }


# ── Template body ─────────────────────────────────────────────────────────────
def build_body(docx_b64):
    return {
        "name":        TEMPLATE_NAME,
        "description": "Non-Employee IT Agreement — 2-page, coordinate-based, built by Mr Anderson 2026-02-22",
        "documents": [
            {
                "documentId":    "1",
                "name":          "Non_Employee_Agreement.docx",
                "documentBase64": docx_b64,
                "fileExtension": "docx",
            }
        ],
        "recipients": {
            "signers": [
                {
                    "roleName":     "Non-Employee",
                    "recipientId":  "1",
                    "routingOrder": "1",
                    "tabs": non_employee_tabs(),
                }
            ]
        },
    }


# ── API helpers ───────────────────────────────────────────────────────────────
def auth_headers(token):
    return {
        "Authorization": f"Bearer {token}",
        "Content-Type":  "application/json",
        "Accept":        "application/json",
    }


def delete_template(token, tid):
    return requests.delete(
        f"{BASE_URI}/restapi/v2.1/accounts/{ACCOUNT_ID}/templates/{tid}",
        headers=auth_headers(token),
    )


def create_template(token, body):
    return requests.post(
        f"{BASE_URI}/restapi/v2.1/accounts/{ACCOUNT_ID}/templates",
        headers=auth_headers(token),
        json=body,
    )


# ── Main ──────────────────────────────────────────────────────────────────────
def main():
    print("Getting access token...")
    try:
        token = get_access_token()
        print("  ✅ Token acquired")
    except Exception as e:
        print(f"  ❌ Auth failed: {e}")
        sys.exit(1)

    with open(DOCX_PATH, "rb") as f:
        docx_b64 = base64.b64encode(f.read()).decode()

    if TEMPLATE_ID:
        print(f"\nDeleting existing template ({TEMPLATE_ID})...")
        r = delete_template(token, TEMPLATE_ID)
        print(f"  {'✅ Deleted' if r.status_code in (200, 204) else f'⚠️  {r.status_code} (may already be gone)'}")

    print(f"\nCreating: {TEMPLATE_NAME!r}")
    resp = create_template(token, build_body(docx_b64))

    if resp.status_code in (200, 201):
        tid = resp.json().get("templateId", "?")
        print(f"  ✅ Created — templateId: {tid}")
        result = {"name": TEMPLATE_NAME, "templateId": tid, "status": "created"}
    else:
        print(f"  ❌ Failed ({resp.status_code}): {resp.text[:600]}")
        result = {"name": TEMPLATE_NAME, "status": "error", "detail": resp.text[:600]}

    out = "/home/isthekid/.openclaw/workspace/docusign/agreement_template_id.json"
    with open(out, "w") as f:
        json.dump(result, f, indent=2)
    print(f"\nResult saved to {out}")
    return result


if __name__ == "__main__":
    main()
