import React, { useEffect, useMemo, useState } from "react";
import { bpFetch } from "../api/client";

const FEATURE_GROUPS = [
  {
    title: "Automation",
    lead: "Automate follow-ups and event-based actions across bookings.",
    items: [
      { key: "advanced_workflows", label: "Advanced workflows" },
      { key: "advanced_webhooks", label: "Advanced webhooks" },
      { key: "sms_reminders", label: "SMS reminders" },
      { key: "whatsapp_notifications", label: "WhatsApp notifications" },
      { key: "mailchimp_crm", label: "Mailchimp and CRM integrations" },
    ],
  },
  {
    title: "Integrations",
    lead: "Connect BookPoint to calendars, meetings, and payment systems.",
    items: [
      { key: "google_calendar_sync", label: "Google Calendar sync" },
      { key: "outlook_calendar_sync", label: "Outlook and Microsoft 365 sync" },
      { key: "video_meetings", label: "Zoom and Google Meet links" },
      { key: "extra_payment_gateways", label: "More payment gateways" },
    ],
  },
  {
    title: "Revenue Tools",
    lead: "Sell more with repeat bookings, bundles, and flexible payment flows.",
    items: [
      { key: "recurring_appointments", label: "Recurring appointments" },
      { key: "packages_bundles", label: "Packages and bundles" },
      { key: "deposits_partial_payments", label: "Deposits and partial payments" },
      { key: "invoices", label: "Invoices" },
      { key: "payment_links", label: "Payment links" },
      { key: "refund_management", label: "Refund management" },
    ],
  },
  {
    title: "Business Controls",
    lead: "Give teams the visibility and permissions they need to run bookings.",
    items: [
      { key: "advanced_reports", label: "Advanced reports" },
      { key: "agent_dashboard", label: "Agent dashboard" },
      { key: "advanced_roles_permissions", label: "Advanced roles and permissions" },
      { key: "timezone_picker", label: "Timezone picker" },
    ],
  },
  {
    title: "Button and Widget Customization",
    lead: "Tune the public booking entry point to match your site and flow.",
    items: [
      { key: "button_widget_customization", label: "Custom booking button text" },
      { key: "button_widget_customization", label: "Custom booking button color and hover color" },
      { key: "button_widget_customization", label: "Custom button size, radius, icon, and full-width mode" },
      { key: "button_widget_customization", label: "Service-specific booking buttons" },
      { key: "shortcode_step_skipping", label: "Shortcode options to preselect service, agent, location, or category" },
      { key: "shortcode_step_skipping", label: "Shortcode options to skip selected booking steps" },
      { key: "button_widget_customization", label: "Advanced booking widget styling" },
    ],
  },
];

const ROLE_CAPS = [
  { key: "pointlybooking_manage_services", label: "Manage Services" },
  { key: "pointlybooking_manage_agents", label: "Manage Agents" },
  { key: "pointlybooking_manage_bookings", label: "Manage Bookings" },
  { key: "pointlybooking_manage_customers", label: "Manage Customers" },
  { key: "pointlybooking_manage_settings", label: "Manage Settings" },
  { key: "pointlybooking_manage_tools", label: "Manage Tools" },
];

const EVENT_LABELS = {
  booking_created: "Booking created",
  booking_updated: "Booking updated",
  booking_confirmed: "Booking confirmed",
  booking_cancelled: "Booking cancelled",
  booking_abandoned: "Booking abandoned",
  customer_created: "Customer created",
};

const INTEGRATION_STATUS_META = {
  connected: { label: "Connected", badge: "paid" },
  configured: { label: "Configured", badge: "completed" },
  failed: { label: "Failed", badge: "refunded" },
  disabled: { label: "Disabled", badge: "pending_payment" },
  not_configured: { label: "Not configured", badge: "pending_payment" },
  needs_credentials: { label: "Needs setup", badge: "pending_payment" },
};

const PRO_TABS = [
  { key: "overview", label: "Overview" },
  { key: "automation", label: "Automation" },
  { key: "integrations", label: "Integrations" },
  { key: "revenue", label: "Revenue" },
  { key: "controls", label: "Controls" },
  { key: "widget", label: "Widget Studio" },
];

const QUICK_SETUP_LINKS = [
  {
    key: "automation",
    title: "Automation Workflows",
    sub: "Advanced workflows, webhooks, SMS, WhatsApp, Mailchimp, CRM, integrations, and revenue actions.",
    page: "pointlybooking_notifications",
  },
  {
    key: "payments",
    title: "Payments and Gateways",
    sub: "Stripe, PayPal, WooCommerce gateway hub, and payment behavior controls.",
    page: "pointlybooking_settings",
    params: { tab: "payments" },
  },
  {
    key: "schedule",
    title: "Timezone and Schedule",
    sub: "Timezone picker, slot rules, availability, and calendar behavior.",
    page: "pointlybooking_settings",
    params: { tab: "schedule" },
  },
  {
    key: "tools",
    title: "Reports and Diagnostics",
    sub: "System reports, diagnostics, exports, and maintenance tooling.",
    page: "pointlybooking_settings",
    params: { tab: "tools" },
  },
  {
    key: "dashboard",
    title: "Agent Dashboard",
    sub: "Dashboard and calendar experience used by manager and staff roles.",
    page: "pointlybooking_dashboard",
  },
  {
    key: "bookings",
    title: "Bookings Workspace",
    sub: "Operational booking flow for agents, staff users, and front-office teams.",
    page: "pointlybooking_bookings",
  },
];

const CONTROL_LINKS = [
  {
    key: "reports",
    title: "Reports Workspace",
    sub: "Use tools, diagnostics, exports, and booking health reporting.",
    page: "pointlybooking_settings",
    params: { tab: "tools" },
  },
  {
    key: "calendar",
    title: "Calendar Operations",
    sub: "Review schedule pressure and booking movement in the main calendar.",
    page: "pointlybooking_calendar",
  },
  {
    key: "dashboard",
    title: "Manager Dashboard",
    sub: "Track activity, KPIs, and booking flow from the admin dashboard.",
    page: "pointlybooking_dashboard",
  },
];

const FEATURE_GROUP_BY_TAB = {
  automation: "Automation",
  integrations: "Integrations",
  revenue: "Revenue Tools",
  controls: "Business Controls",
  widget: "Button and Widget Customization",
};

