import { For, Show, createEffect, createMemo, createSignal, onMount } from "solid-js";
import DashboardDesignPreview from "~/components/admin/DashboardDesignPreview";

const API = "";

type RoleOption = { id: string; key: string; name: string };

type Module = {
  id: string;
  module_key: string;
  module_name: string;
  category: string;
  default_sidebar_label: string;
  default_route: string;
  icon_key: string;
};

type RolePermission = {
  module_key: string;
  module_name: string;
  category: string;
  can_view: boolean;
  can_list: boolean;
  can_create: boolean;
  can_update: boolean;
  can_delete: boolean;
};

type ExternalDashboard = {
  id: string;
  roleId: string;
  roleKey: string;
  name: string;
  code: string;
  widgets: string[];
  tabs: string[];
  sidebarItems: string[];
  fields: string[];
  previewPath: string;
  status: "ACTIVE" | "INACTIVE" | "DRAFT";
  updatedAt: string;
  pkgCardColors?: Record<string, string>;
};

const ROLE_WIDGETS: Record<"PROFESSIONAL" | "COMPANY" | "JOB_SEEKER" | "CUSTOMER", string[]> = {
  CUSTOMER: [
    "total_requirements",
    "open_requirements",
    "closed_requirements",
    "responses_received",
    "shortlisted_responses",
    "credits",
  ],
  COMPANY: [
    "total_jobs",
    "active_jobs",
    "pending_jobs",
    "applications_received",
    "shortlisted_candidates",
    "credits",
  ],
  JOB_SEEKER: [
    "available_jobs",
    "my_applications",
    "shortlisted",
    "saved_jobs",
    "profile_status",
    "verification_status",
    "portfolio",
  ],
  PROFESSIONAL: [
    "open_leads",
    "my_requests",
    "accepted_requests",
    "tracecoins",
    "portfolio",
  ],
};

const ROLE_PORTFOLIO_TABS: Record<string, string[]> = {
  PHOTOGRAPHER: ["about", "services_pricing", "portfolio_gallery", "experience_equipment", "testimonials", "faqs"],
  MAKEUP_ARTIST: ["about", "services_pricing", "gallery", "experience_certifications", "testimonials", "faqs"],
  TUTOR: ["about", "subjects_pricing", "student_work", "qualifications", "testimonials", "faqs"],
  DEVELOPER: ["about", "services_pricing", "projects", "tech_stack_experience", "testimonials", "faqs"],
  VIDEO_EDITOR: ["about", "services_pricing", "showreel", "experience_tools", "testimonials", "faqs"],
  UGC_CONTENT_CREATOR: ["about", "services_pricing", "content_portfolio", "experience_tools", "testimonials", "faqs"],
  GRAPHIC_DESIGNER: ["about", "services_pricing", "portfolio_gallery", "experience_tools", "testimonials", "faqs"],
  SOCIAL_MEDIA_MANAGER: ["about", "services_pricing", "case_studies", "experience_tools", "testimonials", "faqs"],
  FITNESS_TRAINER: ["about", "training_plans", "client_results", "certifications", "testimonials", "faqs"],
  CATERING_SERVICES: ["about", "packages_pricing", "gallery", "experience_certifications", "testimonials", "faqs"],
  JOB_SEEKER: ["about", "education", "work_experience", "skills_certifications", "projects"],
};

const COMMON_PROFILE_FIELDS = [
  "full_name",
  "email",
  "phone",
  "location",
  "verification_status",
  "approval_status",
];
const AVAILABLE_TABS = [
  "overview",
  "basic_information",
  "documents",
  "about",
  "services_pricing",
  "portfolio_gallery",
  "gallery",
  "projects",
  "showreel",
  "content_portfolio",
  "case_studies",
  "experience_equipment",
  "experience_tools",
  "experience_certifications",
  "qualifications",
  "tech_stack_experience",
  "training_plans",
  "client_results",
  "certifications",
  "student_work",
  "subjects_pricing",
  "packages_pricing",
  "education",
  "work_experience",
  "skills_certifications",
  "testimonials",
  "faqs",
  "approvals",
  "users",
  "reports",
  "audit_logs",
  "settings",
];
const ROLE_BASED_SIDEBAR: Record<"PROFESSIONAL" | "COMPANY" | "JOB_SEEKER" | "CUSTOMER", string[]> =
  {
    PROFESSIONAL: [
      "My Dashboard",
      "My Profile",
      "My Portfolio",
      "Leads",
      "My Responses",
      "Credits",
      "Explore Nxtgauge",
      "Verification",
      "Help Center",
      "Settings",
      "Logout",
    ],
    COMPANY: [
      "My Dashboard",
      "My Profile",
      "Jobs",
      "Applications",
      "Shortlisted Candidates",
      "Credits",
      "Explore Nxtgauge",
      "Verification",
      "Help Center",
      "Settings",
      "Switch Services",
      "Logout",
    ],
    JOB_SEEKER: [
      "My Dashboard",
      "My Profile",
      "My Portfolio",
      "Jobs",
      "My Applications",
      "Saved Jobs",
      "Explore Nxtgauge",
      "Verification",
      "Help Center",
      "Settings",
      "Switch Services",
      "Logout",
    ],
    CUSTOMER: [
      "My Dashboard",
      "My Profile",
      "My Requirements",
      "Received Responses",
      "Shortlisted Responses",
      "Credits",
      "Explore Nxtgauge",
      "Verification",
      "Help Center",
      "Settings",
      "Switch Services",
      "Logout",
    ],
  };
const AVAILABLE_SIDEBAR_ITEMS = Array.from(new Set(Object.values(ROLE_BASED_SIDEBAR).flat()));
const AVAILABLE_FIELDS = [
  "full_name",
  "email",
  "phone",
  "location",
  "verification_status",
  "approval_status",
];
const PORTFOLIO_SIDEBAR_ITEM = "My Portfolio";

function normalizeToken(value: string): string {
  return String(value || "")
    .trim()
    .toLowerCase();
}

function humanizeLabel(value: string): string {
  return String(value || "")
    .replace(/_/g, " ")
    .replace(/\b\w/g, (c) => c.toUpperCase());
}

function hasSidebarItem(items: string[], value: string): boolean {
  const needle = normalizeToken(value);
  return items.some((item) => normalizeToken(item) === needle);
}

function applyPortfolioRule(
  items: string[],
  persona: "PROFESSIONAL" | "COMPANY" | "JOB_SEEKER" | "CUSTOMER" | null
): string[] {
  if (!items.length) return items;

  if (persona === "PROFESSIONAL" || persona === "JOB_SEEKER") {
    if (hasSidebarItem(items, PORTFOLIO_SIDEBAR_ITEM)) return items;
    const insertAfter = items.findIndex((item) => normalizeToken(item) === "my profile");
    if (insertAfter >= 0) {
      const next = [...items];
      next.splice(insertAfter + 1, 0, PORTFOLIO_SIDEBAR_ITEM);
      return next;
    }
    return [...items, PORTFOLIO_SIDEBAR_ITEM];
  }

  if (!hasSidebarItem(items, PORTFOLIO_SIDEBAR_ITEM)) return items;
  return items.filter((item) => normalizeToken(item) !== normalizeToken(PORTFOLIO_SIDEBAR_ITEM));
}

