#!/usr/bin/env python3
"""
ComplyForm — Postmark Template Batch Creator (v3 design)

Creates 1 Layout + 19 Standard templates via Postmark API.
Template aliases match exactly what backend code references.

Design: Stripe/Vercel-style minimal header, teal accent (#0d9488),
Dataplus X dark mode, cashier-style structured data, base64 inline logo.

Usage:
    python3 create_postmark_templates.py                    # dry-run
    python3 create_postmark_templates.py --execute          # create
    python3 create_postmark_templates.py --execute --verify # create + verify
    python3 create_postmark_templates.py --verify-only      # check existing

Requires: POSTMARK_SERVER_TOKEN env var (or --token).
"""

import argparse
import json
import os
import sys
import time
from urllib.request import Request, urlopen
from urllib.error import HTTPError

API_BASE = "https://api.postmarkapp.com"

# 96px PNG from 1024px source, displayed at 32x32 (3x retina)
LOGO_B64 = (
    "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"
)
LOGO_DATA_URI = f"data:image/png;base64,{LOGO_B64}"

TEAL = "#0d9488"
TEAL_DARK = "#0f766e"


# ---------------------------------------------------------------------------
# Layout
# ---------------------------------------------------------------------------

def _build_layout():
    return {
        "Name": "ComplyForm Base Layout",
        "Alias": "complyform-base",
        "TemplateType": "Layout",
        "Subject": "",
        "HtmlBody": f"""\
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
  body {{ margin:0; padding:0; background-color:#f6f8fa; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; }}
  .ew {{ width:100%; background-color:#f6f8fa; padding:48px 0; }}
  .ec {{ max-width:560px; margin:0 auto; background-color:#ffffff; border:1px solid #e5e7eb; border-radius:12px; overflow:hidden; }}
  .eb {{ padding:32px 36px 0; color:#374151; font-size:15px; line-height:1.7; }}
  .eb h1 {{ font-size:20px; font-weight:600; color:#111827; margin:0 0 20px; line-height:1.3; }}
  .eb p {{ margin:0 0 16px; }}
  .eb a {{ color:{TEAL}; text-decoration:underline; }}
  .btn {{ display:inline-block; background-color:{TEAL}; color:#ffffff !important; text-decoration:none !important; padding:12px 28px; border-radius:8px; font-weight:600; font-size:15px; }}
  .code {{ background:#f8fafc; border:1px solid #e5e7eb; border-radius:8px; padding:16px 20px; font-family:'SF Mono',Monaco,'Cascadia Code',monospace; font-size:14px; color:#111827; margin:16px 0; word-break:break-all; letter-spacing:0.02em; }}
  .alert {{ background:#fffbeb; border-left:3px solid #f59e0b; padding:14px 16px; margin:16px 0; }}
  .info {{ background:#f0fdfa; border:1px solid #99f6e4; border-radius:8px; padding:16px 20px; margin:16px 0; }}
  .lbl {{ font-size:13px; font-weight:500; text-transform:uppercase; letter-spacing:0.05em; color:#6b7280; margin:0 0 8px; }}
  .muted {{ color:#9ca3af; font-size:13px; }}
  .ef {{ padding:28px 36px 0; margin-top:32px; }}
  .efl {{ border-top:1px solid #f3f4f6; padding:20px 0; }}
  .efl td {{ font-size:12px; color:#9ca3af; }}
  .efl a {{ color:#9ca3af; text-decoration:none; }}
  @media (prefers-color-scheme: dark) {{
    body {{ background-color:#0b0f19 !important; }}
    .ew {{ background-color:#0b0f19 !important; }}
    .ec {{ background-color:#111827 !important; border-color:#1f2937 !important; }}
    .eb {{ color:#e2e8f0 !important; }}
    .eb h1 {{ color:#f9fafb !important; }}
    .code {{ background:#1e293b !important; border-color:#334155 !important; color:#f1f5f9 !important; }}
    .alert {{ background:rgba(245,158,11,0.1) !important; }}
    .info {{ background:rgba(13,148,136,0.08) !important; border-color:rgba(13,148,136,0.2) !important; }}
    .muted {{ color:#64748b !important; }}
    .efl {{ border-color:#1f2937 !important; }}
    .efl td {{ color:#4b5563 !important; }}
    .efl a {{ color:#4b5563 !important; }}
    .logo-text {{ color:#f9fafb !important; }}
  }}
</style>
</head>
<body>
<div class="ew">
  <div class="ec" role="article" aria-roledescription="email">
    <div class="eb">
      <table cellpadding="0" cellspacing="0" style="margin:0 0 28px;">
        <tr>
          <td style="vertical-align:middle;padding-right:10px;">
            <img src="{LOGO_DATA_URI}" width="32" height="32" alt="CF" style="display:block;border-radius:7px;">
          </td>
          <td style="vertical-align:middle;">
            <span class="logo-text" style="color:#111827;font-size:16px;font-weight:600;letter-spacing:-0.02em;">ComplyForm</span>
          </td>
        </tr>
      </table>
      {{{{{{@content}}}}}}
    </div>
    <div class="ef">
      <div class="efl">
        <table style="width:100%;">
          <tr>
            <td>ComplyForm</td>
            <td style="text-align:right;">
              <a href="https://complyform.dev/privacy">Privacy</a>&nbsp;&nbsp;&middot;&nbsp;&nbsp;<a href="https://complyform.dev/terms">Terms</a>&nbsp;&nbsp;&middot;&nbsp;&nbsp;<a href="https://docs.complyform.dev">Docs</a>
            </td>
          </tr>
        </table>
      </div>
    </div>
  </div>
</div>
</body>
</html>""",
        "TextBody": """\
ComplyForm
----------

{{{@content}}}

---
ComplyForm
Privacy: https://complyform.dev/privacy | Terms: https://complyform.dev/terms | Docs: https://docs.complyform.dev""",
    }

