/**
 * LinkedIn action registry — single source of truth for the
 * dashboard's Automations cards (and, later, the panel's config
 * forms once we lift them to this schema).
 *
 * Each entry describes:
 *   - id, title, hint                     — UI copy
 *   - category                            — group label in the card grid
 *   - limitsCategory                      — which /api/linkedin/limits-check
 *                                           category to gate by (so the card
 *                                           shows budget + disables on cap)
 *   - swAction                            — chrome.runtime message action
 *                                           the dashboard fires to start it
 *   - fields[]                            — config form schema (rendered as
 *                                           inputs in the dashboard modal)
 *   - needsLinkedInTab                    — true → spawns the worker tab
 *   - startUrl                            — the URL the worker tab navigates
 *                                           to before invoking the action
 *
 * Field shape:
 *   { id, label, type, default, min?, max?, placeholder?, hint?, options? }
 *   types: "number" | "text" | "textarea" | "boolean" | "select"
 *
 * Browser-only file — exposes window.LI_ACTION_REGISTRY.
 * Loaded BEFORE dashboard.js so the renderer can read it at module load.
 */

(function () {
  const COMMON_PLACEHOLDER_CHIPS = [
    "{firstName}", "{lastName}", "{name}",
    "{headline}", "{company}", "{hook}",
  ];

  const LI_ACTIONS = [
    {
      id: "accept-and-dm",
      title: "Accept & Message",
      hint: "Accept pending invites, optionally like their latest post, then send an AI-personalized DM. Every recipient gets a distinct variation.",
      category: "Outbound",
      limitsCategory: "message",
      swAction: "li-start-accept-and-dm-batch-bg",
      moduleMap: { nodes: [
        { id: "n1", type: "trigger.manual",     name: "User clicks Accept & Message" },
        { id: "n2", type: "browser.navigate",   name: "Open the invitation manager" },
        { id: "n3", type: "browser.scrape_invites", name: "Read pending invites" },
        { id: "n4", type: "logic.loop",          name: "For each invite (up to your max)" },
        { id: "n5", type: "logic.if",            name: "Skip senders who left no note (if enabled)" },
        { id: "n6", type: "browser.like_post",   name: "Like their latest post (if enabled)" },
        { id: "n7", type: "browser.accept_invite", name: "Accept the invite" },
        { id: "n8", type: "ai.generate_message", name: "AI-draft a personalized DM (1 of 12 variations)" },
        { id: "n9", type: "outreach.send_dm",    name: "Send the DM" },
        { id: "n10", type: "db.record_event",    name: "Log the accept + DM" },
      ] },
      needsLinkedInTab: true,
      startUrl: "https://www.linkedin.com/mynetwork/invitation-manager/received/",
      fields: [
        { id: "count",        label: "Max to process",         type: "number",   default: 15, min: 1, max: 25 },
        { id: "template",     label: "Message template",       type: "textarea",
          default: "",
          placeholder: "Hi {firstName}, thanks for connecting! {hook} Wanted to ...",
          chips: COMMON_PLACEHOLDER_CHIPS,
          hint: "12 AI variations are generated per batch; {hook} adds a 1-line per-recipient opener (slower but more personal).",
        },
        { id: "delay",        label: "Delay between people (sec)", type: "number", default: 6, min: 3, max: 60 },
        { id: "likeFirst",    label: "Like their latest post first", type: "boolean", default: true },
        { id: "skipNoMsg",    label: "Skip senders who left no note", type: "boolean", default: false },
      ],
      // The SW handler expects this exact config shape:
      configKey: "config",
      configMap: {
        count:     "maxProcess",
        template:  "template",
        delay:     "delayMs",        // multiplied by 1000 by the mapper
        likeFirst: "likeFirst",
        skipNoMsg: "skipNoMsg",
      },
      configTransform: (raw) => ({
        maxProcess: clampInt(raw.count, 15),
        template: String(raw.template || "").trim(),
        delayMs: (parseInt(raw.delay, 10) || 6) * 1000,
        likeFirst: !!raw.likeFirst,
        skipNoMsg: !!raw.skipNoMsg,
      }),
    },

    {
      id: "add-connections",
      title: "Add Connections",
      hint: "Search by keyword and bulk-send connection requests with a personalized note.",
      category: "Outbound",
      limitsCategory: "connect_request",
      swAction: "li-start-add-connections-bg",
      moduleMap: { nodes: [
        { id: "n1", type: "trigger.manual",     name: "User clicks Add Connections" },
        { id: "n2", type: "browser.navigate",   name: "Open people search for your keyword" },
        { id: "n3", type: "browser.scan_feed",   name: "Collect matching profiles" },
        { id: "n4", type: "logic.loop",          name: "For each profile (up to your count)" },
        { id: "n5", type: "logic.if",            name: "Headline-match / exclude-keyword filter" },
        { id: "n6", type: "browser.like_post",   name: "Like their latest activity (if enabled)" },
        { id: "n7", type: "browser.send_connect", name: "Send a connection request with your note" },
        { id: "n8", type: "db.record_event",     name: "Log the request" },
      ] },
      needsLinkedInTab: true,
      startUrl: "https://www.linkedin.com/search/results/people/",
      fields: [
        { id: "keyword",    label: "Search keyword",  type: "text",
          default: "CEO web3", placeholder: "CEO web3 DeFi crypto" },
        { id: "count",      label: "Connections to send", type: "number", default: 10, min: 1, max: 30 },
        { id: "degree2",    label: "Include 2nd-degree",  type: "boolean", default: true },
        { id: "degree3",    label: "Include 3rd+ degree", type: "boolean", default: false },
        { id: "message",    label: "Personal note (optional)", type: "textarea",
          default: "",
          placeholder: "Hi {firstName}! I'd love to connect...",
          chips: ["{firstName}", "{name}"],
          hint: "200-char limit. LinkedIn truncates anything longer.",
        },
        { id: "exclude",    label: "Exclude keywords",  type: "text",
          default: "", placeholder: "Marketing, Manager, John" },
        { id: "delay",      label: "Delay between people (sec)", type: "number", default: 3, min: 1, max: 30 },
        { id: "likeFirst",  label: "Like their latest activity first", type: "boolean", default: true },
        { id: "enrichFilter", label: "Filter by headline match", type: "boolean", default: false,
          hint: "Slower; skips profiles whose headline doesn't contain the keyword." },
      ],
      configTransform: (raw) => ({
        keyword: String(raw.keyword || "CEO web3").trim(),
        count: clampInt(raw.count, 10, 30),
        degree2: !!raw.degree2,
        degree3: !!raw.degree3,
        message: String(raw.message || "").trim() || null,
        exclude: String(raw.exclude || "").toLowerCase().split(",").map(s => s.trim()).filter(Boolean),
        delayMs: (parseInt(raw.delay, 10) || 3) * 1000,
        likeFirst: !!raw.likeFirst,
        enrichFilter: !!raw.enrichFilter,
      }),
    },

    {
      id: "like-posts",
      title: "Like Posts",
      hint: "Scroll the feed and like posts. Optional comment on every Nth one. Useful for engagement signal + visibility.",
      category: "Engagement",
      limitsCategory: "like",
      swAction: "li-start-like-posts-bg",
      moduleMap: { nodes: [
        { id: "n1", type: "trigger.manual",   name: "User clicks Like Posts" },
        { id: "n2", type: "browser.navigate", name: "Open your feed" },
        { id: "n3", type: "browser.scan_feed", name: "Scroll and read posts" },
        { id: "n4", type: "logic.loop",        name: "For each post (up to your count)" },
        { id: "n5", type: "logic.if",          name: "Keyword filter / comment every N" },
        { id: "n6", type: "browser.like_post", name: "Like it (and optionally comment)" },
        { id: "n7", type: "db.record_event",   name: "Log the like" },
      ] },
      needsLinkedInTab: true,
      startUrl: "https://www.linkedin.com/feed/",
      fields: [
        { id: "count",        label: "Posts to like", type: "number", default: 10, min: 1, max: 100 },
        { id: "keywordFilter", label: "Keyword filter (optional)", type: "text",
          default: "", placeholder: "crypto, web3, DeFi",
          hint: "Comma-separated. Only likes posts whose text contains one of these." },
        { id: "doComment",    label: "Also comment", type: "boolean", default: false },
        { id: "commentText",  label: "Comment text", type: "textarea",
          default: "", placeholder: "What you'd say", dependsOn: "doComment" },
        { id: "commentEveryN", label: "Comment every N posts", type: "number",
          default: 3, min: 1, max: 20, dependsOn: "doComment" },
      ],
      configTransform: (raw) => ({
        count: clampInt(raw.count, 10, 100),
        keywordFilter: String(raw.keywordFilter || "").toLowerCase().trim(),
        commentText: raw.doComment ? String(raw.commentText || "").trim() : "",
        commentEveryN: raw.doComment ? clampInt(raw.commentEveryN, 3, 20) : 0,
      }),
    },

    {
      id: "message-connections",
      title: "Message Connections",
      hint: "Bulk-DM 1st-degree connections with a template. AI variations + per-recipient hook supported.",
      category: "Outbound",
      limitsCategory: "message",
      swAction: "li-start-message-connections-bg",
      moduleMap: { nodes: [
        { id: "n1", type: "trigger.manual",     name: "User clicks Message Connections" },
        { id: "n2", type: "browser.navigate",   name: "Open your connections list" },
        { id: "n3", type: "logic.loop",          name: "For each connection (up to your count)" },
        { id: "n4", type: "ai.generate_message", name: "AI-draft a variation (if enabled)" },
        { id: "n5", type: "outreach.send_dm",    name: "Send the DM" },
        { id: "n6", type: "db.record_event",     name: "Log the message" },
      ] },
      needsLinkedInTab: true,
      startUrl: "https://www.linkedin.com/mynetwork/invite-connect/connections/",
      fields: [
        { id: "template",  label: "Message template", type: "textarea",
          default: "",
          placeholder: "Hi {firstName}, wanted to reach out about...",
          chips: COMMON_PLACEHOLDER_CHIPS,
          hint: "Reuses the same variation pool + per-recipient context as Accept & Message.",
        },
        { id: "count",     label: "Number of connections to message", type: "number", default: 10, min: 1, max: 30 },
        { id: "delay",     label: "Delay between people (sec)", type: "number", default: 6, min: 3, max: 60 },
        { id: "aiVariate", label: "Generate AI variations", type: "boolean", default: true },
      ],
      configTransform: (raw) => ({
        template: String(raw.template || "").trim(),
        count: clampInt(raw.count, 10, 30),
        delayMs: (parseInt(raw.delay, 10) || 6) * 1000,
        aiVariate: raw.aiVariate !== false,
      }),
    },

    {
      id: "accept-invites",
      title: "Accept Invites",
      hint: "Bulk-accept N pending invitations with no follow-up DM. Use Accept & Message if you want to send a DM.",
      category: "Cleanup",
      limitsCategory: "connect_request",
      swAction: "li-start-accept-invites-bg",
      moduleMap: { nodes: [
        { id: "n1", type: "trigger.manual",     name: "User clicks Accept Invites" },
        { id: "n2", type: "browser.navigate",   name: "Open the invitation manager" },
        { id: "n3", type: "browser.scrape_invites", name: "Read pending invites" },
        { id: "n4", type: "logic.loop",          name: "For each invite (up to your max)" },
        { id: "n5", type: "browser.accept_invite", name: "Accept it" },
        { id: "n6", type: "db.record_event",     name: "Log the accept" },
      ] },
      needsLinkedInTab: true,
      startUrl: "https://www.linkedin.com/mynetwork/invitation-manager/received/",
      fields: [
        { id: "count", label: "Max to accept", type: "number", default: 20, min: 1, max: 100 },
      ],
      configTransform: (raw) => ({
        count: clampInt(raw.count, 20, 100),
      }),
    },

    {
      id: "withdraw-invites",
      title: "Withdraw Sent Invites",
      hint: "Bulk-withdraw old pending invites that nobody accepted. Frees up your weekly connect budget on LinkedIn's side.",
      category: "Cleanup",
      limitsCategory: "profile_view",
      swAction: "li-start-withdraw-invites-bg",
      moduleMap: { nodes: [
        { id: "n1", type: "trigger.manual",      name: "User clicks Withdraw Sent Invites" },
        { id: "n2", type: "browser.navigate",    name: "Open your Sent invitations" },
        { id: "n3", type: "browser.scan_feed",    name: "Read pending sent invites" },
        { id: "n4", type: "logic.loop",           name: "For each (up to your max)" },
        { id: "n5", type: "browser.withdraw_invite", name: "Withdraw it" },
        { id: "n6", type: "db.record_event",      name: "Log the withdrawal" },
      ] },
      needsLinkedInTab: true,
      startUrl: "https://www.linkedin.com/mynetwork/invitation-manager/sent/",
      fields: [
        { id: "count", label: "Max to withdraw", type: "number", default: 20, min: 1, max: 100 },
      ],
      configTransform: (raw) => ({
        count: clampInt(raw.count, 20, 100),
      }),
    },

    {
      id: "follow-connections",
      title: "Follow Suggested",
      hint: "Follow N suggested connections from LinkedIn's My Network page. Low-touch engagement signal, useful for warming up your account.",
      category: "Engagement",
      limitsCategory: "profile_view",
      swAction: "li-start-follow-connections-bg",
      moduleMap: { nodes: [
        { id: "n1", type: "trigger.manual",    name: "User clicks Follow Suggested" },
        { id: "n2", type: "browser.navigate",  name: "Open My Network" },
        { id: "n3", type: "browser.scan_feed",  name: "Read suggested people" },
        { id: "n4", type: "logic.loop",         name: "For each (up to your max)" },
        { id: "n5", type: "browser.follow_user", name: "Follow them" },
        { id: "n6", type: "db.record_event",    name: "Log the follow" },
      ] },
      needsLinkedInTab: true,
      startUrl: "https://www.linkedin.com/mynetwork/",
      fields: [
        { id: "count", label: "Max to follow", type: "number", default: 20, min: 1, max: 100 },
      ],
      configTransform: (raw) => ({
        count: clampInt(raw.count, 20, 100),
      }),
    },

    {
      id: "view-profiles",
      title: "View Profiles",
      hint: "Search and visit N profiles. LinkedIn records the visit, putting your name in their 'who viewed you' list — soft-touch outbound signal.",
      category: "Soft touch",
      limitsCategory: "profile_view",
      swAction: "li-start-view-profiles-bg",
      moduleMap: { nodes: [
        { id: "n1", type: "trigger.manual",    name: "User clicks View Profiles" },
        { id: "n2", type: "browser.navigate",  name: "Open people search for your keyword" },
        { id: "n3", type: "browser.scan_feed",  name: "Collect matching profiles" },
        { id: "n4", type: "logic.loop",         name: "For each (up to your count)" },
        { id: "n5", type: "browser.view_profile", name: "Visit the profile (lands in their 'who viewed you')" },
        { id: "n6", type: "db.record_event",    name: "Log the visit" },
      ] },
      needsLinkedInTab: true,
      startUrl: "https://www.linkedin.com/feed/",
      fields: [
        { id: "keyword",  label: "Search keyword", type: "text", default: "CEO web3", placeholder: "CEO web3" },
        { id: "count",    label: "Profiles to view", type: "number", default: 10, min: 1, max: 50 },
      ],
      configTransform: (raw) => ({
        keyword: String(raw.keyword || "CEO web3").trim(),
        count: clampInt(raw.count, 10, 50),
      }),
    },
  ];

  function clampInt(v, fallback, max = 9999) {
    const n = parseInt(v, 10);
    if (!Number.isFinite(n) || n <= 0) return fallback;
    return Math.min(n, max);
  }

  // Expose for the dashboard + (future) the panel.
  if (typeof window !== "undefined") {
    window.LI_ACTION_REGISTRY = LI_ACTIONS;
    window.LI_ACTION_CLAMP_INT = clampInt;
  }
})();
