"""
Trial provisioning for AutoPIL managed sandboxes.

- Creates an isolated tenant with demo seed data
- Sends welcome email via Resend
- Background threads handle TTL expiry and drip emails
"""

import json
import logging
import os
import threading
import time
import uuid
from datetime import datetime, timedelta, timezone
from urllib.error import URLError
from urllib.request import Request, urlopen

logger = logging.getLogger(__name__)

TRIAL_DAYS = 15
TRIAL_FROM_EMAIL = os.environ.get("TRIAL_FROM_EMAIL", "trials@autopil.ai")
TRIAL_BASE_URL = os.environ.get("TRIAL_BASE_URL", "https://autopil-api.onrender.com")


# ── email ──────────────────────────────────────────────────────────────────────

def _send_resend(to: str, subject: str, html: str) -> bool:
    import subprocess
    api_key = os.environ.get("RESEND_API_KEY", "")
    if not api_key:
        logger.warning("RESEND_API_KEY not set — skipping email to %s", to)
        return False
    logger.info("Sending via Resend: key_prefix=%s key_len=%d", api_key[:6], len(api_key))
    from_email = os.environ.get("TRIAL_FROM_EMAIL", "trials@autopil.ai")
    payload = json.dumps({"from": from_email, "to": [to], "subject": subject, "html": html})
    try:
        result = subprocess.run(
            [
                "curl", "-s", "-o", "/dev/null", "-w", "%{http_code}",
                "-X", "POST", "https://api.resend.com/emails",
                "-H", f"Authorization: Bearer {api_key}",
                "-H", "Content-Type: application/json",
                "-d", payload,
            ],
            capture_output=True, text=True, timeout=15,
        )
        status = result.stdout.strip()
        if status in ("200", "201"):
            logger.info("Email sent to %s: %s", to, subject)
            return True
        logger.error("Resend HTTP %s stderr=%s", status, result.stderr)
        return False
    except Exception as e:
        logger.error("Failed to send email to %s: %s", to, e)
        return False


def send_welcome_email(name: str, email: str, company: str, api_key: str, trial_end: datetime) -> bool:
    end_str = trial_end.strftime("%B %d, %Y")
    first = name.split()[0]
    html = f"""
<div style="font-family:Inter,sans-serif;max-width:600px;margin:0 auto;background:#030d1a;color:#ddeaf6;padding:2rem;border-radius:12px">
  <div style="margin-bottom:1.5rem">
    <span style="font-size:1.4rem;font-weight:800;color:#fff">Auto<span style="color:#00ccdd">PIL</span></span>
    <span style="font-size:0.75rem;color:#7a9ab5;margin-left:0.5rem">Platform Intelligence Layer</span>
  </div>
  <h2 style="color:#fff;margin-bottom:0.5rem">Your trial is ready, {first}.</h2>
  <p style="color:#7a9ab5">Context governance for AI agents — active through <strong style="color:#ddeaf6">{end_str}</strong>.</p>
  <div style="background:rgba(0,204,221,0.06);border:1px solid rgba(0,204,221,0.2);border-radius:8px;padding:1.25rem;margin:1.5rem 0">
    <p style="margin:0 0 0.4rem;font-size:0.82rem;color:#7a9ab5;text-transform:uppercase;letter-spacing:0.05em">Dashboard</p>
    <a href="{TRIAL_BASE_URL}" style="color:#00ccdd;font-weight:600">{TRIAL_BASE_URL}</a>
    <p style="margin:1rem 0 0.4rem;font-size:0.82rem;color:#7a9ab5;text-transform:uppercase;letter-spacing:0.05em">API Key</p>
    <code style="font-family:monospace;font-size:0.85rem;color:#00ccdd;word-break:break-all">{api_key}</code>
    <p style="margin:0.3rem 0 0;font-size:0.75rem;color:#7a9ab5">Save this — it will not be shown again.</p>
  </div>
  <h3 style="color:#fff;margin:1.5rem 0 0.75rem">Get started in 3 steps</h3>
  <ol style="color:#7a9ab5;padding-left:1.25rem;line-height:2.2">
    <li>Open the dashboard above — demo data is already loaded</li>
    <li>Call <code style="color:#00ccdd">POST /v1/context/evaluate</code> with your API key in <code style="color:#00ccdd">X-API-Key</code></li>
    <li>Explore the audit log, policy editor, and catalog health panels</li>
  </ol>
  <p style="color:#7a9ab5;font-size:0.85rem;margin-top:2rem">
    Questions? Reply to this email or reach us at
    <a href="mailto:anil@vibrantcapital.ai" style="color:#00ccdd">anil@vibrantcapital.ai</a>
  </p>
  <p style="color:#3d5a72;font-size:0.75rem;margin-top:1.5rem">AutoPIL &mdash; {company} trial &middot; Expires {end_str}</p>
</div>
"""
    return _send_resend(email, "Your AutoPIL trial is ready", html)