const INTEGRATION_REVENUE_PLAYBOOKS = [
  {
    id: "playbook_google_calendar",
    section: "Integrations",
    name: "Booking Created -> Google Calendar Sync",
    event_key: "booking_created",
    workflow_name: "Booking Created: Google Calendar sync",
    requiredActionTypes: ["google_calendar_sync"],
    actions: [{ type: "google_calendar_sync", status: "active", config: {} }],
  },
  {
    id: "playbook_outlook_sync",
    section: "Integrations",
    name: "Booking Created -> Outlook / Microsoft 365 Sync",
    event_key: "booking_created",
    workflow_name: "Booking Created: Outlook sync",
    requiredActionTypes: ["outlook_calendar_sync"],
    actions: [{ type: "outlook_calendar_sync", status: "active", config: {} }],
  },
  {
    id: "playbook_zoom_meeting",
    section: "Integrations",
    name: "Booking Confirmed -> Zoom Meeting Link",
    event_key: "booking_confirmed",
    workflow_name: "Booking Confirmed: Zoom meeting link",
    requiredActionTypes: ["zoom_meeting_create"],
    actions: [{ type: "zoom_meeting_create", status: "active", config: {} }],
  },
  {
    id: "playbook_google_meet",
    section: "Integrations",
    name: "Booking Confirmed -> Google Meet Link",
    event_key: "booking_confirmed",
    workflow_name: "Booking Confirmed: Google Meet link",
    requiredActionTypes: ["google_meet_link"],
    actions: [{ type: "google_meet_link", status: "active", config: {} }],
  },
  {
    id: "playbook_recurring",
    section: "Revenue",
    name: "Booking Confirmed -> Create Recurring Appointments",
    event_key: "booking_confirmed",
    workflow_name: "Booking Confirmed: recurring appointments",
    requiredActionTypes: ["create_recurring_appointments"],
    actions: [{ type: "create_recurring_appointments", status: "active", config: {} }],
  },
  {
    id: "playbook_package",
    section: "Revenue",
    name: "Booking Confirmed -> Create Package Purchase",
    event_key: "booking_confirmed",
    workflow_name: "Booking Confirmed: package purchase",
    requiredActionTypes: ["create_package_purchase"],
    actions: [{ type: "create_package_purchase", status: "active", config: {} }],
  },
  {
    id: "playbook_deposit",
    section: "Revenue",
    name: "Booking Created -> Deposit Payment Link",
    event_key: "booking_created",
    workflow_name: "Booking Created: deposit payment link",
    requiredActionTypes: ["create_deposit_payment_link"],
    actions: [{ type: "create_deposit_payment_link", status: "active", config: {} }],
  },
  {
    id: "playbook_invoice",
    section: "Revenue",
    name: "Booking Confirmed -> Create Invoice",
    event_key: "booking_confirmed",
    workflow_name: "Booking Confirmed: create invoice",
    requiredActionTypes: ["create_invoice"],
    actions: [{ type: "create_invoice", status: "active", config: {} }],
  },
  {
    id: "playbook_payment_link",
    section: "Revenue",
    name: "Booking Created -> Create Payment Link",
    event_key: "booking_created",
    workflow_name: "Booking Created: payment link",
    requiredActionTypes: ["create_payment_link"],
    actions: [{ type: "create_payment_link", status: "active", config: {} }],
  },
  {
    id: "playbook_refund",
    section: "Revenue",
    name: "Booking Cancelled -> Refund Management",
    event_key: "booking_cancelled",
    workflow_name: "Booking Cancelled: refund payment",
    requiredActionTypes: ["refund_payment"],
    actions: [{ type: "refund_payment", status: "active", config: {} }],
  },
];

const PRO_ONBOARDING_TRACKS = [
  {
    key: "consultation",
    label: "Consultation",
    summary: "Professional-services rollout for consultancies, agencies, and advisory teams.",
    lead: "Prioritize calendar sync, payment follow-up, and clear booking handoff.",
    focusTab: "automation",
    setupKeys: ["automation", "payments", "schedule", "bookings"],
    playbookIds: ["playbook_google_calendar", "playbook_payment_link", "playbook_invoice"],
    featureKeys: ["google_calendar_sync", "payment_links", "invoices", "timezone_picker"],
    checklist: [
      "Connect your main calendar so confirmed bookings stay in sync.",
      "Enable payment links or invoices for post-booking collection.",
      "Review timezone rules before sharing the widget with clients.",
    ],
  },
  {
    key: "salon",
    label: "Salon",
    summary: "Team-appointment rollout for beauty, wellness, and treatment businesses.",
    lead: "Focus on deposits, repeat visits, and staff-facing operational control.",
    focusTab: "revenue",
    setupKeys: ["payments", "dashboard", "bookings", "automation"],
    playbookIds: ["playbook_deposit", "playbook_recurring", "playbook_google_calendar"],
    featureKeys: ["deposits_partial_payments", "recurring_appointments", "agent_dashboard", "google_calendar_sync"],
    checklist: [
      "Turn on deposit collection for high-value services.",
      "Create recurring workflows for repeat appointments and maintenance visits.",
      "Set up manager and staff views before involving the full team.",
    ],
  },
  {
    key: "clinic",
    label: "Clinic",
    summary: "Structured rollout for practices that need staff coordination and patient-style follow-up.",
    lead: "Focus on calendar reliability, permissions, reminders, and billing records.",
    focusTab: "controls",
    setupKeys: ["schedule", "automation", "dashboard", "tools"],
    playbookIds: ["playbook_outlook_sync", "playbook_invoice", "playbook_payment_link"],
    featureKeys: ["outlook_calendar_sync", "invoices", "advanced_roles_permissions", "timezone_picker"],
    checklist: [
      "Connect practitioner calendars before opening live scheduling.",
      "Define manager and staff permissions for front-desk operations.",
      "Set invoice or payment-link handling for follow-up collection.",
    ],
  },
  {
    key: "coach",
    label: "Coach",
    summary: "Remote-session rollout for coaching, consulting, and online delivery businesses.",
    lead: "Focus on meeting links, recurring programs, and timezone-aware booking.",
    focusTab: "integrations",
    setupKeys: ["automation", "schedule", "payments", "dashboard"],
    playbookIds: ["playbook_zoom_meeting", "playbook_google_meet", "playbook_recurring", "playbook_payment_link"],
    featureKeys: ["video_meetings", "recurring_appointments", "payment_links", "timezone_picker"],
    checklist: [
      "Add Zoom or Google Meet creation before sending confirmed sessions.",
      "Set timezone behavior for remote clients in different regions.",
      "Use recurring or payment-link workflows for programs and retainers.",
    ],
  },
  {
    key: "rental",
    label: "Rental",
    summary: "Reservation rollout for equipment, room hire, and operational booking teams.",
    lead: "Focus on staged collection, payment recovery, and cancellation handling.",
    focusTab: "revenue",
    setupKeys: ["payments", "bookings", "tools", "automation"],
    playbookIds: ["playbook_deposit", "playbook_payment_link", "playbook_refund"],
    featureKeys: ["deposits_partial_payments", "payment_links", "refund_management", "advanced_reports"],
    checklist: [
      "Collect deposits before inventory or room allocation is confirmed.",
      "Use payment links to recover unpaid reservation balances.",
      "Prepare refund handling before publishing cancellation policies.",
    ],
  },
];

function makeAdminUrl(page, params = {}) {
  const url = new URL("admin.php", window.location.origin);
  url.searchParams.set("page", page);
  Object.entries(params).forEach(([k, v]) => {
    if (v == null || v === "") return;
    url.searchParams.set(k, String(v));
  });
  return url.pathname + url.search;
}

function withBuildQuery(url, build) {
  if (!url) return "";
  return `${url}${url.includes("?") ? "&" : "?"}v=${encodeURIComponent(build)}`;
}

function normalizePositiveInt(value) {
  const n = Number(value);
  if (!Number.isFinite(n)) return 0;
  return Math.max(0, Math.trunc(n));
}

function sanitizeColor(value) {
  if (typeof value !== "string") return "";
  const color = value.trim();
  if (!color) return "";
  if (/^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(color)) return color;
  if (/^rgba?\(\s*[\d.\s,%]+\s*\)$/i.test(color)) return color;
  if (/^hsla?\(\s*[\d.\s,%]+\s*\)$/i.test(color)) return color;
  return "";
}

function formatDateTimeLabel(value) {
  const v = String(value || "").trim();
  if (!v) return "";
  const candidate = v.includes("T") ? v : v.replace(" ", "T");
  const d = new Date(candidate);
  if (Number.isNaN(d.getTime())) return v;
  return d.toLocaleString();
}

function normalizeCsv(value) {
  return String(value || "")
    .split(",")
    .map((part) => part.trim())
    .filter(Boolean)
    .join(",");
}

