"""Smartlead cold-email logic for the jarvis-tools service (Railway).
Key from env SMARTLEAD_API_KEY. Env-based so every device reaches it via the
one connector. Isolated from the memory service (no ML deps).
"""
from __future__ import annotations

import json
import os
import urllib.error
import urllib.request

_BASE = os.environ.get("SMARTLEAD_URL",
                       "https://server.smartlead.ai/api/v1").rstrip("/")
_UA = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
       "(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36")


def configured() -> bool:
    return bool(os.environ.get("SMARTLEAD_API_KEY", ""))


def _api(method: str, path: str, body=None, timeout: int = 30):
    key = os.environ.get("SMARTLEAD_API_KEY", "")
    if not path.startswith("/"):
        path = "/" + path
    sep = "&" if "?" in path else "?"
    url = f"{_BASE}{path}{sep}api_key={key}"
    data = json.dumps(body).encode() if body is not None else None
    req = urllib.request.Request(url, data=data, method=method)
    req.add_header("Content-Type", "application/json")
    req.add_header("User-Agent", _UA)     # Smartlead's Cloudflare 403s Python-urllib
    req.add_header("Accept", "application/json")
    try:
        with urllib.request.urlopen(req, timeout=timeout) as r:
            raw = r.read()
    except urllib.error.HTTPError as e:
        raise RuntimeError(f"HTTP {e.code}: {e.read()[:400].decode('utf-8','ignore')}")
    return json.loads(raw) if raw else {}


def _campaign_id(ref: str) -> str | None:
    ref = str(ref).strip()
    if not ref:
        return None
    if ref.isdigit():
        return ref
    try:
        camps = _api("GET", "/campaigns") or []
        for c in camps:
            if str(c.get("name", "")).lower() == ref.lower():
                return str(c.get("id"))
        for c in camps:
            if ref.lower() in str(c.get("name", "")).lower():
                return str(c.get("id"))
    except Exception:  # noqa: BLE001
        return None
    return None


def campaigns() -> str:
    camps = _api("GET", "/campaigns")
    if not camps:
        return "No campaigns yet (sender inboxes are ready, nothing running)."
    return f"{len(camps)} campaign(s):\n" + "\n".join(
        f"- [{c.get('id')}] {c.get('name')!r} — {c.get('status')}" for c in camps)


def campaign_stats(campaign: str) -> str:
    cid = _campaign_id(campaign)
    if not cid:
        return "Campaign not found — list campaigns first."
    a = _api("GET", f"/campaigns/{cid}/analytics")
    g = lambda k: a.get(k, 0)  # noqa: E731
    return (f"Campaign {a.get('name', cid)}: sent {g('sent_count')}, opened "
            f"{g('open_count')}, replied {g('reply_count')}, bounced "
            f"{g('bounce_count')}, unsubscribed {g('unsubscribed_count')}.")


def senders() -> str:
    accs = _api("GET", "/email-accounts/?offset=0&limit=100")
    if not accs:
        return "No sender inboxes configured."
    lines = []
    for e in accs:
        wu = e.get("warmup_details") or {}
        lines.append(f"- {e.get('from_email')} — reputation "
                     f"{wu.get('warmup_reputation', 'n/a')}, "
                     f"{e.get('message_per_day', '?')}/day, "
                     f"warmup {'on' if e.get('is_warmup_enabled') else 'off'}")
    return f"{len(accs)} inbox(es):\n" + "\n".join(lines)


def create_campaign(name: str) -> str:
    name = str(name).strip()
    if not name:
        return "create_campaign failed: need a name."
    out = _api("POST", "/campaigns/create", {"name": name})
    return f"Created campaign {name!r} (id {out.get('id') or out.get('campaign_id')})."


def set_sequence(campaign: str, sequence_json: str) -> str:
    cid = _campaign_id(campaign)
    if not cid:
        return "Campaign not found."
    try:
        seqs = json.loads(sequence_json)
    except Exception as e:  # noqa: BLE001
        return f"sequence_json isn't valid JSON: {str(e)[:120]}"
    _api("POST", f"/campaigns/{cid}/sequences", {"sequences": seqs})
    return f"Saved a {len(seqs)}-step sequence on campaign {cid}."


def add_leads(campaign: str, leads_json: str) -> str:
    cid = _campaign_id(campaign)
    if not cid:
        return "Campaign not found."
    try:
        leads = json.loads(leads_json)
    except Exception as e:  # noqa: BLE001
        return f"leads_json isn't valid JSON: {str(e)[:120]}"
    if not leads:
        return "No leads to add."
    out = _api("POST", f"/campaigns/{cid}/leads", {"lead_list": leads[:100]})
    up = out.get("upload_count", out.get("total_leads", len(leads)))
    return f"Added {up} lead(s) to campaign {cid}."


def campaign_control(campaign: str, action: str) -> str:
    cid = _campaign_id(campaign)
    if not cid:
        return "Campaign not found."
    status = {"start": "START", "pause": "PAUSED", "stop": "STOPPED"}.get(
        str(action).lower())
    if not status:
        return "action must be start, pause, or stop."
    _api("POST", f"/campaigns/{cid}/status", {"status": status})
    return f"Campaign {cid} → {status}."


def raw(method: str, path: str, body_json: str = "") -> str:
    body = None
    if body_json:
        try:
            body = json.loads(body_json)
        except Exception as e:  # noqa: BLE001
            return f"body_json isn't valid JSON: {str(e)[:120]}"
    out = _api(str(method).upper(), str(path), body)
    s = json.dumps(out, ensure_ascii=False)
    return s[:4000] + (" …[truncated]" if len(s) > 4000 else "")