def send_day7_email(name: str, email: str, trial_end: datetime) -> bool:
    end_str = trial_end.strftime("%B %d, %Y")
    first = name.split()[0]
    html = f"""
<div style="font-family:Inter,sans-serif;max-width:600px;margin:0 auto;background:#030d1a;color:#ddeaf6;padding:2rem;border-radius:12px">
  <div style="margin-bottom:1.5rem">
    <span style="font-size:1.4rem;font-weight:800;color:#fff">Auto<span style="color:#00ccdd">PIL</span></span>
  </div>
  <h2 style="color:#fff">8 days left in your trial, {first}.</h2>
  <p style="color:#7a9ab5">Your AutoPIL trial is active through <strong style="color:#ddeaf6">{end_str}</strong>. Here's what to explore before it ends:</p>
  <ul style="color:#7a9ab5;padding-left:1.25rem;line-height:2.2">
    <li>Connect a real catalog (Unity Catalog, Collibra, or Purview)</li>
    <li>Create a custom policy for your most sensitive data domains</li>
    <li>Set up an alert rule to notify on high-sensitivity access</li>
    <li>Export the audit log and share it with your compliance team</li>
  </ul>
  <p style="color:#7a9ab5;margin-top:1.5rem">
    Want to talk through your use case?
    <a href="mailto:anil@vibrantcapital.ai" style="color:#00ccdd;font-weight:600">Book a call &rarr;</a>
  </p>
  <p style="color:#3d5a72;font-size:0.75rem;margin-top:1.5rem">AutoPIL &middot; Trial expires {end_str}</p>
</div>
"""
    return _send_resend(email, "8 days left in your AutoPIL trial", html)


def send_day13_email(name: str, email: str) -> bool:
    first = name.split()[0]
    html = f"""
<div style="font-family:Inter,sans-serif;max-width:600px;margin:0 auto;background:#030d1a;color:#ddeaf6;padding:2rem;border-radius:12px">
  <div style="margin-bottom:1.5rem">
    <span style="font-size:1.4rem;font-weight:800;color:#fff">Auto<span style="color:#00ccdd">PIL</span></span>
  </div>
  <h2 style="color:#fff">Your trial ends in 2 days, {first}.</h2>
  <p style="color:#7a9ab5">Your AutoPIL trial expires in 2 days. If you'd like to continue, let's talk about next steps.</p>
  <p style="margin:1.5rem 0">
    <a href="mailto:anil@vibrantcapital.ai" style="color:#00ccdd;font-weight:700;font-size:1rem">Schedule a call &rarr;</a>
  </p>
  <p style="color:#7a9ab5;font-size:0.9rem">We can extend your trial or walk through a production deployment plan — whatever is most useful for your team.</p>
  <p style="color:#3d5a72;font-size:0.75rem;margin-top:1.5rem">AutoPIL &middot; Reply to this email anytime</p>
</div>
"""
    return _send_resend(email, "Your AutoPIL trial ends in 2 days", html)


# ── seed data ──────────────────────────────────────────────────────────────────

_DEMO_POLICIES = [
    {
        "name":             "block_pii_external",
        "agent_role":       "risk_agent",
        "allowed_sources":  [],
        "denied_sources":   ["customer_pii", "hr_db", "payments_db"],
        "max_sensitivity":  "medium",
        "allowed_tasks":    [],
        "denied_tasks":     [],
        "industry":         "financial_services",
        "category":         "data_access",
    },
    {
        "name":             "analyst_read_only",
        "agent_role":       "analyst",
        "allowed_sources":  ["transactions_db", "portfolio_db", "risk_db", "credit_db", "support_db"],
        "denied_sources":   [],
        "max_sensitivity":  "high",
        "allowed_tasks":    [],
        "denied_tasks":     ["export"],
        "industry":         "financial_services",
        "category":         "role_based",
    },
    {
        "name":             "compliance_audit_trail",
        "agent_role":       "compliance_agent",
        "allowed_sources":  ["compliance_db", "trading_db", "transactions_db"],
        "denied_sources":   [],
        "max_sensitivity":  "high",
        "allowed_tasks":    [],
        "denied_tasks":     [],
        "industry":         "financial_services",
        "category":         "compliance",
    },
]

_DEMO_EVENTS = [
    ("Customer transaction patterns for Q4",          "analyst",          "u001", "transactions_db", "medium",   "ALLOW", "analyst_read_only",      "Access permitted"),
    ("Full SSN and account numbers for risk review",  "risk_agent",       "u002", "customer_pii",    "critical", "DENY",  "block_pii_external",     "PII cannot be accessed by external agents"),
    ("Portfolio performance — top 100 clients",       "analyst",          "u003", "portfolio_db",    "medium",   "ALLOW", "analyst_read_only",      "Access permitted"),
    ("Export complete customer list with contacts",   "export_agent",     "u004", "customer_db",     "high",     "DENY",  "analyst_read_only",      "Export agents cannot access high-sensitivity data"),
    ("Regulatory filings due this quarter",           "compliance_agent", "u005", "compliance_db",   "low",      "ALLOW", "compliance_audit_trail", "Access permitted — compliance agent"),
    ("Trading history for suspicious accounts",       "risk_agent",       "u006", "trading_db",      "high",     "ALLOW", "analyst_read_only",      "Access permitted — risk agent scope"),
    ("Customer credit score summary",                 "credit_agent",     "u007", "credit_db",       "high",     "ALLOW", "analyst_read_only",      "Access permitted — credit agent scope"),
    ("Employee salary records",                       "hr_agent",         "u008", "hr_db",           "critical", "DENY",  "block_pii_external",     "PII cannot be accessed by external agents"),
    ("Anonymized transaction data for ML training",   "ml_agent",         "u009", "transactions_db", "low",      "ALLOW", "compliance_audit_trail", "Access permitted — anonymized data"),
    ("Customer complaint history",                    "support_agent",    "u010", "support_db",      "medium",   "ALLOW", "analyst_read_only",      "Access permitted — support agent scope"),
    ("Payment card numbers for fraud detection",      "fraud_agent",      "u011", "payments_db",     "critical", "DENY",  "block_pii_external",     "PII cannot be accessed by external agents"),
    ("Market risk exposure summary",                  "risk_agent",       "u012", "risk_db",         "high",     "ALLOW", "analyst_read_only",      "Access permitted — risk agent scope"),
]


