// dashboard-workflow-wizard-generic-for-al.js — extracted verbatim from dashboard.js (pure move).

// ── Workflow Wizard (generic for all workflow types) ──────────────

// \u2500\u2500 OPERATIONS REGISTRY \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
// Single source of truth for everything the system can DO. Replaces the
// fragmented entry points (wizard intent groups, picker cards, in-page panel
// actions, sidebar launchers). Each entry feeds the Operations Center catalog
// AND drives the unified launch flow (Account picker \u2192 Configure \u2192 Launch).
//
// Tag taxonomy (filter lenses, multi-tag \u2014 an op can have many):
//   \u2022 "multi-account"   \u2014 can fan out across multiple accounts on the same platform
//   \u2022 "passive"         \u2014 always-on / scheduled (warmup, autoreply, listener)
//   \u2022 "single-platform" \u2014 touches only one platform
//   \u2022 "multi-step"      \u2014 sequenced or multi-stage execution
//   \u2022 "cross-platform"  \u2014 coordinates across LI + X + Email + TG
//
// accountMode:
//   "multi"  \u2014 user selects N accounts in the AccountPicker step
//   "single" \u2014 user selects exactly 1 account (DM/email per-account ops)
//   "none"   \u2014 operation doesn't bind to a specific account (e.g., signal pursuit)
//
// Launch contracts:
//   templateKey  \u2014 reuse WORKFLOW_TYPES[key].fields for the configure step,
//                  submit via api("workflow-create", { type, name, config, accountIds })
//   route        \u2014 instead of the unified flow, deep-link into an existing dedicated page
//                  (used during transition for ops that aren't yet subsumed)
const OPERATIONS = [
  // \u2500\u2500 Cross-platform multi-step outreach (existing WORKFLOW_TYPES) \u2500\u2500
  {
    id: "service_outreach",
    label: "Service Outreach",
    icon: "\u{1f3af}",
    description: "Find companies that need your services across X + LinkedIn + Email",
    tags: ["multi-account", "multi-step", "cross-platform"],
    platforms: ["twitter", "linkedin", "email"],
    accountMode: "multi",
    templateKey: "service_outreach",
  },
  {
    id: "hiring_outreach",
    label: "Hiring Outreach",
    icon: "\u{1f4bc}",
    description: "Target companies actively hiring roles you serve",
    tags: ["multi-account", "multi-step", "cross-platform"],
    platforms: ["twitter", "linkedin", "email"],
    accountMode: "multi",
    templateKey: "hiring_outreach",
  },
  {
    id: "competitor_targeting",
    label: "Competitor Targeting",
    icon: "\u{1f575}\ufe0f",
    description: "Steal a competitor's audience by engaging their followers",
    tags: ["multi-account", "multi-step", "cross-platform"],
    platforms: ["twitter", "linkedin"],
    accountMode: "multi",
    templateKey: "competitor_targeting",
  },
  {
    id: "geo_outreach",
    label: "Geo Outreach",
    icon: "\u{1f30d}",
    description: "Target a specific city or region",
    tags: ["multi-account", "multi-step", "cross-platform"],
    platforms: ["twitter", "linkedin", "email"],
    accountMode: "multi",
    templateKey: "geo_outreach",
  },
  {
    id: "new_token_outreach",
    label: "New Token Outreach",
    icon: "\u{1f680}",
    description: "Target freshly-listed crypto tokens",
    tags: ["multi-account", "multi-step", "cross-platform"],
    platforms: ["twitter", "linkedin"],
    accountMode: "multi",
    templateKey: "new_token_outreach",
  },
  {
    id: "event_promotion",
    label: "Event Promotion",
    icon: "\u{1f389}",
    description: "Invite people to your event across channels",
    tags: ["multi-account", "multi-step", "cross-platform"],
    platforms: ["twitter", "linkedin", "telegram", "email"],
    accountMode: "multi",
    templateKey: "event_promotion",
  },
  {
    id: "content_amplification",
    label: "Content Amplification",
    icon: "\u{1f4e3}",
    description: "Spread your content to relevant audiences",
    tags: ["multi-account", "multi-step", "cross-platform"],
    platforms: ["twitter", "linkedin"],
    accountMode: "multi",
    templateKey: "content_amplification",
  },
  {
    id: "comment_campaign",
    label: "Comment Campaign",
    icon: "\u{1f4ac}",
    description: "AI-engage posts by keyword on X + LinkedIn",
    tags: ["multi-account", "single-platform"],
    platforms: ["twitter", "linkedin"],
    accountMode: "multi",
    templateKey: "comment_campaign",
  },
  {
    id: "group_amplification",
    label: "Group Amplification",
    icon: "\u{1f4e2}",
    description: "Post & engage in target Telegram groups",
    tags: ["multi-account", "passive", "single-platform"],
    platforms: ["telegram"],
    accountMode: "multi",
    templateKey: "group_amplification",
  },
  {
    id: "crm_campaign",
    label: "CRM Campaign",
    icon: "\u{1f5c2}",
    description: "Direct outreach to filtered CRM contacts",
    tags: ["multi-step", "cross-platform"],
    platforms: ["telegram", "email", "twitter", "linkedin"],
    accountMode: "multi",
    templateKey: "crm_campaign",
  },

  // \u2500\u2500 Direct-channel campaigns (existing dedicated routes) \u2500\u2500
  {
    id: "telegram_dm",
    label: "Telegram DM Campaign",
    icon: "\u{1f4e8}",
    description: "Send personalized DMs to Telegram contacts",
    tags: ["multi-account", "single-platform"],
    platforms: ["telegram"],
    accountMode: "single",
    route: "new-dm-campaign",
  },
  {
    id: "email_campaign",
    label: "Email Campaign",
    icon: "\u2709\ufe0f",
    description: "One-off email send to a list",
    tags: ["single-platform"],
    platforms: ["email"],
    accountMode: "single",
    route: "new-email-campaign",
  },
  {
    id: "email_sequence",
    label: "Email Sequence",
    icon: "\u{1f504}",
    description: "Multi-step drip with timed delays",
    tags: ["passive", "multi-step", "single-platform"],
    platforms: ["email"],
    accountMode: "single",
    route: "email/sequences",
  },

  // \u2500\u2500 Passive always-on operations \u2500\u2500
  {
    id: "email_warmup",
    label: "Email Warmup",
    icon: "\u{1f525}",
    description: "Gradually increase send volume to avoid spam filters",
    tags: ["passive", "single-platform", "multi-account"],
    platforms: ["email"],
    accountMode: "multi",
    route: "email/warmup",
  },
  {
    id: "tg_autoreply",
    label: "Telegram Auto-Reply",
    icon: "\u{1f916}",
    description: "AI-respond to incoming Telegram DMs while you're away",
    tags: ["passive", "single-platform", "multi-account"],
    platforms: ["telegram"],
    accountMode: "multi",
    route: "telegram/autoreply",
  },
  {
    id: "tg_passive_listener",
    label: "Group Listener",
    icon: "\u{1f441}",
    description: "Passively monitor Telegram groups for keyword triggers",
    tags: ["passive", "single-platform"],
    platforms: ["telegram"],
    accountMode: "multi",
    route: "telegram/passive",
  },
  {
    id: "tg_active_member",
    label: "Active Member",
    icon: "\u{1f4ac}",
    description: "AI engagement in Telegram groups to build presence",
    tags: ["passive", "single-platform", "multi-account"],
    platforms: ["telegram"],
    accountMode: "multi",
    route: "telegram/activemember",
  },
  {
    id: "tg_stories",
    label: "Story Rotator",
    icon: "\u{1f4f8}",
    description: "Auto-rotate Telegram stories on a schedule",
    tags: ["passive", "single-platform"],
    platforms: ["telegram"],
    accountMode: "multi",
    route: "telegram/stories",
  },
  {
    id: "tg_forward",
    label: "Forward Rules",
    icon: "\u27a1",
    description: "Auto-forward Telegram messages by keyword",
    tags: ["passive", "single-platform"],
    platforms: ["telegram"],
    accountMode: "multi",
    route: "telegram/forward",
  },

  // \u2500\u2500 Single-platform native ops \u2500\u2500
  {
    id: "tg_broadcast",
    label: "Telegram Broadcast",
    icon: "\u{1f4e2}",
    description: "Post the same message to many Telegram groups at once",
    tags: ["multi-account", "single-platform"],
    platforms: ["telegram"],
    accountMode: "multi",
    route: "telegram/broadcast",
  },
  {
    id: "tg_mass_invite",
    label: "Mass Invite",
    icon: "\u{1f4e5}",
    description: "Bulk invite users to your Telegram group",
    tags: ["multi-account", "single-platform"],
    platforms: ["telegram"],
    accountMode: "multi",
    route: "telegram/invite",
  },
  {
    id: "tg_smart_scrape",
    label: "Smart Scrape",
    icon: "\u{1f9f2}",
    description: "Scrape members from target Telegram groups",
    tags: ["single-platform"],
    platforms: ["telegram"],
    accountMode: "single",
    route: "telegram/scrape",
  },
  {
    id: "vc_outreach",
    label: "VC / Investor Outreach",
    icon: "\u{1f3db}",
    description: "Partner-specific pitch to VC fund partners",
    tags: ["multi-step", "cross-platform"],
    platforms: ["twitter", "linkedin", "email"],
    accountMode: "multi",
    route: "vc",
  },
  {
    id: "signal_pursue",
    label: "Pursue Signals",
    icon: "\u{1f525}",
    description: "AI-engage on detected buying signals",
    tags: ["passive", "cross-platform"],
    platforms: ["twitter", "linkedin"],
    accountMode: "none",
    route: "signals",
  },
  {
    id: "import_csv",
    label: "Import Contacts (CSV)",
    icon: "\u{1f4e5}",
    description: "Bulk-load contacts from a CSV into the CRM",
    tags: [],
    platforms: [],
    accountMode: "none",
    route: "import",
  },
];