function mergeSidebarForPersona(
  items: string[],
  persona: "PROFESSIONAL" | "COMPANY" | "JOB_SEEKER" | "CUSTOMER" | null
): string[] {
  const base =
    persona && ROLE_BASED_SIDEBAR[persona]?.length
      ? ROLE_BASED_SIDEBAR[persona]
      : ["My Dashboard", "My Profile", "Switch Services", "Logout"];
  const merged = new Map<string, string>();
  for (const item of [...items, ...base]) {
    const label = String(item || "").trim();
    if (!label) continue;
    const key = normalizeToken(label);
    if (!merged.has(key)) merged.set(key, label);
  }
  let next = Array.from(merged.values());
  if (persona === "JOB_SEEKER") {
    next = next.filter((item) => normalizeToken(item) !== "credits");
  }
  if (!next.some((item) => normalizeToken(item) === normalizeToken("Explore Nxtgauge"))) {
    const verificationIdx = next.findIndex(
      (item) => normalizeToken(item) === normalizeToken("Verification")
    );
    if (verificationIdx >= 0) next.splice(verificationIdx, 0, "Explore Nxtgauge");
    else next.push("Explore Nxtgauge");
  }
  return applyPortfolioRule(next, persona);
}

function sameSidebarOrder(a: string[], b: string[]): boolean {
  if (a.length !== b.length) return false;
  return a.every((item, idx) => normalizeToken(item) === normalizeToken(b[idx] || ""));
}

function rolePreviewPath(roleKey: string): string {
  const key = String(roleKey || "").toUpperCase();
  if (key.includes("COMPANY")) return "/employers/dashboard";
  if (key.includes("CUSTOMER") || key.includes("SERVICE_SEEKER"))
    {return "/users/customer/dashboard";}
  if (key.includes("JOB_SEEKER") || key.includes("JOBSEEKER")) return "/users/candidate/dashboard";
  if (key.includes("PHOTOGRAPHER")) return "/users/photographer/dashboard";
  if (key.includes("MAKEUP")) return "/users/makeup/dashboard";
  if (key.includes("TUTOR")) return "/users/tutors/dashboard";
  if (key.includes("DEVELOPER")) return "/users/developers/dashboard";
  if (key.includes("VIDEO")) return "/users/video-editors/dashboard";
  if (key.includes("UGC") || (key.includes("CONTENT") && key.includes("CREATOR")))
    {return "/users/ugc-content-creators/dashboard";}
  if (key.includes("FITNESS")) return "/users/fitness-trainers/dashboard";
  if (key.includes("GRAPHIC")) return "/users/graphic-designers/dashboard";
  if (key.includes("SOCIAL")) return "/users/social-media-managers/dashboard";
  if (key.includes("CATER")) return "/users/catering-services/dashboard";
  return "/signup";
}

function defaultTabsForRole(roleKey: string): string[] {
  const key = String(roleKey || "").toUpperCase();
  if (!key) return ["overview"];
  if (ROLE_PORTFOLIO_TABS[key]) return ROLE_PORTFOLIO_TABS[key];
  if (key.includes("COMPANY")) return ["overview", "jobs", "applications", "shortlisted_candidates"];
  if (key.includes("CUSTOMER") || key.includes("SERVICE_SEEKER")) return ["overview", "my_requirements", "received_responses", "shortlisted_responses"];
  return ["overview"];
}

function defaultFieldsForRole(roleKey: string): string[] {
  const key = String(roleKey || "").toUpperCase();
  if (key.includes("COMPANY")) return [...COMMON_PROFILE_FIELDS, "company_name"];
  if (key.includes("CUSTOMER") || key.includes("SERVICE_SEEKER")) return [...COMMON_PROFILE_FIELDS, "service_preferences"];
  if (key.includes("JOB_SEEKER") || key.includes("JOBSEEKER")) return [...COMMON_PROFILE_FIELDS, "work_experience", "skills"];
  return [...COMMON_PROFILE_FIELDS, "service_categories", "experience_years"];
}

function asStringArray(value: unknown): string[] {
  if (!Array.isArray(value)) return [];
  return value.map((item) => String(item || "").trim()).filter(Boolean);
}

function normalizeDashboard(item: any): ExternalDashboard {
  const cfg = item?.config_json ?? {};
  const widgets = asStringArray(
    Array.isArray(cfg?.widgets)
      ? cfg.widgets.map((w: any) => (typeof w === "string" ? w : w?.key || w?.id))
      : []
  );
  const tabs = asStringArray(cfg?.tabs);
  const sidebarItems = asStringArray(cfg?.sidebar_items ?? cfg?.sidebarItems);
  const fields = asStringArray(cfg?.fields);
  const previewPath = String(cfg?.preview_path || cfg?.previewPath || "").trim();
  const pkgCardColors = cfg?.pkg_card && typeof cfg.pkg_card === "object" ? cfg.pkg_card : undefined;

  const isInactive =
    item?.is_active === false || String(item?.status || "").toUpperCase() === "INACTIVE";
  const isDraft = String(item?.status || "").toUpperCase() === "DRAFT";

  return {
    id: String(item?.id || ""),
    roleId: String(item?.role_id || ""),
    roleKey: String(cfg?.role_key || cfg?.roleKey || item?.role_key || ""),
    name: String(cfg?.name || item?.name || "External Dashboard"),
    code: String(cfg?.code || item?.code || ""),
    widgets,
    tabs,
    sidebarItems,
    fields,
    previewPath,
    status: isInactive ? "INACTIVE" : isDraft ? "DRAFT" : "ACTIVE",
    updatedAt: String(item?.updated_at || ""),
    pkgCardColors,
  };
}

function looksLikeGateway404(payload: any): boolean {
  const text = String(payload?.message || payload?.error || payload || "").toLowerCase();
  return text.includes("route not found in gateway");
}

function normalizeRoleNameFromKey(key: string): string {
  return String(key || "")
    .toLowerCase()
    .replace(/_/g, " ")
    .replace(/\b\w/g, (c) => c.toUpperCase());
}

function StatusBadge(props: { status: string }) {
  const active = () => props.status === "ACTIVE";
  return (
    <span
      style={`display:inline-flex;align-items:center;border-radius:9999px;border:1px solid ${active() ? "#FFD8C2" : "#D1D5DB"};background:${active() ? "#FFF1EB" : "#F3F4F6"};color:${active() ? "#FF5E13" : "#4B5563"};padding:2px 10px;font-size:12px;font-weight:500`}
    >
      {active() ? "Active" : "Inactive"}
    </span>
  );
}