function escapeShortcodeValue(value) {
  return String(value).replace(/"/g, "&quot;");
}

function buildShortcode(builder) {
  const attrs = [];
  const push = (name, value) => {
    if (value == null) return;
    const s = String(value).trim();
    if (!s) return;
    attrs.push(`${name}="${escapeShortcodeValue(s)}"`);
  };

  push("button_text", builder.buttonText);
  if (builder.serviceId > 0) push("service_id", builder.serviceId);
  if (builder.agentId > 0) push("agent_id", builder.agentId);
  if (builder.locationId > 0) push("location_id", builder.locationId);
  if (builder.categoryId > 0) push("category_id", builder.categoryId);

  const categoryIds = normalizeCsv(builder.categoryIds);
  if (categoryIds) push("category_ids", categoryIds);

  const skipSteps = normalizeCsv(builder.skipSteps);
  if (skipSteps) push("skip_steps", skipSteps);

  push("button_color", sanitizeColor(builder.buttonColor));
  push("button_hover_color", sanitizeColor(builder.buttonHoverColor));
  push("button_text_color", sanitizeColor(builder.buttonTextColor));

  if (["sm", "md", "lg"].includes(builder.buttonSize)) {
    push("button_size", builder.buttonSize);
  }

  if (builder.buttonRadius > 0) {
    push("button_radius", builder.buttonRadius);
  }

  push("button_icon", builder.buttonIcon);
  if (builder.buttonFullWidth) push("button_full_width", "1");

  push("widget_primary_color", sanitizeColor(builder.widgetPrimaryColor));
  push("widget_overlay_color", sanitizeColor(builder.widgetOverlayColor));
  push("widget_background_color", sanitizeColor(builder.widgetBackgroundColor));
  push("widget_side_background_color", sanitizeColor(builder.widgetSideBackgroundColor));
  push("widget_main_background_color", sanitizeColor(builder.widgetMainBackgroundColor));

  if (builder.widgetBorderRadius > 0) push("widget_border_radius", builder.widgetBorderRadius);
  if (builder.widgetMaxWidth >= 420) push("widget_max_width", builder.widgetMaxWidth);

  if (builder.widgetShowLeftPanel !== "default") push("widget_show_left_panel", builder.widgetShowLeftPanel === "yes" ? "1" : "0");
  if (builder.widgetShowSummary !== "default") push("widget_show_summary", builder.widgetShowSummary === "yes" ? "1" : "0");

  return `[pointlybooking_booking_form${attrs.length ? ` ${attrs.join(" ")}` : ""}]`;
}

function playbookSignature(playbook) {
  return `${playbook.event_key || ""}::${playbook.workflow_name || playbook.name || ""}`;
}

function FeatureChecklist({ group, proActive, features }) {
  return (
    <section className="bp-card bp-p-16 bp-pro-card">
      <div className="bp-section-title">{group.title}</div>
      <div className="bp-muted bp-text-sm" style={{ marginTop: 6, lineHeight: 1.5 }}>
        {group.lead}
      </div>
      <ul className="bp-pro-list">
        {group.items.map((item) => (
          <li key={`${group.title}-${item.label}`}>
            <div className="bp-pro-list__text">
              <div>{item.label}</div>
              <div className="bp-pro-list__sub">
                {proActive && features[item.key] ? "Unlocked in Pro" : "Available in Pro"}
              </div>
            </div>
            <span className={`bp-badge bp-pro-list__badge ${proActive && features[item.key] ? "paid" : "pending_payment"}`}>
              {proActive && features[item.key] ? "Included" : "Pro"}
            </span>
          </li>
        ))}
      </ul>
    </section>
  );
}

function SetupLinkGrid({ links }) {
  return (
    <div className="bp-pro-ops-grid">
      {links.map((link) => (
        <a key={link.key} className="bp-pro-op" href={makeAdminUrl(link.page, link.params || {})}>
          <div className="bp-pro-op__title">{link.title}</div>
          <div className="bp-pro-op__sub">{link.sub}</div>
        </a>
      ))}
    </div>
  );
}

function PlaybookGrid({ playbooks, busyPlaybook, onLaunch }) {
  return (
    <div className="bp-pro-playbooks">
      {playbooks.map((playbook) => (
        <div key={playbook.id} className="bp-pro-playbook">
          <div className="bp-flex bp-justify-between bp-items-center" style={{ gap: 8, flexWrap: "wrap" }}>
            <div className="bp-font-800">{playbook.name}</div>
            <span className={`bp-badge ${playbook.ready ? "paid" : "pending_payment"}`}>
              {playbook.ready ? "Ready" : "Unavailable"}
            </span>
          </div>
          <div className="bp-muted bp-text-xs" style={{ marginTop: 6 }}>
            {playbook.section} • Event: {EVENT_LABELS[playbook.event_key] || playbook.event_key}
          </div>
          <div style={{ marginTop: 10 }}>
            <button
              type="button"
              className="bp-btn bp-btn-primary"
              disabled={!playbook.ready || busyPlaybook === playbook.id}
              onClick={() => onLaunch(playbook)}
            >
              {busyPlaybook === playbook.id ? "Adding..." : "Add Playbook"}
            </button>
          </div>
        </div>
      ))}
    </div>
  );
}

export default function ProScreen() {
  const admin = window.pointlybooking_ADMIN || {};
  const features = admin.features || {};
  const proActive = Boolean(admin.proActive);
  const proVersion = admin.proVersion || "1.4.0";
  const proUrl = admin.proUrl || "https://wpbookpoint.com/";
  const pluginUrl = String(admin.pluginUrl || window.bpAdmin?.pluginUrl || "").replace(/\/$/, "");
  const build = admin.build || Date.now();
  const proIconUrl = withBuildQuery(admin.proIconUrl || (pluginUrl ? `${pluginUrl}/public/icons/pro.svg` : ""), build);
  const featureCount = FEATURE_GROUPS.reduce((count, group) => count + group.items.length, 0);
  const enabledFeatureCount = FEATURE_GROUPS.reduce((count, group) => {
    return count + group.items.filter((item) => Boolean(features[item.key])).length;
  }, 0);

  const [activeTab, setActiveTab] = useState(() => {
    const tab = new URLSearchParams(window.location.search).get("pro_tab");
    return PRO_TABS.some((item) => item.key === tab) ? tab : "overview";
  });
  const [toast, setToast] = useState("");
  const [actionTypes, setActionTypes] = useState({});
  const [busyPlaybook, setBusyPlaybook] = useState("");
  const [playbookErr, setPlaybookErr] = useState("");
  const [integrationHealth, setIntegrationHealth] = useState([]);
  const [integrationLoading, setIntegrationLoading] = useState(false);
  const [integrationBusy, setIntegrationBusy] = useState("");
  const [integrationErr, setIntegrationErr] = useState("");
  const [trackBusy, setTrackBusy] = useState("");
  const [trackErr, setTrackErr] = useState("");

  const [rolesState, setRolesState] = useState({
    pointlybooking_manager: {},
    pointlybooking_staff: {},
  });
  const [rolesLoaded, setRolesLoaded] = useState(false);
  const [rolesSaving, setRolesSaving] = useState(false);
  const [rolesError, setRolesError] = useState("");

  const [builder, setBuilder] = useState({
    buttonText: "Book Now",
    serviceId: 0,
    agentId: 0,
    locationId: 0,
    categoryId: 0,
    categoryIds: "",
    skipSteps: "",
    buttonColor: "",
    buttonHoverColor: "",
    buttonTextColor: "",
    buttonSize: "md",
    buttonRadius: 0,
    buttonIcon: "calendar",
    buttonFullWidth: false,
    widgetPrimaryColor: "",
    widgetOverlayColor: "",
    widgetBackgroundColor: "",
    widgetSideBackgroundColor: "",
    widgetMainBackgroundColor: "",
    widgetBorderRadius: 0,
    widgetMaxWidth: 0,
    widgetShowLeftPanel: "default",
    widgetShowSummary: "default",
  });
  const [copyMsg, setCopyMsg] = useState("");
  const [activeTrack, setActiveTrack] = useState(() => {
    const track = new URLSearchParams(window.location.search).get("pro_track");
    return PRO_ONBOARDING_TRACKS.some((item) => item.key === track) ? track : "consultation";
  });

  useEffect(() => {
    let alive = true;
    bpFetch("/admin/notifications/meta")
      .then((resp) => {
        if (!alive) return;
        const types = resp?.data?.action_types;
        setActionTypes(types && typeof types === "object" ? types : {});
      })
      .catch(() => {
        if (!alive) return;
        setActionTypes({});
      });
    return () => {
      alive = false;
    };
  }, []);

  useEffect(() => {
    if (!proActive) return undefined;
    let alive = true;
    bpFetch("/admin/pro/roles")
      .then((resp) => {
        if (!alive) return;
        const roles = resp?.data?.roles || {};
        setRolesState({
          pointlybooking_manager: roles.pointlybooking_manager || {},
          pointlybooking_staff: roles.pointlybooking_staff || {},
        });
        setRolesLoaded(true);
      })
      .catch(() => {
        if (!alive) return;
        setRolesLoaded(false);
        setRolesError("Role controls are unavailable. Activate Pro backend routes and refresh.");
      });
    return () => {
      alive = false;
    };
  }, [proActive]);

  useEffect(() => {
    if (!proActive) {
      setIntegrationHealth([]);
      return undefined;
    }
    let alive = true;
    setIntegrationErr("");
    setIntegrationLoading(true);
    bpFetch("/admin/pro/integrations")
      .then((resp) => {
        if (!alive) return;
        const items = Array.isArray(resp?.data?.items) ? resp.data.items : [];
        setIntegrationHealth(items);
      })
      .catch((err) => {
        if (!alive) return;
        setIntegrationErr(err?.message || "Could not load integration health.");
      })
      .finally(() => {
        if (!alive) return;
        setIntegrationLoading(false);
      });
    return () => {
      alive = false;
    };
  }, [proActive]);

  useEffect(() => {
    if (!toast) return undefined;
    const timeout = window.setTimeout(() => setToast(""), 2600);
    return () => window.clearTimeout(timeout);
  }, [toast]);

  const availablePlaybooks = useMemo(() => {
    return INTEGRATION_REVENUE_PLAYBOOKS.map((playbook) => {
      const ready = playbook.requiredActionTypes.every((type) => Boolean(actionTypes[type]));
      return { ...playbook, ready };
    });
  }, [actionTypes]);

  const integrationPlaybooks = useMemo(
    () => availablePlaybooks.filter((playbook) => playbook.section === "Integrations"),
    [availablePlaybooks]
  );
  const revenuePlaybooks = useMemo(
    () => availablePlaybooks.filter((playbook) => playbook.section === "Revenue"),
    [availablePlaybooks]
  );

  const integrationSummary = useMemo(() => {
    return integrationHealth.reduce(
      (acc, row) => {
        acc.total += 1;
        if (row.status === "connected" || row.status === "configured") acc.ready += 1;
        if (row.status === "failed") acc.failed += 1;
        return acc;
      },
      { total: 0, ready: 0, failed: 0 }
    );
  }, [integrationHealth]);

  const shortcode = useMemo(() => buildShortcode(builder), [builder]);
  const availablePlaybookMap = useMemo(() => {
    const map = new Map();
    availablePlaybooks.forEach((playbook) => {
      map.set(playbook.id, playbook);
    });
    return map;
  }, [availablePlaybooks]);
  const setupLinkMap = useMemo(() => {
    const map = new Map();
    [...QUICK_SETUP_LINKS, ...CONTROL_LINKS].forEach((link) => {
      if (!map.has(link.key)) {
        map.set(link.key, link);
      }
    });
    return map;
  }, []);
  const selectedTrack = useMemo(() => {
    return PRO_ONBOARDING_TRACKS.find((track) => track.key === activeTrack) || PRO_ONBOARDING_TRACKS[0];
  }, [activeTrack]);
  const selectedTrackPlaybooks = useMemo(() => {
    return (selectedTrack?.playbookIds || []).map((id) => availablePlaybookMap.get(id)).filter(Boolean);
  }, [selectedTrack, availablePlaybookMap]);
  const selectedTrackLinks = useMemo(() => {
    return (selectedTrack?.setupKeys || []).map((key) => setupLinkMap.get(key)).filter(Boolean);
  }, [selectedTrack, setupLinkMap]);
  const selectedTrackFeatureStats = useMemo(() => {
    const keys = Array.isArray(selectedTrack?.featureKeys) ? selectedTrack.featureKeys : [];
    const total = keys.length;
    const ready = keys.filter((key) => Boolean(features[key])).length;
    return { total, ready };
  }, [selectedTrack, features]);
  const selectedTrackReadyPlaybooks = useMemo(() => {
    return selectedTrackPlaybooks.filter((playbook) => playbook.ready);
  }, [selectedTrackPlaybooks]);
  const buttonPreviewStyle = useMemo(() => {
    const style = {};
    if (sanitizeColor(builder.buttonColor)) style["--bp-btn-bg"] = sanitizeColor(builder.buttonColor);
    if (sanitizeColor(builder.buttonHoverColor)) style["--bp-btn-hover-bg"] = sanitizeColor(builder.buttonHoverColor);
    if (sanitizeColor(builder.buttonTextColor)) style["--bp-btn-text"] = sanitizeColor(builder.buttonTextColor);
    if (builder.buttonRadius > 0) style["--bp-btn-radius"] = `${builder.buttonRadius}px`;
    if (builder.buttonFullWidth) style.width = "100%";
    return style;
  }, [builder]);

  const activeGroup = FEATURE_GROUPS.find((group) => group.title === FEATURE_GROUP_BY_TAB[activeTab]) || null;

  function activateTab(key) {
    setActiveTab(key);
    const url = new URL(window.location.href);
    url.searchParams.set("pro_tab", key);
    window.history.replaceState({}, "", url.toString());
  }

  function activateTrack(key) {
    setActiveTrack(key);
    const url = new URL(window.location.href);
    url.searchParams.set("pro_track", key);
    window.history.replaceState({}, "", url.toString());
  }

  async function loadIntegrationHealth() {
    if (!proActive) return;
    setIntegrationLoading(true);
    setIntegrationErr("");
    try {
      const resp = await bpFetch("/admin/pro/integrations");
      const items = Array.isArray(resp?.data?.items) ? resp.data.items : [];
      setIntegrationHealth(items);
    } catch (err) {
      setIntegrationErr(err?.message || "Could not refresh integration health.");
    } finally {
      setIntegrationLoading(false);
    }
  }

  async function testIntegrationConnection(row) {
    if (!row?.key) return;
    setIntegrationBusy(row.key);
    setIntegrationErr("");
    try {
      const resp = await bpFetch("/admin/pro/integrations/test", {
        method: "POST",
        body: { integration: row.key },
      });
      const data = resp?.data || {};
      if (data.status === "connected") {
        setToast(data.message || `${row.label} connection test succeeded.`);
      } else {
        setIntegrationErr(data.message || `${row.label} connection test failed.`);
      }
      await loadIntegrationHealth();
    } catch (err) {
      setIntegrationErr(err?.message || `${row.label} connection test failed.`);
    } finally {
      setIntegrationBusy("");
    }
  }

  async function launchPlaybook(playbook) {
    setPlaybookErr("");
    setBusyPlaybook(playbook.id);
    try {
      const existing = await fetchExistingWorkflowSignatures();
      const result = await provisionPlaybook(playbook, existing);
      if (result.skipped) {
        setToast(`Playbook already exists: ${playbook.name}`);
      } else {
        setToast(`Playbook added: ${playbook.name}`);
      }
    } catch (err) {
      setPlaybookErr(err.message || "Could not add playbook.");
    } finally {
      setBusyPlaybook("");
    }
  }

  async function fetchExistingWorkflowSignatures() {
    const resp = await bpFetch("/admin/notifications/workflows?page=1&per=100");
    const items = Array.isArray(resp?.data?.items) ? resp.data.items : [];
    const signatures = new Set();
    items.forEach((workflow) => {
      signatures.add(`${workflow.event_key || ""}::${workflow.name || ""}`);
    });
    return signatures;
  }

  async function provisionPlaybook(playbook, existingSignatures = null) {
    const signature = playbookSignature(playbook);
    if (existingSignatures && existingSignatures.has(signature)) {
      return { skipped: true };
    }

    const workflowResp = await bpFetch("/admin/notifications/workflows", {
      method: "POST",
      body: {
        name: playbook.workflow_name || playbook.name,
        event_key: playbook.event_key,
        status: "active",
      },
    });
    const workflowId = workflowResp?.data?.id;
    if (!workflowId) throw new Error("Could not create workflow.");

    for (const action of playbook.actions || []) {
      await bpFetch(`/admin/notifications/workflows/${workflowId}/actions`, {
        method: "POST",
        body: {
          type: action.type,
          status: action.status || "active",
          config: action.config || {},
        },
      });
    }

    if (existingSignatures) {
      existingSignatures.add(signature);
    }

    return { skipped: false, workflowId };
  }

  async function launchTrackPlaybooks(track) {
    if (!track) return;
    setTrackErr("");
    setTrackBusy(track.key);
    try {
      const existing = await fetchExistingWorkflowSignatures();
      let added = 0;
      let skipped = 0;
      for (const playbook of selectedTrackPlaybooks) {
        if (!playbook.ready) continue;
        const result = await provisionPlaybook(playbook, existing);
        if (result.skipped) skipped += 1;
        else added += 1;
      }

      if (added > 0) {
        setToast(`Starter stack added: ${added} workflow${added === 1 ? "" : "s"} created.`);
      } else if (skipped > 0) {
        setToast("Starter stack already exists for this track.");
      } else {
        setToast("No ready starter playbooks are available for this track yet.");
      }
    } catch (err) {
      setTrackErr(err.message || "Could not launch starter stack.");
    } finally {
      setTrackBusy("");
    }
  }

  function setRoleCap(roleKey, capKey, value) {
    setRolesState((prev) => ({
      ...prev,
      [roleKey]: {
        ...(prev[roleKey] || {}),
        [capKey]: value,
      },
    }));
  }

  async function saveRoles() {
    setRolesSaving(true);
    setRolesError("");
    try {
      await bpFetch("/admin/pro/roles", {
        method: "POST",
        body: { roles: rolesState },
      });
      setToast("Role permissions saved.");
    } catch (err) {
      setRolesError(err.message || "Could not save role permissions.");
    } finally {
      setRolesSaving(false);
    }
  }

  async function copyShortcode() {
    try {
      await navigator.clipboard.writeText(shortcode);
      setCopyMsg("Shortcode copied.");
      setToast("Shortcode copied.");
      setTimeout(() => setCopyMsg(""), 1800);
    } catch {
      setCopyMsg("Copy failed.");
      setTimeout(() => setCopyMsg(""), 1800);
    }
  }

  return (
    <div className="myplugin-page bp-pro">
      <main className="myplugin-content bp-pro-shell">
        {toast ? <div className="bp-toast bp-toast-success">{toast}</div> : null}

        <div className="bp-page-head bp-page-head--pro">
          <div>
            <div className="bp-h1">{proActive ? `BookPoint Pro ${proVersion}` : "Upgrade to Pro"}</div>
            <div className="bp-muted">
              {proActive
                ? "Pro is active. Use this page to manage premium setup flows, integrations, revenue automation, and widget presets."
                : "Install BookPoint Pro to unlock integrations, revenue tools, business controls, and advanced booking widget customization."}
            </div>
          </div>
          <div className="bp-pro-headActions">
            <div className="bp-pro-headMeta" aria-label="Pro page status">
              <div className={`bp-pro-headPill bp-pro-headPill--status ${proActive ? "is-paid" : "is-pending"}`}>
                <span className="bp-pro-headPill__eyebrow">Status</span>
                <span className="bp-pro-headPill__value">{proActive ? "Pro active" : "Upgrade available"}</span>
              </div>
              <div className="bp-pro-headPill bp-pro-headPill--feature">
                <span className="bp-pro-headPill__eyebrow">Pro toolkit</span>
                <span className="bp-pro-headPill__value">{featureCount} features</span>
              </div>
            </div>
            <a className="bp-primary-btn bp-pro-headCta" href={proUrl} target="_blank" rel="noreferrer">
              {proActive ? "Visit Pro Site" : "Get BookPoint Pro"}
            </a>
          </div>
        </div>

        <section className="bp-card bp-p-24 bp-pro-hero">
          <div className="bp-pro-hero__content">
            <div className="bp-pro-hero__eyebrow">{proActive ? "Pro Control Center" : "Separate paid add-on"}</div>
            <div className="bp-pro-hero__title">
              {proActive ? "Run premium setup from one place." : "Unlock the advanced operating layer for BookPoint."}
            </div>
            <p className="bp-pro-copy">
              {proActive
                ? "Track integration health, launch workflow playbooks, control staff permissions, and build styled booking widgets without leaving the admin."
                : "BookPoint Pro adds real automation, calendar sync, revenue tooling, team controls, and a deeper booking widget studio. The free plugin stays clean while Pro handles the advanced workflow layer."}
            </p>
            <div className="bp-pro-hero__actions">
              <a className="bp-btn bp-btn-primary" href={proActive ? makeAdminUrl("pointlybooking_notifications") : proUrl} target={proActive ? undefined : "_blank"} rel={proActive ? undefined : "noreferrer"}>
                {proActive ? "Open Automation" : "View Pro Details"}
              </a>
              <a className="bp-btn" href={makeAdminUrl("pointlybooking_settings", { tab: "payments" })}>
                Payments and Gateways
              </a>
            </div>
          </div>

          <div className="bp-pro-hero__stats">
            <div className="bp-pro-stat">
              <div className="bp-pro-stat__value">{proActive ? enabledFeatureCount : featureCount}</div>
              <div className="bp-pro-stat__label">{proActive ? "features unlocked" : "features available"}</div>
            </div>
            <div className="bp-pro-stat">
              <div className="bp-pro-stat__value">{integrationSummary.total || 0}</div>
              <div className="bp-pro-stat__label">integration checks</div>
            </div>
            <div className="bp-pro-stat">
              <div className="bp-pro-stat__value">{integrationSummary.ready || 0}</div>
              <div className="bp-pro-stat__label">ready integrations</div>
            </div>
            <div className="bp-pro-stat bp-pro-stat--icon">
              {proIconUrl ? <img src={proIconUrl} alt="BookPoint Pro" /> : <span>PRO</span>}
            </div>
          </div>
        </section>

        <section className="bp-card bp-p-16 bp-pro-tabsCard">
          <div className="bp-pro-tabs" role="tablist" aria-label="Upgrade to Pro sections">
            {PRO_TABS.map((tab) => (
              <button
                key={tab.key}
                type="button"
                className={`bp-pro-tab ${activeTab === tab.key ? "active" : ""}`}
                onClick={() => activateTab(tab.key)}
                role="tab"
                aria-selected={activeTab === tab.key}
              >
                {tab.label}
              </button>
            ))}
          </div>
        </section>

        {activeTab === "overview" ? (
          <div className="bp-pro-panel">
            <section className="bp-card bp-p-16">
              <div className="bp-flex bp-justify-between bp-items-center" style={{ gap: 12, flexWrap: "wrap" }}>
                <div>
                  <div className="bp-section-title" style={{ margin: 0 }}>Pro Onboarding Tracks</div>
                  <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                    Pick the closest operating model, then use the recommended setup links and starter workflows to get Pro live faster.
                  </div>
                </div>
                <span className={`bp-badge ${proActive ? "paid" : "pending_payment"}`}>
                  {proActive ? "Pro active" : "Preview before upgrade"}
                </span>
              </div>

              <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginTop: 14 }}>
                {PRO_ONBOARDING_TRACKS.map((track) => (
                  <button
                    key={track.key}
                    type="button"
                    className={`bp-pro-tab ${activeTrack === track.key ? "active" : ""}`}
                    onClick={() => activateTrack(track.key)}
                  >
                    {track.label}
                  </button>
                ))}
              </div>

              <div className="bp-pro-grid bp-pro-grid--summary" style={{ marginTop: 16 }}>
                <section className="bp-card bp-p-16 bp-pro-summaryCard">
                  <div className="bp-pro-summaryCard__head">
                    <div className="bp-section-title" style={{ margin: 0 }}>{selectedTrack.label}</div>
                    <span className="bp-badge completed">
                      {selectedTrackFeatureStats.ready}/{selectedTrackFeatureStats.total} key capabilities
                    </span>
                  </div>
                  <div className="bp-muted bp-text-sm" style={{ marginTop: 8, lineHeight: 1.6 }}>
                    {selectedTrack.summary}
                  </div>
                  <div className="bp-muted bp-text-sm" style={{ marginTop: 8, lineHeight: 1.6 }}>
                    {selectedTrack.lead}
                  </div>
                  <ul className="bp-pro-miniList">
                    {selectedTrack.checklist.map((item) => (
                      <li key={item}>{item}</li>
                    ))}
                  </ul>
                  <div className="bp-pro-summaryCard__foot" style={{ gap: 8, flexWrap: "wrap" }}>
                    {proActive ? (
                      <>
                        <button
                          type="button"
                          className="bp-btn bp-btn-primary"
                          onClick={() => launchTrackPlaybooks(selectedTrack)}
                          disabled={trackBusy === selectedTrack.key || selectedTrackReadyPlaybooks.length === 0}
                        >
                          {trackBusy === selectedTrack.key ? "Launching..." : "Launch Starter Stack"}
                        </button>
                        <button
                          type="button"
                          className="bp-btn"
                          onClick={() => activateTab(selectedTrack.focusTab)}
                        >
                          Open {PRO_TABS.find((tab) => tab.key === selectedTrack.focusTab)?.label || "Section"}
                        </button>
                      </>
                    ) : (
                      <>
                        <a className="bp-btn bp-btn-primary" href={makeAdminUrl("pointlybooking_pro", { pro_tab: selectedTrack.focusTab, pro_track: selectedTrack.key })}>
                          Review Upgrade Path
                        </a>
                        <a className="bp-btn" href={proUrl} target="_blank" rel="noreferrer">
                          View Pro Details
                        </a>
                      </>
                    )}
                  </div>
                  {trackErr ? <div className="bp-error" style={{ marginTop: 12 }}>{trackErr}</div> : null}
                </section>

                <section className="bp-card bp-p-16 bp-pro-summaryCard">
                  <div className="bp-pro-summaryCard__head">
                    <div className="bp-section-title" style={{ margin: 0 }}>Recommended Setup Flow</div>
                    <span className="bp-badge paid">{selectedTrackLinks.length} links</span>
                  </div>
                  <div className="bp-muted bp-text-sm" style={{ marginTop: 8, lineHeight: 1.6 }}>
                    Use these admin areas first for the {selectedTrack.label.toLowerCase()} rollout.
                  </div>
                  <SetupLinkGrid links={selectedTrackLinks} />
                </section>

                <section className="bp-card bp-p-16 bp-pro-summaryCard">
                  <div className="bp-pro-summaryCard__head">
                    <div className="bp-section-title" style={{ margin: 0 }}>Starter Playbooks</div>
                    <span className={`bp-badge ${selectedTrackReadyPlaybooks.length ? "paid" : "pending_payment"}`}>
                      {selectedTrackReadyPlaybooks.length}/{selectedTrackPlaybooks.length} ready
                    </span>
                  </div>
                  <div className="bp-muted bp-text-sm" style={{ marginTop: 8, lineHeight: 1.6 }}>
                    Recommended automation and revenue workflows for this track.
                  </div>
                  {selectedTrackPlaybooks.length ? (
                    <PlaybookGrid playbooks={selectedTrackPlaybooks} busyPlaybook={busyPlaybook} onLaunch={launchPlaybook} />
                  ) : (
                    <div className="bp-muted bp-text-sm" style={{ marginTop: 12 }}>
                      No starter playbooks are mapped to this onboarding track yet.
                    </div>
                  )}
                </section>
              </div>
            </section>

            <section className="bp-card bp-p-16">
              <div className="bp-section-title" style={{ margin: 0 }}>Quick Setup Links</div>
              <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                Direct links to the areas where Pro capabilities are configured and used.
              </div>
              <SetupLinkGrid links={QUICK_SETUP_LINKS} />
            </section>

            <section className="bp-pro-grid bp-pro-grid--summary">
              {FEATURE_GROUPS.map((group) => (
                <section key={group.title} className="bp-card bp-p-16 bp-pro-summaryCard">
                  <div className="bp-pro-summaryCard__head">
                    <div className="bp-section-title" style={{ margin: 0 }}>{group.title}</div>
                    <span className={`bp-badge ${proActive ? "paid" : "pending_payment"}`}>
                      {group.items.length} items
                    </span>
                  </div>
                  <div className="bp-muted bp-text-sm" style={{ marginTop: 8, lineHeight: 1.5 }}>{group.lead}</div>
                  <ul className="bp-pro-miniList">
                    {group.items.slice(0, 3).map((item) => (
                      <li key={`${group.title}-${item.label}`}>{item.label}</li>
                    ))}
                  </ul>
                  <div className="bp-pro-summaryCard__foot">
                    <button
                      type="button"
                      className="bp-btn"
                      onClick={() => activateTab(
                        Object.keys(FEATURE_GROUP_BY_TAB).find((key) => FEATURE_GROUP_BY_TAB[key] === group.title) || "overview"
                      )}
                    >
                      Open section
                    </button>
                  </div>
                </section>
              ))}
            </section>
          </div>
        ) : null}

        {activeTab === "automation" && activeGroup ? (
          <div className="bp-pro-panel">
            <section className="bp-card bp-p-16 bp-pro-banner">
              <div>
                <div className="bp-section-title" style={{ margin: 0 }}>Automation Workspace</div>
                <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                  Build advanced workflow logic, trigger notifications, and wire BookPoint into CRM and webhook pipelines.
                </div>
              </div>
              <div className="bp-pro-banner__actions">
                <a className="bp-btn bp-btn-primary" href={makeAdminUrl("pointlybooking_notifications")}>Open Automation</a>
                <a className="bp-btn" href={makeAdminUrl("pointlybooking_settings", { tab: "notifications" })}>Notification Settings</a>
              </div>
            </section>

            <FeatureChecklist group={activeGroup} proActive={proActive} features={features} />
          </div>
        ) : null}

        {activeTab === "integrations" && activeGroup ? (
          <div className="bp-pro-panel">
            <FeatureChecklist group={activeGroup} proActive={proActive} features={features} />

            <section className="bp-card bp-p-16">
              <div className="bp-flex bp-justify-between bp-items-center" style={{ gap: 10, flexWrap: "wrap" }}>
                <div>
                  <div className="bp-section-title" style={{ margin: 0 }}>Integration Health Center</div>
                  <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                    Live readiness and test status for calendar sync, meetings, CRM, notifications, and gateway integrations.
                  </div>
                </div>
                <button type="button" className="bp-btn" onClick={loadIntegrationHealth} disabled={integrationLoading}>
                  {integrationLoading ? "Refreshing..." : "Refresh"}
                </button>
              </div>

              {integrationErr ? <div className="bp-error" style={{ marginTop: 12 }}>{integrationErr}</div> : null}
              {!integrationLoading && integrationHealth.length === 0 ? (
                <div className="bp-muted bp-mt-12">
                  {proActive ? "No integration health data is available yet." : "Activate Pro to load live integration health checks."}
                </div>
              ) : null}

              <div className="bp-pro-health-grid">
                {integrationHealth.map((row) => {
                  const statusMeta = INTEGRATION_STATUS_META[row.status] || {
                    label: String(row.status || "Unknown"),
                    badge: "pending_payment",
                  };
                  const setup = row?.setup || {};
                  const setupPage = typeof setup.page === "string" ? setup.page : "";
                  const setupParams = setup && typeof setup.params === "object" && !Array.isArray(setup.params) ? setup.params : {};
                  const setupUrl = setupPage ? makeAdminUrl(setupPage, setupParams) : "";
                  const lastRunAt = formatDateTimeLabel(row.last_run_at);
                  const runText = row.last_run_status ? `${String(row.last_run_status).replace(/_/g, " ")}` : "no runs yet";

                  return (
                    <div key={row.key} className="bp-pro-health-item">
                      <div className="bp-flex bp-justify-between bp-items-center" style={{ gap: 8, flexWrap: "wrap" }}>
                        <div className="bp-font-800">{row.label}</div>
                        <span className={`bp-badge ${statusMeta.badge}`}>{statusMeta.label}</span>
                      </div>
                      <div className="bp-muted bp-text-xs" style={{ lineHeight: 1.5 }}>{row.description}</div>
                      <div className="bp-pro-health-meta">
                        <span>{row.source === "workflow" ? `Actions: ${row.active_actions || 0}/${row.total_actions || 0} active` : `Credentials: ${row.has_credentials ? "configured" : "missing"}`}</span>
                        <span>Last run: {runText}</span>
                        {lastRunAt ? <span>{lastRunAt}</span> : null}
                      </div>
                      <div className="bp-pro-health-message">{row.message || "Run a test to verify connectivity."}</div>
                      <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginTop: 6 }}>
                        <button
                          type="button"
                          className="bp-btn bp-btn-primary"
                          onClick={() => testIntegrationConnection(row)}
                          disabled={!row.testable || integrationBusy === row.key}
                        >
                          {integrationBusy === row.key ? "Testing..." : "Test connection"}
                        </button>
                        {setupUrl ? <a className="bp-btn" href={setupUrl}>Open setup</a> : null}
                      </div>
                    </div>
                  );
                })}
              </div>
            </section>

            <section className="bp-card bp-p-16">
              <div className="bp-section-title" style={{ margin: 0 }}>Integration Playbooks</div>
              <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                One-click starter workflows for Google Calendar, Microsoft 365, Zoom, and Google Meet.
              </div>
              {playbookErr ? <div className="bp-error" style={{ marginTop: 12 }}>{playbookErr}</div> : null}
              <PlaybookGrid playbooks={integrationPlaybooks} busyPlaybook={busyPlaybook} onLaunch={launchPlaybook} />
            </section>
          </div>
        ) : null}

        {activeTab === "revenue" && activeGroup ? (
          <div className="bp-pro-panel">
            <FeatureChecklist group={activeGroup} proActive={proActive} features={features} />

            <section className="bp-card bp-p-16">
              <div className="bp-section-title" style={{ margin: 0 }}>Revenue Playbooks</div>
              <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                Start recurring bookings, bundles, deposits, invoices, payment links, and refund handling from workflow templates.
              </div>
              {playbookErr ? <div className="bp-error" style={{ marginTop: 12 }}>{playbookErr}</div> : null}
              <PlaybookGrid playbooks={revenuePlaybooks} busyPlaybook={busyPlaybook} onLaunch={launchPlaybook} />
            </section>

            <section className="bp-card bp-p-16">
              <div className="bp-section-title" style={{ margin: 0 }}>Revenue Setup Links</div>
              <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                Payment settings, booking flow controls, and operational tools related to paid bookings.
              </div>
              <SetupLinkGrid
                links={[
                  QUICK_SETUP_LINKS[1],
                  QUICK_SETUP_LINKS[5],
                  { key: "customers", title: "Customers", sub: "Review payment history, customer records, and billing context.", page: "pointlybooking_customers" },
                ]}
              />
            </section>
          </div>
        ) : null}

        {activeTab === "controls" && activeGroup ? (
          <div className="bp-pro-panel">
            <FeatureChecklist group={activeGroup} proActive={proActive} features={features} />

            <section className="bp-card bp-p-16">
              <div className="bp-section-title" style={{ margin: 0 }}>Advanced Roles and Permissions</div>
              <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                Control BookPoint manager and staff capabilities directly from Pro.
              </div>
              {rolesError ? <div className="bp-error" style={{ marginTop: 12 }}>{rolesError}</div> : null}
              {!proActive ? (
                <div className="bp-muted bp-mt-12">Activate Pro to manage advanced BookPoint roles from this page.</div>
              ) : !rolesLoaded ? (
                <div className="bp-muted bp-mt-12">Role controls are loading...</div>
              ) : (
                <>
                  <div className="bp-pro-role-grid bp-mt-12">
                    {ROLE_CAPS.map((cap) => (
                      <div key={cap.key} className="bp-pro-role-row">
                        <div className="bp-pro-role-cap">{cap.label}</div>
                        <label className="bp-check">
                          <input
                            type="checkbox"
                            checked={Boolean(rolesState.pointlybooking_manager?.[cap.key])}
                            onChange={(e) => setRoleCap("pointlybooking_manager", cap.key, e.target.checked)}
                          />
                          Manager
                        </label>
                        <label className="bp-check">
                          <input
                            type="checkbox"
                            checked={Boolean(rolesState.pointlybooking_staff?.[cap.key])}
                            onChange={(e) => setRoleCap("pointlybooking_staff", cap.key, e.target.checked)}
                          />
                          Staff
                        </label>
                      </div>
                    ))}
                  </div>
                  <div className="bp-mt-12">
                    <button type="button" className="bp-btn bp-btn-primary" onClick={saveRoles} disabled={rolesSaving}>
                      {rolesSaving ? "Saving..." : "Save Permissions"}
                    </button>
                  </div>
                </>
              )}
            </section>

            <section className="bp-card bp-p-16">
              <div className="bp-section-title" style={{ margin: 0 }}>Control Surfaces</div>
              <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                The main operational screens that benefit from advanced roles, reporting, and agent visibility.
              </div>
              <SetupLinkGrid links={CONTROL_LINKS} />
            </section>
          </div>
        ) : null}

        {activeTab === "widget" && activeGroup ? (
          <div className="bp-pro-panel">
            <FeatureChecklist group={activeGroup} proActive={proActive} features={features} />

            <section className="bp-card bp-p-16">
              <div className="bp-section-title" style={{ margin: 0 }}>Button and Widget Studio</div>
              <div className="bp-muted bp-text-sm" style={{ marginTop: 6 }}>
                Generate production-ready shortcode presets for service-specific buttons, preselects, skip steps, and advanced widget styling.
              </div>

              <div className="bp-pro-shortcode-grid bp-mt-12">
                <div className="bp-pro-shortcode-form">
                  <div className="bp-grid bp-grid-2 bp-gap-10">
                    <div className="bp-settings-field">
                      <label className="bp-label">Button text</label>
                      <input className="bp-input" value={builder.buttonText} onChange={(e) => setBuilder({ ...builder, buttonText: e.target.value })} />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Button icon</label>
                      <input className="bp-input" value={builder.buttonIcon} onChange={(e) => setBuilder({ ...builder, buttonIcon: e.target.value })} placeholder="calendar or icon URL" />
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Service ID</label>
                      <input className="bp-input" type="number" min={0} value={builder.serviceId} onChange={(e) => setBuilder({ ...builder, serviceId: normalizePositiveInt(e.target.value) })} />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Category ID</label>
                      <input className="bp-input" type="number" min={0} value={builder.categoryId} onChange={(e) => setBuilder({ ...builder, categoryId: normalizePositiveInt(e.target.value) })} />
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Agent ID</label>
                      <input className="bp-input" type="number" min={0} value={builder.agentId} onChange={(e) => setBuilder({ ...builder, agentId: normalizePositiveInt(e.target.value) })} />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Location ID</label>
                      <input className="bp-input" type="number" min={0} value={builder.locationId} onChange={(e) => setBuilder({ ...builder, locationId: normalizePositiveInt(e.target.value) })} />
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Category IDs (CSV)</label>
                      <input className="bp-input" value={builder.categoryIds} onChange={(e) => setBuilder({ ...builder, categoryIds: e.target.value })} placeholder="1,2,3" />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Skip steps (CSV)</label>
                      <input className="bp-input" value={builder.skipSteps} onChange={(e) => setBuilder({ ...builder, skipSteps: e.target.value })} placeholder="location,category,service,extras,agent" />
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Button color</label>
                      <input className="bp-input" value={builder.buttonColor} onChange={(e) => setBuilder({ ...builder, buttonColor: e.target.value })} placeholder="#2563eb" />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Button hover color</label>
                      <input className="bp-input" value={builder.buttonHoverColor} onChange={(e) => setBuilder({ ...builder, buttonHoverColor: e.target.value })} placeholder="#1d4ed8" />
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Button text color</label>
                      <input className="bp-input" value={builder.buttonTextColor} onChange={(e) => setBuilder({ ...builder, buttonTextColor: e.target.value })} placeholder="#ffffff" />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Button size</label>
                      <select className="bp-input" value={builder.buttonSize} onChange={(e) => setBuilder({ ...builder, buttonSize: e.target.value })}>
                        <option value="sm">Small</option>
                        <option value="md">Medium</option>
                        <option value="lg">Large</option>
                      </select>
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Button radius (px)</label>
                      <input className="bp-input" type="number" min={0} value={builder.buttonRadius} onChange={(e) => setBuilder({ ...builder, buttonRadius: normalizePositiveInt(e.target.value) })} />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Full-width button</label>
                      <label className="bp-check">
                        <input type="checkbox" checked={builder.buttonFullWidth} onChange={(e) => setBuilder({ ...builder, buttonFullWidth: e.target.checked })} />
                        Enable
                      </label>
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Widget primary color</label>
                      <input className="bp-input" value={builder.widgetPrimaryColor} onChange={(e) => setBuilder({ ...builder, widgetPrimaryColor: e.target.value })} placeholder="#2563eb" />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Widget overlay color</label>
                      <input className="bp-input" value={builder.widgetOverlayColor} onChange={(e) => setBuilder({ ...builder, widgetOverlayColor: e.target.value })} placeholder="rgba(0,0,0,0.5)" />
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Widget background color</label>
                      <input className="bp-input" value={builder.widgetBackgroundColor} onChange={(e) => setBuilder({ ...builder, widgetBackgroundColor: e.target.value })} placeholder="#ffffff" />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Widget side panel background</label>
                      <input className="bp-input" value={builder.widgetSideBackgroundColor} onChange={(e) => setBuilder({ ...builder, widgetSideBackgroundColor: e.target.value })} placeholder="#f8fafc" />
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Widget main panel background</label>
                      <input className="bp-input" value={builder.widgetMainBackgroundColor} onChange={(e) => setBuilder({ ...builder, widgetMainBackgroundColor: e.target.value })} placeholder="#ffffff" />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Widget border radius (px)</label>
                      <input className="bp-input" type="number" min={0} value={builder.widgetBorderRadius} onChange={(e) => setBuilder({ ...builder, widgetBorderRadius: normalizePositiveInt(e.target.value) })} />
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Widget max width (px)</label>
                      <input className="bp-input" type="number" min={0} value={builder.widgetMaxWidth} onChange={(e) => setBuilder({ ...builder, widgetMaxWidth: normalizePositiveInt(e.target.value) })} />
                    </div>
                    <div className="bp-settings-field">
                      <label className="bp-label">Widget show left panel</label>
                      <select className="bp-input" value={builder.widgetShowLeftPanel} onChange={(e) => setBuilder({ ...builder, widgetShowLeftPanel: e.target.value })}>
                        <option value="default">Default</option>
                        <option value="yes">Yes</option>
                        <option value="no">No</option>
                      </select>
                    </div>

                    <div className="bp-settings-field">
                      <label className="bp-label">Widget show summary</label>
                      <select className="bp-input" value={builder.widgetShowSummary} onChange={(e) => setBuilder({ ...builder, widgetShowSummary: e.target.value })}>
                        <option value="default">Default</option>
                        <option value="yes">Yes</option>
                        <option value="no">No</option>
                      </select>
                    </div>
                  </div>
                </div>

                <div className="bp-pro-shortcode-preview">
                  <div className="bp-font-800">Preview</div>
                  <button type="button" className="bp-book-btn" style={buttonPreviewStyle}>
                    <span className="bp-book-btn-label">{builder.buttonText || "Book Now"}</span>
                  </button>
                  <div className="bp-muted bp-text-xs" style={{ marginTop: 8 }}>
                    This preview reflects button style attributes from the shortcode.
                  </div>

                  <div className="bp-font-800" style={{ marginTop: 14 }}>Generated shortcode</div>
                  <textarea className="bp-textarea" value={shortcode} readOnly rows={8} />
                  <div style={{ display: "flex", gap: 8, flexWrap: "wrap", marginTop: 10 }}>
                    <button type="button" className="bp-btn bp-btn-primary" onClick={copyShortcode}>
                      Copy shortcode
                    </button>
                    <a className="bp-btn" href={makeAdminUrl("pointlybooking_how_to_use")}>
                      Open usage guide
                    </a>
                  </div>
                  {copyMsg ? <div className="bp-muted bp-text-xs" style={{ marginTop: 8 }}>{copyMsg}</div> : null}
                </div>
              </div>
            </section>
          </div>
        ) : null}
      </main>
    </div>
  );
}