// Convenience lookup
function findOperation(opId) {
  return OPERATIONS.find((o) => o.id === opId) || null;
}

// Operations whose schema is configured but the periodic engine isn't wired.
// Source of truth: nexus-bot/src/api/telegram-features-routes.js WORKFLOW_EXPLAINERS
// (engineMode === "stub"). Picking these from the catalog still saves config,
// but nothing periodic processes them — surfaced as a "Preview" badge so users
// don't expect auto-execution. Keep in sync with the API map.
//
// Phase O: the 5 originally-stub OPERATIONS are now wired as composer templates
// (hiring_outreach.json, competitor_targeting.json, geo_outreach.json,
// content_amplification.json, crm_campaign.json) — pick them from the Build
// page's templates picker. The set is empty so the "Preview" badge no longer
// appears for any OPERATION.
const STUB_OPERATION_IDS = new Set([]);
function isOperationStub(opId) {
  return STUB_OPERATION_IDS.has(opId);
}

// All distinct tags, in display order (used for filter chips)
const OPERATION_TAGS = [
  "multi-account",
  "passive",
  "single-platform",
  "multi-step",
  "cross-platform",
];

const WORKFLOW_TYPES = {
  service_outreach: {
    title: "Service Outreach",
    icon: "\ud83c\udfaf",
    fields: [
      {
        key: "serviceType",
        label: "Your service type",
        placeholder: "e.g. marketing, development, consulting",
      },
      {
        key: "roleKeywords",
        label: "Target role keywords",
        placeholder: "e.g. CEO, CTO, Head of Marketing",
      },
      {
        key: "fundingFilter",
        label: "Funding stage filter",
        placeholder: "e.g. seed, series_a, series_b (or leave blank for all)",
        optional: true,
      },
      {
        key: "freshnessFilter",
        label: "Max days since last funding round",
        placeholder: "e.g. 90",
        type: "number",
        optional: true,
      },
    ],
  },
  hiring_outreach: {
    title: "Hiring Outreach",
    icon: "\ud83d\udcbc",
    fields: [
      {
        key: "roleKeywords",
        label: "Roles they're hiring for",
        placeholder: "e.g. BD, marketing, solidity developer",
      },
      {
        key: "fundingFilter",
        label: "Funding stage",
        placeholder: "e.g. seed, series_a",
        optional: true,
      },
    ],
  },
  competitor_targeting: {
    title: "Competitor Targeting",
    icon: "\ud83d\udd75\ufe0f",
    fields: [
      {
        key: "competitors",
        label: "Competitor names or handles",
        placeholder: "e.g. CompetitorCo, @their_handle",
      },
      {
        key: "pitch",
        label: "Why you're better (pitch angle)",
        placeholder: "e.g. We offer X that they don't\u2026",
      },
    ],
  },
  geo_outreach: {
    title: "Geo Outreach",
    icon: "\ud83c\udf0d",
    fields: [
      { key: "city", label: "Target city/region", placeholder: "e.g. Lisbon, Dubai, Singapore" },
      {
        key: "sector",
        label: "Sector filter",
        placeholder: "e.g. defi, gaming, infrastructure",
        optional: true,
      },
    ],
  },
  new_token_outreach: {
    title: "New Token Outreach",
    icon: "\ud83d\ude80",
    fields: [
      {
        key: "minMarketCap",
        label: "Min market cap ($)",
        placeholder: "e.g. 1000000",
        type: "number",
        optional: true,
      },
      { key: "maxAge", label: "Max listing age (days)", placeholder: "e.g. 30", type: "number" },
    ],
  },
  event_promotion: {
    title: "Event Promotion",
    icon: "\ud83c\udf89",
    fields: [
      { key: "eventName", label: "Event name", placeholder: "e.g. Web3 Summit Lisbon" },
      { key: "eventDate", label: "Event date", placeholder: "e.g. 2026-05-15" },
      {
        key: "eventUrl",
        label: "Event URL",
        placeholder: "https://lu.ma/your-event",
        optional: true,
      },
      {
        key: "targetAudience",
        label: "Target audience",
        placeholder: "e.g. crypto founders, VCs, developers",
      },
    ],
  },
  content_amplification: {
    title: "Content Amplification",
    icon: "\ud83d\udce3",
    fields: [
      { key: "contentUrl", label: "Content URL", placeholder: "https://your-blog.com/article" },
      {
        key: "targetKeywords",
        label: "Target audience keywords",
        placeholder: "e.g. defi, yield farming, liquidity",
      },
    ],
  },
  comment_campaign: {
    title: "Comment Campaign",
    icon: "\ud83d\udcac",
    fields: [
      {
        key: "keywords",
        label: "Search keywords (comma-separated)",
        placeholder: "e.g. hiring web3, looking for CRM, need outreach tool",
      },
      {
        key: "commentAngle",
        label: "Comment angle / tone",
        placeholder: "e.g. Helpful expert offering to assist",
      },
      {
        key: "promotionPitch",
        label: "Your pitch (mentioned subtly in comments)",
        placeholder: "e.g. I run a tool that helps with this\u2026",
      },
      {
        key: "platform",
        label: "Platform",
        type: "select",
        options: ["twitter", "linkedin", "both"],
      },
    ],
  },
  group_amplification: {
    title: "Group Amplification",
    icon: "\ud83d\udce2",
    fields: [
      {
        key: "promotionPitch",
        label: "Promotion pitch",
        placeholder: "Your message to post in groups\u2026",
      },
      {
        key: "mode",
        label: "Mode",
        type: "select",
        options: ["post_boost", "listen_reply", "both"],
      },
      {
        key: "dailyPostsPerAccount",
        label: "Daily posts per account",
        type: "number",
        placeholder: "3",
      },
      {
        key: "dailyRepliesPerAccount",
        label: "Daily replies per account",
        type: "number",
        placeholder: "5",
      },
    ],
  },
  crm_campaign: {
    title: "CRM Campaign",
    icon: "\ud83d\uddc2",
    fields: [
      {
        key: "stageFilter",
        label: "Contact stage filter",
        type: "select",
        options: ["all", "cold", "contacted", "warm", "hot"],
      },
      {
        key: "sectorFilter",
        label: "Sector filter",
        placeholder: "e.g. defi, infrastructure (or blank for all)",
        optional: true,
      },
      {
        key: "tagFilter",
        label: "Tag filter",
        placeholder: "e.g. conference_speaker, recently_funded",
        optional: true,
      },
      {
        key: "messageTemplate",
        label: "Message template",
        placeholder: "Hi {name}, I noticed you work at {company}\u2026",
        textarea: true,
      },
    ],
  },
};