def seed_demo_data(tenant_id: str, industry: str, audit_log, policy_store) -> None:
    """Seed demo policies and 96 audit events into the trial tenant."""
    try:
        for pol in _DEMO_POLICIES:
            try:
                policy_store.upsert({**pol}, tenant_id=tenant_id, changed_by="trial_seed")
            except Exception as e:
                logger.warning("Policy seed failed (%s): %s", pol["name"], e)

        base_time = datetime.now(timezone.utc) - timedelta(days=7)
        session_id = str(uuid.uuid4())
        from autopil.models import AuditEvent, Decision

        for repeat in range(8):
            for i, (query, role, user_id, source_id, sensitivity, decision, policy_name, reason) in enumerate(_DEMO_EVENTS):
                event = AuditEvent(
                    event_id=str(uuid.uuid4()),
                    session_id=session_id if (repeat * 12 + i) % 6 != 0 else str(uuid.uuid4()),
                    agent_role=role,
                    user_id=user_id,
                    source_id=source_id,
                    query=query,
                    decision=Decision.ALLOW if decision == "ALLOW" else Decision.DENY,
                    policy_name=policy_name,
                    reason=reason,
                    context_hash=None,
                    timestamp=(base_time + timedelta(hours=(repeat * 12 + i) * 2)).isoformat(),
                    sensitivity_level=sensitivity,
                    source_type="rest",
                    catalog_enriched=False,
                )
                try:
                    audit_log.record(event, tenant_id=tenant_id)
                except Exception as e:
                    logger.warning("Audit seed failed: %s", e)

        logger.info("Demo data seeded for tenant %s (%d events)", tenant_id, 8 * len(_DEMO_EVENTS))
    except Exception as e:
        logger.error("Seed failed for tenant %s: %s", tenant_id, e)


# ── background workers ─────────────────────────────────────────────────────────

def _cleanup_loop(trial_store, tenant_store, interval_hours: int = 24) -> None:
    while True:
        try:
            expired = trial_store.expire_trials(before=datetime.now(timezone.utc))
            for tenant_id in expired:
                try:
                    tenant_store.deactivate_tenant(tenant_id)
                    logger.info("Trial expired — deactivated tenant %s", tenant_id)
                except Exception as e:
                    logger.error("Failed to deactivate tenant %s: %s", tenant_id, e)
        except Exception as e:
            logger.error("TTL cleanup error: %s", e)
        time.sleep(interval_hours * 3600)


def _drip_loop(trial_store, interval_hours: int = 12) -> None:
    while True:
        try:
            now = datetime.now(timezone.utc)
            for trial in trial_store.list_active_trials():
                try:
                    trial_end_raw = trial["trial_end"]
                    if isinstance(trial_end_raw, datetime):
                        trial_end = trial_end_raw
                    else:
                        trial_end = datetime.fromisoformat(str(trial_end_raw).replace("Z", "+00:00"))
                    if trial_end.tzinfo is None:
                        trial_end = trial_end.replace(tzinfo=timezone.utc)
                    days_left = (trial_end - now).days
                    if days_left <= 8 and not trial.get("email_day7_sent"):
                        if send_day7_email(trial["name"], trial["email"], trial_end):
                            trial_store.mark_email_sent(trial["trial_id"], "day7")
                    if days_left <= 2 and not trial.get("email_day13_sent"):
                        if send_day13_email(trial["name"], trial["email"]):
                            trial_store.mark_email_sent(trial["trial_id"], "day13")
                except Exception as e:
                    logger.error("Drip error for trial %s: %s", trial.get("trial_id"), e)
        except Exception as e:
            logger.error("Drip loop error: %s", e)
        time.sleep(interval_hours * 3600)


def start_background_workers(trial_store, tenant_store) -> None:
    """Start TTL cleanup and drip email background threads. Call once on startup."""
    threading.Thread(target=_cleanup_loop, args=(trial_store, tenant_store), daemon=True, name="trial-ttl").start()
    threading.Thread(target=_drip_loop, args=(trial_store,), daemon=True, name="trial-drip").start()
    logger.info("Trial background workers started")