LAYOUT = _build_layout()


# ---------------------------------------------------------------------------
# 19 Standard Templates
# ---------------------------------------------------------------------------

TEMPLATES = [
    {"Name":"License Key Delivery","Alias":"license-key-delivery","Subject":"Your ComplyForm {{tier_name}} license key","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Welcome to ComplyForm {{tier_name}}!</h1>\n<p>Your license has been activated. Here\u2019s your license key:</p>\n<div class=\"code\">{{license_key}}</div>\n<p class=\"lbl\">Activate</p>\n<div class=\"code\">complyform config activate {{license_key}}</div>\n<p><a href=\"https://docs.complyform.dev/quickstart\" class=\"btn\">Get started in 30 seconds</a></p>\n<p class=\"muted\">By activating, you acknowledge the <a href=\"https://complyform.dev/terms\">Terms of Service</a>.</p>",
     "TextBody":"Welcome to ComplyForm {{tier_name}}!\n\nYour license key: {{license_key}}\n\nActivate:\n  complyform config activate {{license_key}}\n\nGet started: https://docs.complyform.dev/quickstart\n\nBy activating, you acknowledge the Terms of Service: https://complyform.dev/terms"},

    {"Name":"Drift Alert","Alias":"drift-alert","Subject":"Compliance drift detected: {{project_name}} ({{old_score}} \u2192 {{new_score}})","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Compliance drift detected</h1>\n<div class=\"alert\">\n  <strong>{{project_name}}</strong> score dropped from <strong>{{old_score}}</strong> to <strong>{{new_score}}</strong>.\n</div>\n<table style=\"width:100%;border-collapse:collapse;margin:0 0 24px;\">\n{{#each findings}}\n<tr style=\"border-bottom:1px solid #f3f4f6;\">\n  <td style=\"padding:10px 0;font-size:13px;font-weight:500;color:#6b7280;width:80px;\">{{control_id}}</td>\n  <td style=\"padding:10px 0;font-size:14px;\">{{description}}</td>\n  <td style=\"padding:10px 0;text-align:right;\"><span style=\"font-size:11px;font-weight:600;padding:3px 8px;border-radius:4px;background:#fef2f2;color:#991b1b;\">{{severity}}</span></td>\n</tr>\n{{/each}}\n</table>\n<p><a href=\"{{dashboard_url}}\" class=\"btn\">View in dashboard</a></p>\n<p class=\"muted\">You\u2019re receiving this because drift monitoring is enabled for this project.</p>",
     "TextBody":"Compliance drift detected\n\n{{project_name}} score dropped from {{old_score}} to {{new_score}}.\n\n{{#each findings}}\n- {{control_id}} \u2014 {{description}} ({{severity}})\n{{/each}}\n\nDashboard: {{dashboard_url}}"},

    {"Name":"License Expiry Warning","Alias":"license-expiry-warning","Subject":"Your ComplyForm {{tier_name}} license expires {{expires_in}}","LayoutTemplate":"complyform-base",
     "HtmlBody":f"<h1>License expiring soon</h1>\n<p>Your <strong>{{{{tier_name}}}}</strong> license expires on <strong>{{{{expiry_date}}}}</strong> ({{{{expires_in}}}}).</p>\n<p><a href=\"{{{{renewal_url}}}}\" class=\"btn\">Renew now</a></p>\n<div class=\"info\">\n  <p style=\"margin:0 0 8px;font-size:13px;font-weight:600;color:{TEAL_DARK};\">After expiry</p>\n  <p style=\"margin:0;font-size:14px;color:#6b7280;line-height:1.6;\">Paid features become unavailable. Community tier continues working. Scan history preserved for 90 days.</p>\n</div>",
     "TextBody":"License expiring soon\n\nYour {{tier_name}} license expires on {{expiry_date}} ({{expires_in}}).\n\nRenew: {{renewal_url}}\n\nAfter expiry: paid features unavailable, Community tier continues, scan history preserved 90 days."},

    {"Name":"Tier Upgrade Confirmation","Alias":"tier-upgrade-confirmation","Subject":"Upgraded to ComplyForm {{new_tier}}!","LayoutTemplate":"complyform-base",
     "HtmlBody":f"<h1>Welcome to {{{{new_tier}}}}!</h1>\n<p>Your upgrade is active. Here\u2019s the summary:</p>\n<div style=\"background:#f8fafc;border:1px solid #e5e7eb;border-radius:8px;padding:4px 20px;margin:0 0 24px;\">\n  <table style=\"width:100%;border-collapse:collapse;\">\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Previous plan</td><td style=\"padding:10px 0;font-size:14px;font-weight:500;text-align:right;\">{{{{old_tier}}}}</td></tr>\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">New plan</td><td style=\"padding:10px 0;font-size:14px;font-weight:600;color:{TEAL};text-align:right;\">{{{{new_tier}}}}</td></tr>\n    {{{{#prorated_amount}}}}\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Prorated charge</td><td style=\"padding:10px 0;font-size:14px;font-weight:500;text-align:right;\">{{{{prorated_amount}}}}</td></tr>\n    {{{{/prorated_amount}}}}\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Next renewal</td><td style=\"padding:10px 0;font-size:14px;font-weight:500;text-align:right;\">{{{{next_renewal_date}}}}</td></tr>\n    <tr><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Annual amount</td><td style=\"padding:10px 0;font-size:14px;font-weight:500;text-align:right;\">{{{{next_renewal_amount}}}}</td></tr>\n  </table>\n</div>\n<p class=\"lbl\">Now unlocked</p>\n{{{{#each capabilities}}}}\n<p style=\"margin:0 0 6px;font-size:14px;\">&#10003;&nbsp; {{{{this}}}}</p>\n{{{{/each}}}}\n<p style=\"margin:24px 0 0;\"><a href=\"https://docs.complyform.dev/tiers/{{{{new_tier_slug}}}}\" class=\"btn\">Explore {{{{new_tier}}}} features</a></p>",
     "TextBody":"Welcome to {{new_tier}}!\n\nPrevious: {{old_tier}} | New: {{new_tier}}\nProrated: {{prorated_amount}}\nNext renewal: {{next_renewal_date}} for {{next_renewal_amount}}\n\nUnlocked: (see email for details)\n\nExplore: https://docs.complyform.dev/tiers/{{new_tier_slug}}"},

    {"Name":"Key Rotation Notice","Alias":"key-rotation","Subject":"ComplyForm signing key rotated \u2014 action required","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Signing key rotated</h1>\n<p>ComplyForm\u2019s Ed25519 signing key has been rotated.</p>\n<p>To continue verifying attestations, update your CLI:</p>\n<div class=\"code\">complyform update</div>\n<p>If you use air-gapped licenses, download the new license file:</p>\n<p><a href=\"{{license_download_url}}\" class=\"btn\">Download new license file</a></p>\n<p class=\"muted\">Your existing license key remains valid \u2014 only the signing verification key has changed.</p>",
     "TextBody":"Signing key rotated\n\nUpdate: complyform update\nDownload: {{license_download_url}}\n\nYour existing license key remains valid."},

    {"Name":"Overage Payment Warning","Alias":"overage-payment-warning","Subject":"Action required: outstanding ComplyForm overage payment","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Outstanding overage payment</h1>\n<div class=\"alert\">\n  <strong>Amount due: {{outstanding_amount}}</strong><br>\n  Payment deadline: {{enforcement_deadline}}\n</div>\n<p>Your {{tier_name}} plan includes {{base_project_limit}} projects. You have {{current_project_count}} active engagements, and the overage charge has not been processed.</p>\n<p><a href=\"{{paddle_portal_url}}\" class=\"btn\">Update payment method</a></p>\n<div class=\"info\">\n  <p style=\"margin:0 0 8px;font-size:13px;font-weight:600;\">After {{enforcement_deadline}}</p>\n  <p style=\"margin:0;font-size:14px;color:#6b7280;line-height:1.6;\">Overage engagements (beyond base {{base_project_limit}}) will be suspended \u2014 least recently scanned first. Your base projects are unaffected.</p>\n</div>",
     "TextBody":"Outstanding overage payment\n\nDue: {{outstanding_amount}} by {{enforcement_deadline}}\n\nUpdate payment: {{paddle_portal_url}}\n\nAfter deadline: overage engagements suspended. Base {{base_project_limit}} unaffected."},

    {"Name":"Onboarding: First Scan Nudge","Alias":"onboarding-first-scan-nudge","Subject":"Run your first ComplyForm scan in 30 seconds","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Ready to scan?</h1>\n<p>You activated your {{tier_name}} license 24 hours ago but haven\u2019t run a scan yet. It takes 30 seconds:</p>\n<div class=\"code\" style=\"line-height:2;\"><span style=\"color:#9ca3af;\">$</span> cd /path/to/terraform<br><span style=\"color:#9ca3af;\">$</span> complyform scan<br><span style=\"color:#9ca3af;\">$</span> complyform assess --compliance=soc2</div>\n<p><a href=\"https://docs.complyform.dev/quickstart\" class=\"btn\">View quickstart guide</a></p>\n<p class=\"muted\">Already scanning? Ignore this \u2014 we track activity to send relevant tips only.</p>",
     "TextBody":"Ready to scan?\n\n  cd /path/to/terraform\n  complyform scan\n  complyform assess --compliance=soc2\n\nQuickstart: https://docs.complyform.dev/quickstart"},

    {"Name":"Onboarding: Activation Success","Alias":"onboarding-activation-success","Subject":"Nice \u2014 your first ComplyForm scan is done!","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>First scan complete!</h1>\n<p>You\u2019ve scanned <strong>{{resource_count}}</strong> resources across <strong>{{provider_count}}</strong> provider(s). Now assess compliance:</p>\n<div class=\"code\">complyform assess --compliance=soc2</div>\n<p>Then remediate any gaps:</p>\n<div class=\"code\">complyform remediate --compliance=soc2</div>\n<p><a href=\"https://docs.complyform.dev/guides/first-assessment\" class=\"btn\">Assessment guide</a></p>",
     "TextBody":"First scan complete!\n\n{{resource_count}} resources across {{provider_count}} provider(s).\n\n  complyform assess --compliance=soc2\n  complyform remediate --compliance=soc2\n\nGuide: https://docs.complyform.dev/guides/first-assessment"},

    {"Name":"Onboarding: Remediate Explainer","Alias":"onboarding-remediate-explainer","Subject":"Close your compliance gaps with ComplyForm remediate","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>From gaps to patches</h1>\n<p>You\u2019ve assessed your infrastructure \u2014 here\u2019s how to fix what you found:</p>\n<div class=\"code\">complyform remediate --compliance=soc2 --review</div>\n<p>This generates Terraform patches for each finding. The <code>--review</code> flag lets you approve each patch before applying.</p>\n{{#is_community}}\n<div class=\"info\">\n  <strong>Community tier:</strong> Remediation available for 4 frameworks. <a href=\"https://complyform.dev/pricing\">Upgrade to Pro</a> for all 53.\n</div>\n{{/is_community}}\n<p><a href=\"https://docs.complyform.dev/guides/remediation\" class=\"btn\">Remediation guide</a></p>",
     "TextBody":"From gaps to patches\n\n  complyform remediate --compliance=soc2 --review\n\nUpgrade for all 53 frameworks: https://complyform.dev/pricing\n\nGuide: https://docs.complyform.dev/guides/remediation"},

    {"Name":"Onboarding: Day 7 Check-in","Alias":"onboarding-day7-checkin","Subject":"Need help with ComplyForm?","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>How\u2019s it going?</h1>\n<p>It\u2019s been a week since you activated ComplyForm. We noticed you haven\u2019t been active recently.</p>\n<p>Common things people get stuck on:</p>\n<p>&#8226;&nbsp; <a href=\"https://docs.complyform.dev/guides/remote-backends\">Scanning remote backends (S3, GCS)</a></p>\n<p>&#8226;&nbsp; <a href=\"https://docs.complyform.dev/guides/ci-cd\">Setting up CI/CD integration</a></p>\n<p>&#8226;&nbsp; <a href=\"https://docs.complyform.dev/guides/custom-frameworks\">Adding custom frameworks</a></p>\n<p><strong>Reply to this email</strong> \u2014 it goes directly to the founder, and I\u2019ll help you get unstuck.</p>",
     "TextBody":"How's it going?\n\nCommon sticking points:\n- Remote backends: https://docs.complyform.dev/guides/remote-backends\n- CI/CD: https://docs.complyform.dev/guides/ci-cd\n- Custom frameworks: https://docs.complyform.dev/guides/custom-frameworks\n\nReply to this email \u2014 it goes directly to the founder."},

    {"Name":"Onboarding: Day 14 Success","Alias":"onboarding-day14-success","Subject":"Two weeks of ComplyForm \u2014 here\u2019s what you\u2019ve done","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Two-week recap</h1>\n<p>Here\u2019s what you\u2019ve accomplished:</p>\n<div style=\"background:#f8fafc;border:1px solid #e5e7eb;border-radius:8px;padding:4px 20px;margin:0 0 24px;\">\n  <table style=\"width:100%;border-collapse:collapse;\">\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Scans completed</td><td style=\"padding:10px 0;font-size:14px;font-weight:500;text-align:right;\">{{scan_count}}</td></tr>\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Assessments run</td><td style=\"padding:10px 0;font-size:14px;font-weight:500;text-align:right;\">{{assessment_count}}</td></tr>\n    <tr><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Remediations applied</td><td style=\"padding:10px 0;font-size:14px;font-weight:500;text-align:right;\">{{remediation_count}}</td></tr>\n  </table>\n</div>\n{{#has_advanced}}\n<p class=\"lbl\">Ready for more</p>\n<p>&#8226;&nbsp; <a href=\"https://docs.complyform.dev/guides/pr-remediation\">Open PRs from remediation</a></p>\n<p>&#8226;&nbsp; <a href=\"https://docs.complyform.dev/guides/policy-generation\">Generate OPA/Rego policies</a></p>\n<p>&#8226;&nbsp; <a href=\"https://docs.complyform.dev/guides/html-reports\">Create HTML compliance reports</a></p>\n{{/has_advanced}}",
     "TextBody":"Two-week recap\n\n- {{scan_count}} scans\n- {{assessment_count}} assessments\n- {{remediation_count}} remediations\nNext steps: https://docs.complyform.dev/guides/pr-remediation"},

    {"Name":"Cancellation Feedback","Alias":"cancellation-feedback","Subject":"Sorry to see you go \u2014 one quick question?","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>We\u2019d love to learn from this</h1>\n<p>Your <strong>{{tier_name}}</strong> subscription is canceled. Access continues until <strong>{{access_until}}</strong>.</p>\n<p style=\"color:#6b7280;font-size:14px;\">If you have 10 seconds \u2014 what was the main reason?</p>\n<a href=\"{{feedback_url}}?reason=too_expensive\" style=\"display:block;background:#f8fafc;border:1px solid #e5e7eb;border-radius:8px;padding:12px 20px;margin:0 0 8px;text-decoration:none;color:#374151;font-size:14px;font-weight:500;\">Too expensive</a>\n<a href=\"{{feedback_url}}?reason=missing_features\" style=\"display:block;background:#f8fafc;border:1px solid #e5e7eb;border-radius:8px;padding:12px 20px;margin:0 0 8px;text-decoration:none;color:#374151;font-size:14px;font-weight:500;\">Missing features I need</a>\n<a href=\"{{feedback_url}}?reason=not_using\" style=\"display:block;background:#f8fafc;border:1px solid #e5e7eb;border-radius:8px;padding:12px 20px;margin:0 0 8px;text-decoration:none;color:#374151;font-size:14px;font-weight:500;\">Not using it enough</a>\n<a href=\"{{feedback_url}}?reason=switched\" style=\"display:block;background:#f8fafc;border:1px solid #e5e7eb;border-radius:8px;padding:12px 20px;margin:0 0 0;text-decoration:none;color:#374151;font-size:14px;font-weight:500;\">Switched to another tool</a>\n<p class=\"muted\" style=\"margin:20px 0 0;\">Community tier continues \u2014 scan and assess for free, always.</p>",
     "TextBody":"Sorry to see you go\n\nAccess until {{access_until}}.\n\nReason?\n- Too expensive: {{feedback_url}}?reason=too_expensive\n- Missing features: {{feedback_url}}?reason=missing_features\n- Not using: {{feedback_url}}?reason=not_using\n- Switched: {{feedback_url}}?reason=switched\n\nCommunity tier continues \u2014 free, always."},

    {"Name":"NPS Survey","Alias":"nps-survey","Subject":"How likely are you to recommend ComplyForm?","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Quick question</h1>\n<p style=\"text-align:center;\">How likely are you to recommend ComplyForm to a colleague?</p>\n<p style=\"text-align:center;margin:24px 0;\">\n{{#each scores}}\n<a href=\"{{url}}\" style=\"display:inline-block;width:36px;height:36px;line-height:36px;text-align:center;margin:2px;border-radius:6px;background:{{color}};color:{{text_color}};text-decoration:none;font-weight:600;font-size:13px;\">{{value}}</a>\n{{/each}}\n</p>\n<p style=\"text-align:center;\" class=\"muted\">0 = Not likely&nbsp;&nbsp;&nbsp;&nbsp;10 = Extremely likely</p>\n<p class=\"muted\" style=\"text-align:center;\">One click \u2014 no form to fill out.</p>",
     "TextBody":"How likely are you to recommend ComplyForm? (0-10)\n\n{{#each scores}}\n{{value}}: {{url}}\n{{/each}}\n\n0 = Not likely, 10 = Extremely likely"},

    {"Name":"Release Announcement","Alias":"release-announcement","Subject":"{{subject}}","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>{{headline}}</h1>\n{{{body_html}}}\n<p class=\"lbl\">Update</p>\n<div class=\"code\">complyform update</div>\n<p><a href=\"{{changelog_url}}\" class=\"btn\">View changelog</a></p>",
     "TextBody":"{{headline}}\n\n{{{body_text}}}\n\nUpdate: complyform update\nChangelog: {{changelog_url}}"},

    {"Name":"Profile Update Notification","Alias":"profile-update-notification","Subject":"ComplyForm profile update: {{framework_count}} framework(s) changed","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Profile bundle updated</h1>\n{{#has_breaking_changes}}\n<div class=\"alert\">\n  <strong>Breaking changes</strong> \u2014 some controls have been modified or removed.\n</div>\n{{/has_breaking_changes}}\n<p class=\"lbl\">Affected frameworks</p>\n{{#each frameworks}}\n<p>&#8226;&nbsp; <strong>{{name}}</strong> \u2014 {{description}}</p>\n{{/each}}\n{{#source_reference}}\n<p class=\"muted\">Source: {{source_reference}}</p>\n{{/source_reference}}\n<p class=\"lbl\">Update</p>\n<div class=\"code\">complyform update</div>\n<p><a href=\"{{changelog_url}}\" class=\"btn\">View profile changelog</a></p>",
     "TextBody":"Profile bundle updated\n\nSee email for affected frameworks.\n\nUpdate: complyform update\nChangelog: {{changelog_url}}"},

    {"Name":"Enterprise Quote Request","Alias":"enterprise-quote-request","Subject":"Enterprise quote request from {{company_name}}","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>New enterprise quote request</h1>\n<div style=\"background:#f8fafc;border:1px solid #e5e7eb;border-radius:8px;padding:4px 20px;margin:0 0 16px;\">\n  <table style=\"width:100%;border-collapse:collapse;\">\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Company</td><td style=\"padding:10px 0;font-size:14px;font-weight:500;text-align:right;\">{{company_name}}</td></tr>\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Contact</td><td style=\"padding:10px 0;font-size:14px;text-align:right;\">{{contact_name}} ({{contact_email}})</td></tr>\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Size</td><td style=\"padding:10px 0;font-size:14px;text-align:right;\">{{company_size}}</td></tr>\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Frameworks</td><td style=\"padding:10px 0;font-size:14px;text-align:right;\">{{frameworks}}</td></tr>\n    <tr style=\"border-bottom:1px solid #f3f4f6;\"><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Clouds</td><td style=\"padding:10px 0;font-size:14px;text-align:right;\">{{clouds}}</td></tr>\n    <tr><td style=\"padding:10px 0;font-size:13px;color:#6b7280;\">Est. engagements</td><td style=\"padding:10px 0;font-size:14px;text-align:right;\">{{engagement_estimate}}</td></tr>\n  </table>\n</div>\n{{#requirements}}\n<p class=\"lbl\">Additional requirements</p>\n<p>{{requirements}}</p>\n{{/requirements}}\n<p class=\"muted\">Submitted from complyform.dev/contact-sales</p>",
     "TextBody":"Enterprise quote request\n\nCompany: {{company_name}}\nContact: {{contact_name}} ({{contact_email}})\nSize: {{company_size}}\nFrameworks: {{frameworks}}\nClouds: {{clouds}}\nEngagements: {{engagement_estimate}}\nRequirements: {{requirements}}"},

    {"Name":"Member Invitation","Alias":"member-invitation","Subject":"You\u2019ve been invited to {{org_name}} on ComplyForm","LayoutTemplate":"complyform-base",
     "HtmlBody":f"<h1 style=\"text-align:center;\">You\u2019re invited!</h1>\n<div style=\"text-align:center;margin:0 0 24px;\">\n  <div style=\"display:inline-block;vertical-align:middle;width:44px;height:44px;border-radius:50%;background:#f0fdfa;line-height:44px;text-align:center;font-weight:600;font-size:15px;color:{TEAL};\">{{{{inviter_initials}}}}</div>\n  <span style=\"display:inline-block;vertical-align:middle;margin:0 12px;color:#d1d5db;font-size:18px;\">&#8594;</span>\n  <div style=\"display:inline-block;vertical-align:middle;width:44px;height:44px;border-radius:50%;background:#f0fdfa;line-height:44px;text-align:center;font-weight:600;font-size:15px;color:{TEAL};\">{{{{org_initials}}}}</div>\n</div>\n<p style=\"text-align:center;\"><strong>{{{{inviter_name}}}}</strong> invited you to join <strong>{{{{org_name}}}}</strong></p>\n<p style=\"text-align:center;color:#6b7280;font-size:14px;\">Role: {{{{role}}}}</p>\n<p style=\"text-align:center;\"><a href=\"{{{{invite_url}}}}\" class=\"btn\">Accept invitation</a></p>\n<p class=\"muted\" style=\"text-align:center;\">Expires {{{{expiry_date}}}}. If you weren\u2019t expecting this, safely ignore it.</p>",
     "TextBody":"You\u2019re invited!\n\n{{inviter_name}} invited you to join {{org_name}} as {{role}}.\n\nAccept: {{invite_url}}\n\nExpires {{expiry_date}}."},

    {"Name":"Data Export Ready","Alias":"data-export-ready","Subject":"Your ComplyForm data export is ready","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Export ready</h1>\n<p>Your data export is ready for download.</p>\n<p><a href=\"{{download_url}}\" class=\"btn\">Download export (ZIP)</a></p>\n<div class=\"info\">\n  <p style=\"margin:0 0 8px;font-size:13px;font-weight:600;\">Contents</p>\n  {{{contents_summary}}}\n</div>\n<p class=\"muted\">This link expires in 24 hours.</p>",
     "TextBody":"Export ready\n\nDownload: {{download_url}}\n\nContents:\n{{{contents_summary}}}\n\nLink expires in 24 hours."},

    {"Name":"Data Deletion Confirmed","Alias":"data-deletion-confirmed","Subject":"Your ComplyForm data has been deleted","LayoutTemplate":"complyform-base",
     "HtmlBody":"<h1>Data deletion confirmed</h1>\n<p>Your data deletion request has been processed. Permanently removed:</p>\n{{{deleted_summary}}}\n<div class=\"info\">\n  <p style=\"margin:0 0 8px;font-size:13px;font-weight:600;\">Note</p>\n  <p style=\"margin:0;font-size:14px;color:#6b7280;\">Paddle billing records are retained for tax and legal compliance per their <a href=\"https://www.paddle.com/legal/privacy\">privacy policy</a>.</p>\n</div>\n<p class=\"muted\">Questions? Reply to this email.</p>",
     "TextBody":"Data deletion confirmed\n\nDeleted:\n{{{deleted_summary}}}\n\nNote: Paddle billing records retained for tax/legal.\nhttps://www.paddle.com/legal/privacy"},
]