export default function ExternalDashboardManagementPage() {
  const [rows, setRows] = createSignal<ExternalDashboard[]>([]);
  const [roles, setRoles] = createSignal<RoleOption[]>([]);
  const [loading, setLoading] = createSignal(false);
  const [saving, setSaving] = createSignal(false);
  const [error, setError] = createSignal("");

  const [view, setView] = createSignal<"list" | "form">("list");
  const [editingId, setEditingId] = createSignal<string | null>(null);
  const [formTab, setFormTab] = createSignal<
    "general" | "tabs" | "sidebar" | "fields" | "theme" | "preview" | "full_preview"
  >("general");
  const [isFullscreenPreview, setIsFullscreenPreview] = createSignal(false);
  const [listTab, setListTab] = createSignal<"all" | "create">("all");

  const [search, setSearch] = createSignal("");
  const [statusFilter, setStatusFilter] = createSignal<"all" | "active" | "inactive">("all");
  const [sortBy, setSortBy] = createSignal<
    "name_asc" | "name_desc" | "updated_desc" | "updated_asc"
  >("updated_desc");
  const [sortMenuOpen, setSortMenuOpen] = createSignal(false);
  const [filterMenuOpen, setFilterMenuOpen] = createSignal(false);

  const [name, setName] = createSignal("");
  const [code, setCode] = createSignal("");
  const [roleId, setRoleId] = createSignal("");
  const [formRoleKey, setFormRoleKey] = createSignal("");
  const [widgets, setWidgets] = createSignal<string[]>([]);
  const [tabs, setTabs] = createSignal<string[]>([]);
  const [sidebarItems, setSidebarItems] = createSignal<string[]>([]);
  const [fields, setFields] = createSignal<string[]>([]);
  const [previewPath, setPreviewPath] = createSignal("");
  const [isActive, setIsActive] = createSignal(true);
  const [dragWidget, setDragWidget] = createSignal<string | null>(null);
  const [activePreviewSidebar, setActivePreviewSidebar] = createSignal("");
  const [activePreviewTab, setActivePreviewTab] = createSignal("");

  type PkgCardColors = {
    white?: string;
    coin_bg?: string;
    coin_avatar_bg?: string;
    best_value_bg?: string;
    border_default?: string;
    text_secondary?: string;
    text_primary?: string;
    text_accent?: string;
    text_muted?: string;
    text_success?: string;
    shadow_default?: string;
    shadow_accent?: string;
  };
  const [pkgCardColors, setPkgCardColors] = createSignal<PkgCardColors>({});

  const rolePersonaById = createMemo(() => {
    const map: Record<string, "PROFESSIONAL" | "COMPANY" | "JOB_SEEKER" | "CUSTOMER"> = {};
    for (const role of roles()) {
      const key = role.key.toUpperCase();
      if (key.includes("COMPANY")) map[role.id] = "COMPANY";
      else if (key.includes("CUSTOMER") || key.includes("SERVICE_SEEKER"))
        {map[role.id] = "CUSTOMER";}
      else if (key.includes("JOB_SEEKER") || key.includes("JOBSEEKER")) map[role.id] = "JOB_SEEKER";
      else map[role.id] = "PROFESSIONAL";
    }
    return map;
  });

  const personaFromKey = (
    key: string
  ): "PROFESSIONAL" | "COMPANY" | "JOB_SEEKER" | "CUSTOMER" | null => {
    const k = String(key || "").toUpperCase();
    if (!k) return null;
    if (k.includes("COMPANY")) return "COMPANY";
    if (k.includes("CUSTOMER") || k.includes("SERVICE_SEEKER")) return "CUSTOMER";
    if (k.includes("JOB_SEEKER") || k.includes("JOBSEEKER")) return "JOB_SEEKER";
    return "PROFESSIONAL"; // photographer, makeup, tutor, developer, video, graphic, social, fitness, catering, etc.
  };

  const availableWidgetOptions = createMemo(() => {
    const persona = personaFromKey(formRoleKey()) || "PROFESSIONAL";
    return ROLE_WIDGETS[persona] || [];
  });

  const sidebarLooksCustomer = createMemo(() => {
    const joined = sidebarItems().join(" ").toLowerCase();
    return (
      joined.includes("my requirements") ||
      joined.includes("received responses") ||
      joined.includes("shortlisted responses")
    );
  });

  const selectedRoleKey = createMemo(() => {
    const selected = roles().find((r) => r.id === roleId());
    return selected?.key || "";
  });

  const previewSidebarItems = createMemo(() => {
    const selectedRoleId = roleId();
    // Primary: look up persona by role ID (from loaded roles list)
    const personaById = rolePersonaById()[selectedRoleId];
    // Fallback: derive persona directly from the stored role key (works when roles API is empty or roleId unmatched)
    const personaByKey = personaFromKey(selectedRoleKey() || formRoleKey());
    const persona = personaById ?? personaByKey;
    const baseItems = sidebarItems().length
      ? sidebarItems()
      : sidebarLooksCustomer()
        ? ROLE_BASED_SIDEBAR.CUSTOMER
        : ["My Dashboard", "My Profile", "Switch Services", "Logout"];
    const merged = mergeSidebarForPersona(
      baseItems,
      persona ?? (sidebarLooksCustomer() ? "CUSTOMER" : null)
    );
    // Deduplicate by normalized key to prevent duplicates from any merge path
    const seen = new Map<string, string>();
    for (const item of merged) {
      const key = normalizeToken(item);
      if (!seen.has(key)) seen.set(key, item);
    }
    return Array.from(seen.values());
  });
  const previewTabs = createMemo(() => (tabs().length ? tabs() : ["overview"]));

  const authHeaders = () => {
    const token =
      typeof sessionStorage !== "undefined"
        ? sessionStorage.getItem("nxtgauge_admin_access_token") || ""
        : "";
    return { Accept: "application/json", ...(token ? { Authorization: `Bearer ${token}` } : {}) };
  };

  const toggle = (
    list: () => string[],
    setter: (v: string[] | ((p: string[]) => string[])) => void,
    value: string
  ) => {
    setter((prev: string[]) =>
      prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value]
    );
  };

  const addWidget = (key: string) => {
    setWidgets((prev) => (prev.includes(key) ? prev : [...prev, key]));
  };

  const removeWidget = (key: string) => {
    setWidgets((prev) => prev.filter((v) => v !== key));
  };

  const moveWidget = (movingKey: string, targetKey: string) => {
    if (!movingKey || !targetKey || movingKey === targetKey) return;
    setWidgets((prev) => {
      const from = prev.indexOf(movingKey);
      const to = prev.indexOf(targetKey);
      if (from === -1 || to === -1) return prev;
      const next = [...prev];
      next.splice(from, 1);
      next.splice(to, 0, movingKey);
      return next;
    });
  };

  const applySidebarPresetForRole = (selectedRoleId: string, force = false) => {
    const persona = rolePersonaById()[selectedRoleId];
    if (!persona) return;
    if (!force && sidebarItems().length > 0) return;
    setSidebarItems(mergeSidebarForPersona(ROLE_BASED_SIDEBAR[persona], persona));
  };

  const applyPreviewPathForRole = (selectedRoleId: string, force = false) => {
    const role = roles().find((r) => r.id === selectedRoleId);
    if (!role) return;
    if (!force && previewPath().trim()) return;
    setPreviewPath(rolePreviewPath(role.key));
  };

  const applyTabsPresetForRole = (selectedRoleId: string, force = false) => {
    const role = roles().find((r) => r.id === selectedRoleId);
    if (!role) return;
    if (!force && tabs().length > 0) return;
    setTabs(defaultTabsForRole(role.key));
  };

  const applyFieldsPresetForRole = (selectedRoleId: string, force = false) => {
    const role = roles().find((r) => r.id === selectedRoleId);
    if (!role) return;
    if (!force && fields().length > 0) return;
    setFields(defaultFieldsForRole(role.key));
  };

  const loadAll = async () => {
    setLoading(true);
    setError("");
    try {
      const [rolesRes, modulesRes] = await Promise.all([
        fetch(`${API}/api/admin/external-roles?per_page=200`, {
          headers: authHeaders(),
          credentials: "include",
        }),
        fetch(`${API}/api/admin/modules`, {
          headers: authHeaders(),
          credentials: "include",
        }),
      ]);

      if (!rolesRes.ok) throw new Error(`Failed to load roles (${rolesRes.status})`);
      if (!modulesRes.ok) throw new Error(`Failed to load modules (${modulesRes.status})`);

      const roleData = await rolesRes.json().catch(() => []);
      const modulesData = await modulesRes.json().catch(() => []);

      const roleRows = roleData?.roles || roleData?.items || roleData || [];
      const modules: Module[] = modulesData?.items || modulesData || [];

      const moduleByKey = new Map(modules.map((m: Module) => [m.module_key, m]));

      setRoles(
        roleRows
          .filter((r: any) => r?.status === "ACTIVE" || r?.status === "INACTIVE")
          .map((r: any) => ({
            id: String(r?.id || ""),
            key: String(r?.code || r?.key || "").toUpperCase(),
            name: String(r?.name || r?.key || "External Role"),
          }))
          .filter((r: RoleOption) => r.id)
      );

      const permissionMap: Record<string, RolePermission[]> = {};
      for (const role of roleRows) {
        try {
          const permRes = await fetch(`${API}/api/admin/roles/${role.id}/permissions`, {
            headers: authHeaders(),
            credentials: "include",
          });
          if (permRes.ok) {
            const perms = await permRes.json();
            permissionMap[role.id] = perms || [];
          }
        } catch {
          permissionMap[role.id] = [];
        }
      }

      const dashboardRows: ExternalDashboard[] = roleRows
        .filter((r: any) => r?.status === "ACTIVE" || r?.status === "INACTIVE")
        .map((r: any) => {
          const roleKey = String(r?.code || r?.key || "").toUpperCase();
          const roleId = String(r?.id || "");
          const roleName = String(r?.name || normalizeRoleNameFromKey(roleKey));
          const perms = permissionMap[roleId] || [];

          const viewablePerms = perms.filter((p: RolePermission) => p.can_view || p.can_list);

          const sidebarItems = viewablePerms
            .map((p: RolePermission) => {
              const mod = moduleByKey.get(p.module_key);
              return mod?.default_sidebar_label || p.module_name;
            })
            .filter(Boolean);

          return {
            id: `dashboard-${roleId}`,
            roleId,
            roleKey,
            name: `${roleName} Dashboard`,
            code: `EXTERNAL-${roleKey}`,
            widgets: [],
            tabs: defaultTabsForRole(roleKey),
            sidebarItems,
            fields: defaultFieldsForRole(roleKey),
            previewPath: rolePreviewPath(roleKey),
            status: (r?.status === "INACTIVE" ? "INACTIVE" : "ACTIVE") as "ACTIVE" | "INACTIVE" | "DRAFT",
            updatedAt: r?.updated_at || r?.created_date || "",
          };
        });

      setRows(dashboardRows.sort((a: ExternalDashboard, b: ExternalDashboard) =>
        b.updatedAt.localeCompare(a.updatedAt)
      ));
    } catch (e: any) {
      setRows([]);
      setRoles([]);
      setError(e?.message || "Failed to load external dashboards.");
    } finally {
      setLoading(false);
    }
  };

  onMount(() => void loadAll());

  const filtered = createMemo(() => {
    const q = search().trim().toLowerCase();
    const next = rows().filter((row) => {
      if (statusFilter() === "active" && row.status !== "ACTIVE") return false;
      if (statusFilter() === "inactive" && row.status === "ACTIVE") return false;
      if (!q) return true;
      return (
        row.name.toLowerCase().includes(q) ||
        row.code.toLowerCase().includes(q) ||
        row.roleKey.toLowerCase().includes(q)
      );
    });
    next.sort((a, b) => {
      if (sortBy() === "name_asc") return a.name.localeCompare(b.name);
      if (sortBy() === "name_desc") return b.name.localeCompare(a.name);
      if (sortBy() === "updated_asc") return a.updatedAt.localeCompare(b.updatedAt);
      return b.updatedAt.localeCompare(a.updatedAt);
    });
    return next;
  });

  const resetForm = () => {
    setEditingId(null);
    setFormTab("preview");
    setName("");
    setCode("");
    const firstRole = roles()[0];
    setRoleId(firstRole?.id || "");
    setFormRoleKey(firstRole?.key || "");
    setWidgets([]);
    setTabs([]);
    setSidebarItems([]);
    setFields([]);
    setPreviewPath("");
    setIsActive(true);
    setActivePreviewSidebar("My Profile");
    setActivePreviewTab("basic info");
    setPkgCardColors({});
  };

  const openCreate = () => {
    resetForm();
    setListTab("create");
    setView("form");
  };

  const openEdit = (row: ExternalDashboard) => {
    setEditingId(row.id);
    setFormTab("preview");
    setName(row.name);
    setCode(row.code);
    setRoleId(row.roleId);
    setFormRoleKey(row.roleKey);
    setWidgets(row.widgets);
    setTabs(row.tabs);
    const persona = rolePersonaById()[row.roleId] ?? personaFromKey(row.roleKey);
    setSidebarItems(mergeSidebarForPersona(row.sidebarItems, persona));
    setFields(row.fields);
    setPreviewPath(row.previewPath || rolePreviewPath(row.roleKey));
    setIsActive(row.status === "ACTIVE");
    setActivePreviewSidebar("My Profile");
    setActivePreviewTab("basic info");
    setPkgCardColors(row.pkgCardColors || {});
    setListTab("create");
    setView("form");
  };

  createEffect(() => {
    const selected = roleId();
    if (!selected || view() !== "form" || editingId()) return;
    // Sync formRoleKey whenever roleId changes (so persona fallback stays fresh)
    const matchedRole = roles().find((r) => r.id === selected);
    if (matchedRole) setFormRoleKey(matchedRole.key);
    applySidebarPresetForRole(selected, false);
    applyTabsPresetForRole(selected, false);
    applyFieldsPresetForRole(selected, false);
    applyPreviewPathForRole(selected, false);
  });

  createEffect(() => {
    if (view() !== "form") return;
    const persona =
      rolePersonaById()[roleId()] ?? personaFromKey(selectedRoleKey() || formRoleKey());
    if (!persona || !sidebarItems().length) return;
    setSidebarItems((prev) => {
      const next = mergeSidebarForPersona(prev, persona);
      return sameSidebarOrder(prev, next) ? prev : next;
    });
  });

  createEffect(() => {
    const items = previewSidebarItems();
    if (!items.includes(activePreviewSidebar())) setActivePreviewSidebar(items[0] || "");
  });

  createEffect(() => {
    const selected = roleId();
    const persona = rolePersonaById()[selected];
    if (!persona) return;
    if (view() !== "form" || editingId()) return;
    setSidebarItems(mergeSidebarForPersona(ROLE_BASED_SIDEBAR[persona], persona));
  });

  createEffect(() => {
    const list = tabs(); // use configured tabs only — not the fallback ['overview']
    if (!list.length) return; // sidebar-driven tabs (profile, portfolio, etc.) manage validation internally
    const active = normalizeToken(activePreviewTab());
    if (!list.some((item) => normalizeToken(item) === active)) setActivePreviewTab(list[0] || "");
  });

  const hasTab = (key: string) =>
    tabs().some((item) => normalizeToken(item) === normalizeToken(key));
  const toggleTab = (key: string) => {
    setTabs((prev) =>
      prev.some((item) => normalizeToken(item) === normalizeToken(key))
        ? prev.filter((item) => normalizeToken(item) !== normalizeToken(key))
        : [...prev, key]
    );
  };

  const saveDashboard = async () => {
    if (!name().trim()) return setError("Dashboard name is required.");
    if (!roleId()) return setError("External role is required.");

    const selectedRole = roles().find((r) => r.id === roleId());
    if (!selectedRole) return setError("Selected role is invalid.");

    setSaving(true);
    setError("");
    try {
      const res = await fetch(`${API}/api/admin/dashboard-config`, {
        method: "POST",
        headers: { "Content-Type": "application/json", ...authHeaders() },
        credentials: "include",
        body: JSON.stringify({
          role_id: roleId(),
          audience: "EXTERNAL",
          is_active: isActive(),
          config_json: {
            name: name().trim(),
            code: code().trim() || `EXTERNAL-${selectedRole.key}`,
            role_key: selectedRole.key,
            widgets: widgets().map((key) => ({ key })),
            tabs: tabs(),
            sidebar_items: sidebarItems(),
            fields: fields(),
            preview_path: previewPath().trim() || rolePreviewPath(selectedRole.key),
            switch_role: {
              visible_if_multi_role: true,
            },
            explore_nxtgauge: {
              enabled: true,
              intent: "role_marketplace_and_profile_verification",
            },
            pkg_card: pkgCardColors(),
          },
        }),
      });
      const payload = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(payload?.message || `Request failed (${res.status})`);
      await loadAll();
      setView("list");
      setListTab("all");
      resetForm();
    } catch (e: any) {
      setError(e?.message || "Failed to save external dashboard.");
    } finally {
      setSaving(false);
    }
  };

  return (
    <div class="w-full space-y-6 pb-8">
      <div>
        <h1 class="text-[28px] font-bold leading-tight text-[#111827]">
          External Dashboard Management
        </h1>
        <p class="mt-1 text-[14px] text-[#6B7280]">
          Create dashboards with tabs, sidebar and fields, then preview before saving.
        </p>
      </div>

      <Show when={error()}>
        <div style="border-radius:10px;border:1px solid #FECACA;background:#FEF2F2;padding:12px 16px;font-size:13px;color:#B91C1C">
          {error()}
        </div>
      </Show>

      <Show
        when={view() === "list"}
        fallback={
          <div style="border-radius:16px;border:1px solid #E5E7EB;background:white;box-shadow:0 1px 4px rgba(0,0,0,0.06);overflow:hidden">
            <div style="padding:18px 24px;border-bottom:1px solid #E5E7EB;display:flex;justify-content:space-between;align-items:center">
              <p style="margin:0;font-size:16px;font-weight:700;color:#111827">
                {editingId() ? "Edit External Dashboard" : "Create External Dashboard"}
              </p>
              <button
                type="button"
                onClick={() => {
                  setView("list");
                  resetForm();
                }}
                style="height:34px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 14px;font-size:12px;font-weight:700;color:#374151;cursor:pointer"
              >
                Back
              </button>
            </div>

            <div style="display:flex;gap:4px;border-bottom:1px solid #E5E7EB;padding:0 16px;background:#FAFAFA">
              <For each={["general", "tabs", "sidebar", "fields", "theme", "preview", "full_preview"] as const}>
                {(tab) => (
                  <button
                    type="button"
                    onClick={() => setFormTab(tab)}
                    style={`position:relative;padding:12px 10px;font-size:12px;font-weight:500;border:none;background:none;cursor:pointer;color:${formTab() === tab ? "#FF5E13" : "#6B7280"}`}
                  >
                    {humanizeLabel(tab)}
                    <Show when={formTab() === tab}>
                      <span style="position:absolute;left:0;right:0;bottom:0;height:2px;background:#FF5E13" />
                    </Show>
                  </button>
                )}
              </For>
            </div>

            <div style="padding:24px">
              <Show when={formTab() === "general"}>
                <div style="display:grid;grid-template-columns:1fr 1fr;gap:16px">
                  <label style="display:block">
                    <span style="font-size:13px;font-weight:600;color:#374151">
                      Dashboard Name *
                    </span>
                    <input
                      value={name()}
                      onInput={(e) => setName(e.currentTarget.value)}
                      style="display:block;margin-top:6px;height:40px;width:100%;border-radius:10px;border:1px solid #E5E7EB;padding:0 14px;font-size:13px"
                    />
                  </label>
                  <label style="display:block">
                    <span style="font-size:13px;font-weight:600;color:#374151">Code</span>
                    <input
                      value={code()}
                      onInput={(e) => setCode(e.currentTarget.value)}
                      placeholder="Optional"
                      style="display:block;margin-top:6px;height:40px;width:100%;border-radius:10px;border:1px solid #E5E7EB;padding:0 14px;font-size:13px"
                    />
                  </label>
                  <label style="display:block;grid-column:1 / -1">
                    <span style="font-size:13px;font-weight:600;color:#374151">
                      External Role *
                    </span>
                    <select
                      value={roleId()}
                      onChange={(e) => setRoleId(e.currentTarget.value)}
                      style="display:block;margin-top:6px;height:40px;width:100%;border-radius:10px;border:1px solid #E5E7EB;padding:0 14px;font-size:13px;background:white"
                    >
                      <For each={roles()}>
                        {(r) => (
                          <option value={r.id}>
                            {r.name} ({r.key})
                          </option>
                        )}
                      </For>
                    </select>
                  </label>
                  <div style="grid-column:1 / -1">
                    <span style="font-size:13px;font-weight:600;color:#374151">
                      Widgets (Drag & Drop)
                    </span>
                    <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:8px">
                      <div style="border:1px solid #E5E7EB;border-radius:10px;padding:10px;background:#FAFAFA">
                        <p style="margin:0;font-size:11px;font-weight:800;color:#6B7280;text-transform:uppercase">
                          Available Widgets
                        </p>
                        <div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:8px">
                          <For each={availableWidgetOptions()}>
                            {(key) => (
                              <button
                                type="button"
                                onClick={() => addWidget(key)}
                                style={`height:30px;border-radius:8px;padding:0 10px;font-size:11px;font-weight:700;cursor:pointer;border:1px solid ${widgets().includes(key) ? "#D1D5DB" : "#E5E7EB"};background:${widgets().includes(key) ? "#F3F4F6" : "white"};color:#374151`}
                              >
                                + {key}
                              </button>
                            )}
                          </For>
                        </div>
                      </div>
                      <div
                        style="border:1px solid #E5E7EB;border-radius:10px;padding:10px;background:white;min-height:120px"
                        onDragOver={(e) => e.preventDefault()}
                      >
                        <p style="margin:0;font-size:11px;font-weight:800;color:#6B7280;text-transform:uppercase">
                          Selected Order
                        </p>
                        <Show
                          when={widgets().length > 0}
                          fallback={
                            <p style="margin-top:10px;font-size:12px;color:#9CA3AF">
                              No widgets selected yet.
                            </p>
                          }
                        >
                          <div style="display:flex;flex-direction:column;gap:8px;margin-top:8px">
                            <For each={widgets()}>
                              {(key) => (
                                <div
                                  draggable
                                  onDragStart={(e) => {
                                    setDragWidget(key);
                                    e.dataTransfer?.setData("text/plain", key);
                                  }}
                                  onDragOver={(e) => e.preventDefault()}
                                  onDrop={(e) => {
                                    e.preventDefault();
                                    moveWidget(dragWidget() || "", key);
                                    setDragWidget(null);
                                  }}
                                  style={`display:flex;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px;border:1px solid #E5E7EB;border-radius:8px;background:${dragWidget() === key ? "#FFF7ED" : "#F9FAFB"};cursor:grab`}
                                >
                                  <span style="font-size:12px;font-weight:700;color:#374151">
                                    :: {key}
                                  </span>
                                  <button
                                    type="button"
                                    onClick={() => removeWidget(key)}
                                    style="height:24px;border-radius:6px;border:1px solid #FECACA;background:#FEF2F2;padding:0 8px;font-size:11px;font-weight:700;color:#B91C1C;cursor:pointer"
                                  >
                                    Remove
                                  </button>
                                </div>
                              )}
                            </For>
                          </div>
                        </Show>
                      </div>
                    </div>
                  </div>
                  <label style="display:flex;align-items:center;gap:8px;grid-column:1 / -1;font-size:13px;color:#374151">
                    <input
                      type="checkbox"
                      checked={isActive()}
                      onChange={(e) => setIsActive(e.currentTarget.checked)}
                      style="width:16px;height:16px;accent-color:#0D0D2A"
                    />
                    Active dashboard
                  </label>
                </div>
              </Show>

              <Show when={formTab() === "tabs"}>
                <div>
                  <p style="font-size:13px;font-weight:600;color:#374151">Dashboard Tabs</p>
                  <div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:8px">
                    <For each={AVAILABLE_TABS}>
                      {(key) => (
                        <button
                          type="button"
                          onClick={() => toggleTab(key)}
                          style={`height:30px;border-radius:8px;padding:0 10px;font-size:11px;font-weight:700;cursor:pointer;border:1px solid ${hasTab(key) ? "#0D0D2A" : "#E5E7EB"};background:${hasTab(key) ? "#0D0D2A" : "white"};color:${hasTab(key) ? "white" : "#374151"}`}
                        >
                          {humanizeLabel(key)}
                        </button>
                      )}
                    </For>
                  </div>
                </div>
              </Show>

              <Show when={formTab() === "sidebar"}>
                <div>
                  <p style="font-size:13px;font-weight:600;color:#374151">Sidebar Items</p>
                  <div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:8px">
                    <For each={AVAILABLE_SIDEBAR_ITEMS}>
                      {(key) => (
                        <button
                          type="button"
                          onClick={() => toggle(sidebarItems, setSidebarItems, key)}
                          style={`height:30px;border-radius:8px;padding:0 10px;font-size:11px;font-weight:700;cursor:pointer;border:1px solid ${sidebarItems().includes(key) ? "#0D0D2A" : "#E5E7EB"};background:${sidebarItems().includes(key) ? "#0D0D2A" : "white"};color:${sidebarItems().includes(key) ? "white" : "#374151"}`}
                        >
                          {key}
                        </button>
                      )}
                    </For>
                  </div>
                </div>
              </Show>

              <Show when={formTab() === "fields"}>
                <div>
                  <p style="font-size:13px;font-weight:600;color:#374151">Visible Fields</p>
                  <div style="display:flex;flex-wrap:wrap;gap:8px;margin-top:8px">
                    <For each={AVAILABLE_FIELDS}>
                      {(key) => (
                        <button
                          type="button"
                          onClick={() => toggle(fields, setFields, key)}
                          style={`height:30px;border-radius:8px;padding:0 10px;font-size:11px;font-weight:700;cursor:pointer;border:1px solid ${fields().includes(key) ? "#0D0D2A" : "#E5E7EB"};background:${fields().includes(key) ? "#0D0D2A" : "white"};color:${fields().includes(key) ? "white" : "#374151"}`}
                        >
                          {key}
                        </button>
                      )}
                    </For>
                  </div>
                </div>
              </Show>

              <Show when={formTab() === "theme"}>
                <div style="display:flex;flex-direction:column;gap:16px">
                  <p style="font-size:13px;color:#6B7280;margin:0">
                    Configure colors for the Buy Credits package cards. Leave blank to use defaults.
                  </p>
                  <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px">
                    <label style="display:block">
                      <span style="font-size:12px;font-weight:600;color:#374151">Text Accent (Price Color)</span>
                      <div style="display:flex;gap:8px;align-items:center;margin-top:4px">
                        <input
                          type="color"
                          value={pkgCardColors().text_accent ?? "#FF5E13"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_accent: e.currentTarget.value }))}
                          style="width:36px;height:36px;border-radius:8px;border:1px solid #E5E7EB;cursor:pointer"
                        />
                        <input
                          type="text"
                          value={pkgCardColors().text_accent ?? "#FF5E13"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_accent: e.currentTarget.value }))}
                          style="flex:1;height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
                          placeholder="#FF5E13"
                        />
                      </div>
                    </label>
                    <label style="display:block">
                      <span style="font-size:12px;font-weight:600;color:#374151">Text Primary</span>
                      <div style="display:flex;gap:8px;align-items:center;margin-top:4px">
                        <input
                          type="color"
                          value={pkgCardColors().text_primary ?? "#111827"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_primary: e.currentTarget.value }))}
                          style="width:36px;height:36px;border-radius:8px;border:1px solid #E5E7EB;cursor:pointer"
                        />
                        <input
                          type="text"
                          value={pkgCardColors().text_primary ?? "#111827"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_primary: e.currentTarget.value }))}
                          style="flex:1;height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
                          placeholder="#111827"
                        />
                      </div>
                    </label>
                    <label style="display:block">
                      <span style="font-size:12px;font-weight:600;color:#374151">Text Secondary</span>
                      <div style="display:flex;gap:8px;align-items:center;margin-top:4px">
                        <input
                          type="color"
                          value={pkgCardColors().text_secondary ?? "#6B7280"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_secondary: e.currentTarget.value }))}
                          style="width:36px;height:36px;border-radius:8px;border:1px solid #E5E7EB;cursor:pointer"
                        />
                        <input
                          type="text"
                          value={pkgCardColors().text_secondary ?? "#6B7280"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_secondary: e.currentTarget.value }))}
                          style="flex:1;height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
                          placeholder="#6B7280"
                        />
                      </div>
                    </label>
                    <label style="display:block">
                      <span style="font-size:12px;font-weight:600;color:#374151">Text Muted</span>
                      <div style="display:flex;gap:8px;align-items:center;margin-top:4px">
                        <input
                          type="color"
                          value={pkgCardColors().text_muted ?? "#9CA3AF"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_muted: e.currentTarget.value }))}
                          style="width:36px;height:36px;border-radius:8px;border:1px solid #E5E7EB;cursor:pointer"
                        />
                        <input
                          type="text"
                          value={pkgCardColors().text_muted ?? "#9CA3AF"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_muted: e.currentTarget.value }))}
                          style="flex:1;height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
                          placeholder="#9CA3AF"
                        />
                      </div>
                    </label>
                    <label style="display:block">
                      <span style="font-size:12px;font-weight:600;color:#374151">Text Success (Coins per ₹)</span>
                      <div style="display:flex;gap:8px;align-items:center;margin-top:4px">
                        <input
                          type="color"
                          value={pkgCardColors().text_success ?? "#16A34A"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_success: e.currentTarget.value }))}
                          style="width:36px;height:36px;border-radius:8px;border:1px solid #E5E7EB;cursor:pointer"
                        />
                        <input
                          type="text"
                          value={pkgCardColors().text_success ?? "#16A34A"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, text_success: e.currentTarget.value }))}
                          style="flex:1;height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
                          placeholder="#16A34A"
                        />
                      </div>
                    </label>
                    <label style="display:block">
                      <span style="font-size:12px;font-weight:600;color:#374151">Coin Background</span>
                      <div style="display:flex;gap:8px;align-items:center;margin-top:4px">
                        <input
                          type="color"
                          value={pkgCardColors().coin_bg ?? "#FFFBF8"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, coin_bg: e.currentTarget.value }))}
                          style="width:36px;height:36px;border-radius:8px;border:1px solid #E5E7EB;cursor:pointer"
                        />
                        <input
                          type="text"
                          value={pkgCardColors().coin_bg ?? "#FFFBF8"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, coin_bg: e.currentTarget.value }))}
                          style="flex:1;height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
                          placeholder="#FFFBF8"
                        />
                      </div>
                    </label>
                    <label style="display:block">
                      <span style="font-size:12px;font-weight:600;color:#374151">Best Value Badge BG</span>
                      <div style="display:flex;gap:8px;align-items:center;margin-top:4px">
                        <input
                          type="color"
                          value={pkgCardColors().best_value_bg?.split(" ")[2]?.replace(/[^#0-9A-Fa-f]/g, "") ?? "#FF5E13"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, best_value_bg: `linear-gradient(135deg, ${e.currentTarget.value} 0%, #FF8A5C 100%)` }))}
                          style="width:36px;height:36px;border-radius:8px;border:1px solid #E5E7EB;cursor:pointer"
                        />
                        <input
                          type="text"
                          value={pkgCardColors().best_value_bg ?? ""}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, best_value_bg: e.currentTarget.value }))}
                          style="flex:1;height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
                          placeholder="linear-gradient(...)"
                        />
                      </div>
                    </label>
                    <label style="display:block">
                      <span style="font-size:12px;font-weight:600;color:#374151">Border Default</span>
                      <div style="display:flex;gap:8px;align-items:center;margin-top:4px">
                        <input
                          type="color"
                          value={pkgCardColors().border_default ?? "#E5E7EB"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, border_default: e.currentTarget.value }))}
                          style="width:36px;height:36px;border-radius:8px;border:1px solid #E5E7EB;cursor:pointer"
                        />
                        <input
                          type="text"
                          value={pkgCardColors().border_default ?? "#E5E7EB"}
                          onInput={(e) => setPkgCardColors(c => ({ ...c, border_default: e.currentTarget.value }))}
                          style="flex:1;height:36px;border-radius:8px;border:1px solid #E5E7EB;padding:0 10px;font-size:13px"
                          placeholder="#E5E7EB"
                        />
                      </div>
                    </label>
                  </div>
                </div>
              </Show>

              <Show when={formTab() === "preview"}>
                <div style="display:flex;flex-direction:column;gap:10px">
                  <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;border:1px solid #E5E7EB;border-radius:10px;background:#FAFAFA">
                    <div>
                      <p style="margin:0;font-size:13px;font-weight:700;color:#111827">
                        Compact Preview
                      </p>
                      <p style="margin:2px 0 0;font-size:12px;color:#6B7280">
                        Validate role sidebar, tabs, and field sections before saving.
                      </p>
                    </div>
                    <button
                      type="button"
                      onClick={() => setFormTab("full_preview")}
                      style="height:32px;border-radius:8px;border:none;background:#0D0D2A;padding:0 12px;font-size:12px;font-weight:700;color:white;cursor:pointer"
                    >
                      Open Full Preview
                    </button>
                  </div>
                  <DashboardDesignPreview
                    status={isActive() ? "ACTIVE" : "INACTIVE"}
                    sidebarItems={previewSidebarItems()}
                    activeSidebar={activePreviewSidebar()}
                    onSidebarSelect={setActivePreviewSidebar}
                    tabs={previewTabs()}
                    activeTab={activePreviewTab()}
                    onTabSelect={setActivePreviewTab}
                    widgets={widgets()}
                    fields={fields()}
                    mode={"customer_external"}
                    roleKey={selectedRoleKey() || formRoleKey()}
                    exploreRoles={roles().map((r) => ({ key: r.key, name: r.name }))}
                    onOpenFullscreen={() => setFormTab("full_preview")}
                    dashboardConfig={{ pkg_card: pkgCardColors() }}
                  />
                </div>
              </Show>

              <Show when={formTab() === "full_preview"}>
                <div style="display:flex;flex-direction:column;gap:10px">
                  <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;border:1px solid #E5E7EB;border-radius:10px;background:#FAFAFA">
                    <div>
                      <p style="margin:0;font-size:13px;font-weight:700;color:#111827">
                        Full External Dashboard Preview
                      </p>
                      <p style="margin:2px 0 0;font-size:12px;color:#6B7280">
                        Navigate full sidebar and tabs in a larger canvas before saving.
                      </p>
                    </div>
                    <div style="display:flex;align-items:center;gap:8px">
                      <button
                        type="button"
                        onClick={() => setIsFullscreenPreview(true)}
                        style="height:32px;border-radius:8px;border:none;background:#0D0D2A;padding:0 12px;font-size:12px;font-weight:700;color:white;cursor:pointer"
                      >
                        Enter Full Screen
                      </button>
                      <button
                        type="button"
                        onClick={() => setFormTab("preview")}
                        style="height:32px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:700;color:#374151;cursor:pointer"
                      >
                        Back To Compact Preview
                      </button>
                    </div>
                  </div>
                  <div style="border:1px solid #E5E7EB;border-radius:14px;background:#FAFAFA;padding:12px;min-height:78vh;overflow:auto">
                    <DashboardDesignPreview
                      status={isActive() ? "ACTIVE" : "INACTIVE"}
                      sidebarItems={previewSidebarItems()}
                      activeSidebar={activePreviewSidebar()}
                      onSidebarSelect={setActivePreviewSidebar}
                      tabs={previewTabs()}
                      activeTab={activePreviewTab()}
                      onTabSelect={setActivePreviewTab}
                      widgets={widgets()}
                      fields={fields()}
                      mode={"customer_external"}
                      roleKey={selectedRoleKey() || formRoleKey()}
                      exploreRoles={roles().map((r) => ({ key: r.key, name: r.name }))}
                      dashboardConfig={{ pkg_card: pkgCardColors() }}
                    />
                  </div>
                </div>
              </Show>
            </div>

            <div style="padding:14px 24px;border-top:1px solid #E5E7EB;display:flex;justify-content:flex-end;gap:10px">
              <button
                type="button"
                onClick={() => {
                  setView("list");
                  resetForm();
                }}
                style="height:38px;border-radius:10px;border:1px solid #E5E7EB;background:white;padding:0 20px;font-size:13px;font-weight:600;color:#374151;cursor:pointer"
              >
                Cancel
              </button>
              <button
                type="button"
                onClick={() => void saveDashboard()}
                disabled={saving()}
                style="height:38px;border-radius:10px;background:#0D0D2A;padding:0 24px;font-size:13px;font-weight:600;color:white;border:none;cursor:pointer;opacity:0.95"
              >
                {saving() ? "Saving..." : editingId() ? "Update Dashboard" : "Create Dashboard"}
              </button>
            </div>
          </div>
        }
      >
        <div style="margin-top:24px;display:flex;align-items:center;gap:24px;border-bottom:1px solid #E5E7EB">
          <button
            type="button"
            onClick={() => {
              setListTab("all");
              setView("list");
            }}
            style={`padding-bottom:12px;font-size:14px;font-weight:500;background:none;border:none;cursor:pointer;${listTab() === "all" ? "color:#FF5E13;border-bottom:2px solid #FF5E13;margin-bottom:-1px" : "color:#6B7280"}`}
          >
            All Dashboards
          </button>
          <button
            type="button"
            onClick={openCreate}
            style={`padding-bottom:12px;font-size:14px;font-weight:500;background:none;border:none;cursor:pointer;${listTab() === "create" ? "color:#FF5E13;border-bottom:2px solid #FF5E13;margin-bottom:-1px" : "color:#6B7280"}`}
          >
            Create Dashboard
          </button>
        </div>

        <div style="position:relative;margin-top:1.5rem;margin-left:-24px;margin-right:-24px;border-radius:0;border-left:none;border-right:none;overflow:visible;border-top:1px solid #E5E7EB;border-bottom:1px solid #E5E7EB;background:white;box-shadow:0 1px 3px rgba(0,0,0,0.06)">
          <div style="display:flex;align-items:center;gap:8px;padding:14px 20px;border-bottom:1px solid #F3F4F6">
            <input
              value={search()}
              onInput={(e) => setSearch(e.currentTarget.value)}
              placeholder="Search dashboards..."
              style="height:34px;flex:1;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:13px;color:#111827;outline:none"
            />
            <div style="position:relative">
              <button
                type="button"
                onClick={() => {
                  setSortMenuOpen((v) => !v);
                  setFilterMenuOpen(false);
                }}
                style="display:inline-flex;height:34px;align-items:center;gap:6px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:500;color:#374151;cursor:pointer"
              >
                <svg
                  width="13"
                  height="13"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                >
                  <path d="M7 4v13" />
                  <path d="m3 13 4 4 4-4" />
                  <path d="M17 20V7" />
                  <path d="m21 11-4-4-4 4" />
                </svg>
                Sort
              </button>
              <Show when={sortMenuOpen()}>
                <div style="position:absolute;left:0;top:38px;z-index:30;min-width:200px;border-radius:12px;border:1px solid #E5E7EB;background:white;padding:6px;box-shadow:0 4px 16px rgba(0,0,0,0.1)">
                  <For
                    each={
                      [
                        ["name_asc", "Name (A-Z)"],
                        ["name_desc", "Name (Z-A)"],
                        ["updated_desc", "Updated (Newest)"],
                        ["updated_asc", "Updated (Oldest)"],
                      ] as const
                    }
                  >
                    {([key, label]) => (
                      <button
                        type="button"
                        onClick={() => {
                          setSortBy(key);
                          setSortMenuOpen(false);
                        }}
                        style={`display:block;width:100%;border-radius:8px;padding:8px 12px;text-align:left;font-size:13px;background:none;border:none;cursor:pointer;color:${sortBy() === key ? "#FF5E13" : "#374151"};background:${sortBy() === key ? "#FFF1EB" : "transparent"}`}
                      >
                        {label}
                      </button>
                    )}
                  </For>
                </div>
              </Show>
            </div>
            <div style="position:relative">
              <button
                type="button"
                onClick={() => {
                  setFilterMenuOpen((v) => !v);
                  setSortMenuOpen(false);
                }}
                style="display:inline-flex;height:34px;align-items:center;gap:6px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:500;color:#374151;cursor:pointer"
              >
                <svg
                  width="13"
                  height="13"
                  viewBox="0 0 24 24"
                  fill="none"
                  stroke="currentColor"
                  stroke-width="2"
                >
                  <path d="M3 5h18M6 12h12M10 19h4" />
                </svg>
                Filters
              </button>
              <Show when={filterMenuOpen()}>
                <div style="position:absolute;left:0;top:38px;z-index:30;min-width:160px;border-radius:12px;border:1px solid #E5E7EB;background:white;padding:6px;box-shadow:0 4px 16px rgba(0,0,0,0.1)">
                  <For
                    each={
                      [
                        ["all", "All Status"],
                        ["active", "Active"],
                        ["inactive", "Inactive"],
                      ] as const
                    }
                  >
                    {([key, label]) => (
                      <button
                        type="button"
                        onClick={() => {
                          setStatusFilter(key);
                          setFilterMenuOpen(false);
                        }}
                        style={`display:block;width:100%;border-radius:8px;padding:8px 12px;text-align:left;font-size:13px;background:none;border:none;cursor:pointer;color:${statusFilter() === key ? "#FF5E13" : "#374151"};background:${statusFilter() === key ? "#FFF1EB" : "transparent"}`}
                      >
                        {label}
                      </button>
                    )}
                  </For>
                </div>
              </Show>
            </div>
            <button
              type="button"
              style="display:inline-flex;height:34px;align-items:center;gap:6px;border-radius:8px;background:#0D0D2A;padding:0 12px;font-size:12px;font-weight:600;color:white;border:none;cursor:pointer"
            >
              <svg
                width="13"
                height="13"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                stroke-width="2"
              >
                <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
                <polyline points="7 10 12 15 17 10" />
                <line x1="12" y1="15" x2="12" y2="3" />
              </svg>
              Export
            </button>
          </div>

          <div class="overflow-x-auto overflow-y-visible">
            <table class="min-w-full">
              <thead>
                <tr style="background:#0D0D2A;text-align:left">
                  <For each={["Name", "Code", "Role", "Widgets", "Status", "Updated", "Actions"]}>
                    {(h) => (
                      <th style="padding:10px 20px;font-size:11px;font-weight:600;text-transform:uppercase;letter-spacing:0.05em;color:#FFFFFF;white-space:nowrap">
                        {h}
                      </th>
                    )}
                  </For>
                </tr>
              </thead>
              <tbody>
                <Show
                  when={!loading()}
                  fallback={
                    <tr>
                      <td colspan="7" style="padding:18px 20px;color:#6B7280;font-size:13px">
                        Loading dashboards...
                      </td>
                    </tr>
                  }
                >
                  <Show
                    when={filtered().length > 0}
                    fallback={
                      <tr>
                        <td colspan="7" style="padding:18px 20px;color:#6B7280;font-size:13px">
                          No external dashboards found.
                        </td>
                      </tr>
                    }
                  >
                    <For each={filtered()}>
                      {(row) => (
                        <tr
                          style="border-bottom:1px solid #F3F4F6"
                          class="hover:bg-[#FAFAFA] transition-colors"
                        >
                          <td style="padding:12px 20px;font-size:14px;font-weight:600;color:#111827">
                            {row.name}
                          </td>
                          <td style="padding:12px 20px;font-size:12px;color:#6B7280;font-family:monospace">
                            {row.code || "—"}
                          </td>
                          <td style="padding:12px 20px;font-size:13px;color:#374151">
                            {row.roleKey || "—"}
                          </td>
                          <td style="padding:12px 20px;font-size:13px;color:#374151">
                            {row.widgets.length}
                          </td>
                          <td style="padding:12px 20px">
                            <StatusBadge status={row.status} />
                          </td>
                          <td style="padding:12px 20px;font-size:13px;color:#6B7280">
                            {row.updatedAt ? new Date(row.updatedAt).toLocaleString() : "—"}
                          </td>
                          <td style="padding:12px 20px">
                            <button
                              type="button"
                              onClick={() => openEdit(row)}
                              style="height:30px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:700;color:#374151;cursor:pointer"
                            >
                              Edit
                            </button>
                          </td>
                        </tr>
                      )}
                    </For>
                  </Show>
                </Show>
              </tbody>
            </table>
          </div>

          <Show when={filtered().length > 0}>
            <div style="display:flex;align-items:center;justify-content:space-between;border-top:1px solid #F3F4F6;padding:12px 20px">
              <p style="font-size:13px;color:#6B7280">
                Showing <strong style="font-weight:600;color:#111827">1–{filtered().length}</strong>{" "}
                of <strong style="font-weight:600;color:#111827">{filtered().length}</strong>{" "}
                dashboards
              </p>
              <div style="display:flex;align-items:center;gap:4px">
                <button
                  type="button"
                  style="display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;border-radius:7px;border:1px solid #E5E7EB;background:white;color:#6B7280;cursor:pointer;font-size:15px"
                >
                  ‹
                </button>
                <button
                  type="button"
                  style="display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;border-radius:7px;background:#FF5E13;color:white;font-size:13px;font-weight:600;border:none;cursor:pointer"
                >
                  1
                </button>
                <button
                  type="button"
                  style="display:inline-flex;width:30px;height:30px;align-items:center;justify-content:center;border-radius:7px;border:1px solid #E5E7EB;background:white;color:#6B7280;cursor:pointer;font-size:15px"
                >
                  ›
                </button>
              </div>
            </div>
          </Show>
        </div>
      </Show>

      <Show when={isFullscreenPreview()}>
        <div style="position:fixed;inset:0;z-index:1000;background:#F3F4F6;padding:12px;display:flex;flex-direction:column;gap:10px">
          <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px 12px;border:1px solid #E5E7EB;border-radius:10px;background:white">
            <div>
              <p style="margin:0;font-size:13px;font-weight:700;color:#111827">
                Full Screen External Dashboard Preview
              </p>
              <p style="margin:2px 0 0;font-size:12px;color:#6B7280">
                Edge-to-edge preview for final visual validation.
              </p>
            </div>
            <button
              type="button"
              onClick={() => setIsFullscreenPreview(false)}
              style="height:34px;border-radius:8px;border:none;background:#0D0D2A;padding:0 12px;font-size:12px;font-weight:700;color:white;cursor:pointer"
            >
              Exit Full Screen
            </button>
          </div>

          <div style="flex:1;min-height:0;border:1px solid #E5E7EB;border-radius:14px;background:#FAFAFA;padding:12px;overflow:auto">
            <DashboardDesignPreview
              status={isActive() ? "ACTIVE" : "INACTIVE"}
              sidebarItems={previewSidebarItems()}
              activeSidebar={activePreviewSidebar()}
              onSidebarSelect={setActivePreviewSidebar}
              tabs={previewTabs()}
              activeTab={activePreviewTab()}
              onTabSelect={setActivePreviewTab}
              widgets={widgets()}
              fields={fields()}
              mode={"customer_external"}
              roleKey={selectedRoleKey() || formRoleKey()}
              exploreRoles={roles().map((r) => ({ key: r.key, name: r.name }))}
              dashboardConfig={{ pkg_card: pkgCardColors() }}
            />
          </div>
        </div>
      </Show>
    </div>
  );
}
