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

const API = '/api/gateway';

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

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;
};

const AVAILABLE_WIDGETS = ['kpi_summary', 'pending_approvals', 'user_growth', 'active_sessions', 'system_health', 'recent_activity', 'quick_actions', 'team_performance'];
const AVAILABLE_TABS = ['overview', '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',
    'Switch Services',
    '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',
    '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',
  'city',
  'role_status',
  'profile_completion',
  'verification_status',
  'kyc_status',
  'approval_status',
  'documents_submitted',
];
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') {
    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 '/users/choose-role';
}

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 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 || ''),
  };
}

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' | '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('');

  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 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'];
    return mergeSidebarForPersona(baseItems, persona ?? (sidebarLooksCustomer() ? 'CUSTOMER' : null));
  });
  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 loadAll = async () => {
    setLoading(true);
    setError('');
    try {
      const [dashRes, rolesRes] = await Promise.all([
        fetch(`${API}/api/admin/dashboard-config`, { headers: authHeaders(), credentials: 'include' }),
        fetch(`${API}/api/admin/roles?audience=EXTERNAL&per_page=200`, { headers: authHeaders(), credentials: 'include' }),
      ]);

      if (!dashRes.ok) throw new Error(`Failed to load dashboard config (${dashRes.status})`);
      if (!rolesRes.ok) throw new Error(`Failed to load external roles (${rolesRes.status})`);

      const dashData = await dashRes.json().catch(() => []);
      const roleData = await rolesRes.json().catch(() => []);
      if (looksLikeGateway404(dashData) || looksLikeGateway404(roleData)) {
        throw new Error('Required admin runtime endpoints are unavailable.');
      }

      const dashRows = Array.isArray(dashData) ? dashData : (dashData?.items || dashData?.configs || []);
      const roleRows = Array.isArray(roleData) ? roleData : (roleData?.roles || roleData?.items || []);

      setRoles(roleRows
        .filter((r: any) => {
          const hasRoleShape = Boolean(r?.id && (r?.key || r?.name));
          if (hasRoleShape && r?.audience == null) return true;
          return String(r?.audience || '').toUpperCase() === 'EXTERNAL';
        })
        .map((r: any) => ({ id: String(r?.id || ''), key: String(r?.key || '').toUpperCase(), name: String(r?.name || r?.key || 'External Role') }))
        .filter((r: RoleOption) => r.id));

      const roleKeyById = new Map<string, string>();
      roleRows.forEach((r: any) => {
        const id = String(r?.id || '').trim();
        const key = String(r?.key || '').toUpperCase().trim();
        if (id) roleKeyById.set(id, key);
      });

      setRows(dashRows
        .filter((item: any) => String(item?.audience || '').toUpperCase() === 'EXTERNAL')
        .map(normalizeDashboard)
        .map((row: ExternalDashboard) => {
          const resolvedRoleKey = String(row.roleKey || roleKeyById.get(row.roleId) || '').toUpperCase();
          const persona = personaFromKey(resolvedRoleKey);
          return {
            ...row,
            roleKey: resolvedRoleKey || row.roleKey,
            sidebarItems: mergeSidebarForPersona(row.sidebarItems, persona),
          };
        })
        .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');
  };

  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');
    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);
    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 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_onboarding',
            },
          },
        }),
      });
      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">
              {(['general', 'tabs', 'sidebar', 'fields', 'preview', 'full_preview'] as const).map((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>
              ))}
            </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={AVAILABLE_WIDGETS}>
                            {(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() === 'preview'}>
                <div style="display:flex;flex-direction:column;gap:10px">
                  <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()}
                    exploreRoles={roles().map((r) => ({ key: r.key, name: r.name }))}
                    onOpenFullscreen={() => setFormTab('full_preview')}
                  />
                </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:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:700;color:#374151;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:#F3F4F6;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()}
                      exploreRoles={roles().map((r) => ({ key: r.key, name: r.name }))}
                    />
                  </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)">
                    {([
                      ['name_asc', 'Name (A-Z)'],
                      ['name_desc', 'Name (Z-A)'],
                      ['updated_desc', 'Updated (Newest)'],
                      ['updated_asc', 'Updated (Oldest)'],
                    ] as const).map(([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>
                    ))}
                  </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)">
                    {([
                      ['all', 'All Status'],
                      ['active', 'Active'],
                      ['inactive', 'Inactive'],
                    ] as const).map(([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>
                    ))}
                  </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">
                    {['Name', 'Code', 'Role', 'Widgets', 'Status', 'Updated', 'Actions'].map((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>
                    ))}
                  </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:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;font-weight:700;color:#374151;cursor:pointer"
              >
                Exit Full Screen
              </button>
            </div>

            <div style="flex:1;min-height:0;border:1px solid #E5E7EB;border-radius:14px;background:#F3F4F6;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()}
                exploreRoles={roles().map((r) => ({ key: r.key, name: r.name }))}
              />
            </div>
          </div>
        </Show>
      </div>
  );
}