# ---------------------------------------------------------------------------
# API
# ---------------------------------------------------------------------------

def api_call(token, method, path, body=None):
    url = f"{API_BASE}{path}"
    headers = {"Accept":"application/json","Content-Type":"application/json","X-Postmark-Server-Token":token}
    data = json.dumps(body).encode() if body else None
    req = Request(url, data=data, headers=headers, method=method)
    try:
        with urlopen(req) as resp:
            return json.loads(resp.read().decode())
    except HTTPError as e:
        return {"_error":True,"_status":e.code,"_body":e.read().decode()}

def create_template(token, template, dry_run):
    alias = template.get("Alias","unknown")
    ttype = template.get("TemplateType","Standard")
    if dry_run:
        return True, f"[DRY-RUN] Would create {ttype}: {alias}"
    result = api_call(token, "POST", "/templates", template)
    if result.get("_error"):
        return False, f"FAILED {alias}: HTTP {result['_status']} \u2014 {result['_body']}"
    return True, f"Created {ttype} '{alias}' (ID: {result.get('TemplateId','?')})"

def verify_templates(token):
    result = api_call(token, "GET", "/templates?count=100&offset=0&TemplateType=All")
    if result.get("_error"):
        print(f"  ERROR: {result['_body']}")
        return 0, 0, []
    existing = {t["Alias"] for t in result.get("Templates",[]) if t.get("Alias")}
    expected = {LAYOUT["Alias"]} | {t["Alias"] for t in TEMPLATES}
    found = expected & existing
    missing = expected - existing
    return len(found), len(missing), sorted(missing)