let dmWizard = {
  name: "",
  template: "",
  targetSource: "crm",
  manualRecipients: "",
  dailyLimit: 30,
  accountId: "",
};

async function renderNewDmCampaign() {
  // Load accounts for the selector
  const accountsData = await api("accounts-all").catch(() => ({}));
  const tgAccounts = accountsData?.telegram || [];

  const content = el("div", { class: "wizard" }, [
    el("div", { class: "page-header" }, [
      el("div", {}, [
        el(
          "button",
          { class: "btn btn-secondary btn-tiny", onclick: () => navigate("operations") },
          "\u00ab Back",
        ),
        el("div", { class: "page-title", style: "margin-top: 10px;" }, "New Telegram DM Campaign"),
      ]),
    ]),
    el("div", { class: "wizard-section" }, [
      el("div", { class: "wizard-section-title" }, "1. Campaign details"),
      el("div", { class: "wizard-label" }, "Campaign name"),
      el("input", {
        class: "wizard-input",
        id: "dm-name",
        placeholder: "e.g. Cold outreach March",
        value: dmWizard.name,
        oninput: (e) => {
          dmWizard.name = e.target.value;
        },
      }),
      el("div", { class: "wizard-label", style: "margin-top: 12px;" }, "Message template"),
      el(
        "div",
        { class: "muted small", style: "margin-bottom: 4px;" },
        "Variables: {name}, {username}, {group}",
      ),
      el(
        "textarea",
        {
          class: "wizard-textarea",
          id: "dm-template",
          placeholder: "Hey {name}! I noticed you're interested in...",
          oninput: (e) => {
            dmWizard.template = e.target.value;
          },
        },
        dmWizard.template,
      ),
      el("div", { class: "wizard-label", style: "margin-top: 12px;" }, "Daily limit"),
      el("input", {
        class: "wizard-input",
        id: "dm-limit",
        type: "number",
        value: String(dmWizard.dailyLimit),
        style: "width: 100px;",
        oninput: (e) => {
          dmWizard.dailyLimit = parseInt(e.target.value) || 30;
        },
      }),
    ]),
    el("div", { class: "wizard-section" }, [
      el("div", { class: "wizard-section-title" }, "2. Recipients"),
      el("div", { class: "row", style: "gap: 8px; margin-bottom: 12px;" }, [
        radioBtn("crm", "CRM contacts with Telegram", dmWizard.targetSource === "crm", () => {
          dmWizard.targetSource = "crm";
          renderNewDmCampaign();
        }),
        radioBtn("manual", "Manual usernames", dmWizard.targetSource === "manual", () => {
          dmWizard.targetSource = "manual";
          renderNewDmCampaign();
        }),
      ]),
      dmWizard.targetSource === "manual"
        ? el(
            "textarea",
            {
              class: "wizard-textarea",
              placeholder: "username1, username2, username3",
              oninput: (e) => {
                dmWizard.manualRecipients = e.target.value;
              },
            },
            dmWizard.manualRecipients,
          )
        : el(
            "div",
            { class: "muted small" },
            "Will send to all CRM contacts that have a Telegram username.",
          ),
    ]),
    el("div", { class: "wizard-section" }, [
      el("div", { class: "wizard-section-title" }, "3. Sending account"),
      tgAccounts.length > 0
        ? el(
            "select",
            {
              class: "filter-select",
              onchange: (e) => {
                dmWizard.accountId = e.target.value;
              },
            },
            [
              el("option", { value: "" }, "Auto-select best account"),
              ...tgAccounts
                .filter((a) => a.status === "active")
                .map((a) =>
                  el(
                    "option",
                    { value: String(a.id) },
                    `${a.label || a.phone} (health: ${a.health_score})`,
                  ),
                ),
            ],
          )
        : el(
            "div",
            { class: "muted small" },
            "No Telegram accounts yet. Use “+ Connect new Telegram account” to add one.",
          ),
    ]),
    el("div", { class: "wizard-actions" }, [
      el(
        "button",
        { class: "btn btn-primary", onclick: submitDmCampaign },
        "\ud83d\ude80 Create & Start",
      ),
      el(
        "button",
        { class: "btn btn-secondary", onclick: () => submitDmCampaign(false) },
        "Save as Draft",
      ),
      el("button", { class: "btn btn-secondary", onclick: () => navigate("campaigns") }, "Cancel"),
    ]),
  ]);
  setContentNode(content);
}