def main():
    parser = argparse.ArgumentParser(description="ComplyForm Postmark template batch creator (v3)")
    parser.add_argument("--execute", action="store_true", help="Create templates (default: dry-run)")
    parser.add_argument("--verify", action="store_true", help="Verify after creation")
    parser.add_argument("--verify-only", action="store_true", help="Only verify existing")
    parser.add_argument("--token", default=None, help="Postmark Server API Token")
    args = parser.parse_args()

    token = args.token or os.environ.get("POSTMARK_SERVER_TOKEN", "")
    if not token and (args.execute or args.verify or args.verify_only):
        print("ERROR: Set POSTMARK_SERVER_TOKEN env var or pass --token")
        sys.exit(1)

    dry_run = not args.execute

    if args.verify_only:
        print("Verifying...")
        found, mc, ma = verify_templates(token)
        print(f"  Found: {found}/20")
        if ma:
            for a in ma: print(f"    - {a}")
            sys.exit(1)
        print("  All 20 present.")
        sys.exit(0)

    if dry_run:
        print("=" * 60)
        print("DRY RUN \u2014 no API calls")
        print("Re-run with --execute to create templates")
        print("=" * 60)

    print(f"\n1 Layout + {len(TEMPLATES)} Standard = {1 + len(TEMPLATES)} total\n")

    ok, msg = create_template(token, LAYOUT, dry_run)
    print(f"  {'\u2713' if ok else '\u2717'} {msg}")
    if not ok and not dry_run:
        print("  Layout failed \u2014 aborting.")
        sys.exit(1)
    if not dry_run: time.sleep(0.3)

    sc = 1 if ok else 0
    fc = 0
    for t in TEMPLATES:
        ok, msg = create_template(token, t, dry_run)
        print(f"  {'\u2713' if ok else '\u2717'} {msg}")
        if ok: sc += 1
        else: fc += 1
        if not dry_run: time.sleep(0.3)

    print(f"\nDone: {sc} succeeded, {fc} failed")

    if args.verify and not dry_run:
        print("\nVerifying...")
        found, mc, ma = verify_templates(token)
        print(f"  Found: {found}/20")
        if ma:
            print(f"  Missing: {', '.join(ma)}")
            sys.exit(1)
        print("  All templates verified.")

    if dry_run:
        print(f"\nTo create:\n  POSTMARK_SERVER_TOKEN='...' python3 {sys.argv[0]} --execute --verify")


if __name__ == "__main__":
    main()