function radioBtn(value, label, checked, onclick) {
  return el(
    "button",
    {
      class: `btn btn-tiny ${checked ? "btn-primary" : "btn-secondary"}`,
      onclick,
    },
    label,
  );
}

async function submitDmCampaign(startImmediately = true) {
  if (!dmWizard.name || !dmWizard.template) {
    toast("Name and template are required", "err");
    return;
  }
  const body = {
    name: dmWizard.name,
    template: dmWizard.template,
    targetSource: dmWizard.targetSource,
    dailyLimit: dmWizard.dailyLimit,
    accountId: dmWizard.accountId || null,
    startImmediately,
  };
  if (dmWizard.targetSource === "manual" && dmWizard.manualRecipients) {
    body.recipients = dmWizard.manualRecipients
      .split(",")
      .map((u) => u.trim())
      .filter(Boolean)
      .map((u) => ({
        userId: "",
        username: u.replace(/^@/, ""),
        name: u.replace(/^@/, ""),
      }));
  }
  toast("Creating campaign\u2026", "info");
  const result = await api("campaign-dm-create", { body });
  if (result?.ok) {
    toast(
      `\u2705 Campaign #${result.campaignId} created (${result.recipientCount} recipients, ${result.status})`,
      "ok",
      6000,
    );
    dmWizard = {
      name: "",
      template: "",
      targetSource: "crm",
      manualRecipients: "",
      dailyLimit: 30,
      accountId: "",
    };
    navigate("campaigns");
  } else {
    toast(`\u274c ${result?.error || "creation failed"}`, "err");
  }
}
