import {
  Match,
  Show,
  Switch,
  createEffect,
  createMemo,
  createResource,
  createSignal,
  onMount,
} from "solid-js";
import { useNavigate, useLocation } from "@solidjs/router";
import { useAuth, RequireAuth, getToken } from "~/lib/auth";
import { fetchOnboardingSchemaForRole } from "~/lib/runtime/storage";
import DashboardDesignPreview from "~/components/admin/DashboardDesignPreview";
import DashboardShell from "~/components/DashboardShell";
import ProfilePage from "~/components/dashboard/ProfilePage";
import PortfolioPage from "~/components/dashboard/PortfolioPage";
import VerificationStatusPage from "~/components/dashboard/VerificationStatusPage";
import CompanyJobsPage from "~/components/dashboard/CompanyJobsPage";
import CompanyApplicationsPage from "~/components/dashboard/CompanyApplicationsPage";
import SettingsPage from "~/components/dashboard/SettingsPage";
import MyDashboardPage from "~/components/dashboard/MyDashboardPage";
import CustomerRequirementsPage from "~/components/dashboard/CustomerRequirementsPage";
import CustomerResponsesPage from "~/components/dashboard/CustomerResponsesPage";
import CompanyShortlistedCandidatesPage from "~/components/dashboard/CompanyShortlistedCandidatesPage";
import JobSeekerApplicationsPage from "~/components/dashboard/JobSeekerApplicationsPage";
import JobSeekerSavedJobsPage from "~/components/dashboard/JobSeekerSavedJobsPage";
import JobSeekerJobsPage from "~/components/dashboard/JobSeekerJobsPage";
import ProfessionalLeadsPage from "~/components/dashboard/ProfessionalLeadsPage";
import ProfessionalResponsesPage from "~/components/dashboard/ProfessionalResponsesPage";
import CreditsPage from "~/components/dashboard/CreditsPage";
import ExploreServicesPage from "~/components/dashboard/ExploreServicesPage";
import HelpCenterDashboardPage from "~/components/dashboard/HelpCenterDashboardPage";
import SwitchServicesPage from "~/components/dashboard/SwitchServicesPage";
import LogoutPage from "~/components/dashboard/LogoutPage";
import NotificationsPage from "~/components/dashboard/NotificationsPage";
import SessionTimer from "~/components/SessionTimer";
import { PROFESSIONAL_ROLE_SET } from "~/components/dashboard/RoleDashboardShared";

// Sidebar items that have real data implementations (wired to backend APIs)
// These show real components instead of DashboardDesignPreview mock
const BASE_REAL_PAGES = ["my dashboard", "my profile", "my portfolio", "verification", "settings"];
const COMMON_REAL_PAGES = [
  "credits",
  "explore nxtgauge",
  "help center",
  "switch services",
  "logout",
];
const COMPANY_REAL_PAGES = ["jobs", "applications", "shortlisted candidates"];
const CUSTOMER_REAL_PAGES = ["my requirements", "received responses", "shortlisted responses"];
const JOB_SEEKER_REAL_PAGES = ["jobs", "my applications", "saved jobs", "my portfolio"];
const PROFESSIONAL_REAL_PAGES = ["leads", "my responses"];
const COMMON_REAL_PAGES_EXTRA = ["notifications"];

type RoleKey =
  | "COMPANY"
  | "CUSTOMER"
  | "JOB_SEEKER"
  | "PHOTOGRAPHER"
  | "MAKEUP_ARTIST"
  | "TUTOR"
  | "DEVELOPER"
  | "VIDEO_EDITOR"
  | "UGC_CONTENT_CREATOR"
  | "GRAPHIC_DESIGNER"
  | "SOCIAL_MEDIA_MANAGER"
  | "FITNESS_TRAINER"
  | "CATERING_SERVICES";

type RuntimeBundle = {
  role: RoleKey;
  status: "ACTIVE" | "INACTIVE";
  sidebarItems: string[];
  tabs: string[];
  widgets: string[];
  fields: string[];
  verificationStatus?: string;
  userRoles?: string[];
  source: "dashboard-config";
  renderMode?: "preview";
  dashboardConfig?: Record<string, any>;
};

const API_GATEWAY = "/api/gateway";
const SERVER_API_BASE = (process.env.PUBLIC_API_URL || "http://localhost:8080/api").replace(
  /\/+$/,
  ""
);

const ROLE_OPTIONS: RoleKey[] = [
  "COMPANY",
  "CUSTOMER",
  "JOB_SEEKER",
  "PHOTOGRAPHER",
  "MAKEUP_ARTIST",
  "TUTOR",
  "DEVELOPER",
  "VIDEO_EDITOR",
  "UGC_CONTENT_CREATOR",
  "GRAPHIC_DESIGNER",
  "SOCIAL_MEDIA_MANAGER",
  "FITNESS_TRAINER",
  "CATERING_SERVICES",
];

const ROLE_BASED_SIDEBAR: Record<RoleKey, string[]> = {
  PHOTOGRAPHER: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  MAKEUP_ARTIST: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  TUTOR: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  DEVELOPER: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  VIDEO_EDITOR: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  UGC_CONTENT_CREATOR: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  GRAPHIC_DESIGNER: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  SOCIAL_MEDIA_MANAGER: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  FITNESS_TRAINER: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  CATERING_SERVICES: [
    "My Dashboard",
    "My Profile",
    "My Portfolio",
    "Leads",
    "My Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  COMPANY: [
    "My Dashboard",
    "My Profile",
    "Jobs",
    "Applications",
    "Shortlisted Candidates",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  CUSTOMER: [
    "My Dashboard",
    "My Profile",
    "My Requirements",
    "Received Responses",
    "Shortlisted Responses",
    "Credits",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
  JOB_SEEKER: [
    "My Dashboard",
    "My Profile",
    "Credits",
    "Jobs",
    "My Applications",
    "Saved Jobs",
    "Explore Nxtgauge",
    "Verification",
    "Help Center",
    "Notifications",
    "Settings",
    "Logout",
  ],
};

const ROLE_PREFIXES: Record<string, string> = {
  PHOTOGRAPHER: "photographers",
  MAKEUP_ARTIST: "makeup-artists",
  TUTOR: "tutors",
  DEVELOPER: "developers",
  VIDEO_EDITOR: "video-editors",
  GRAPHIC_DESIGNER: "graphic-designers",
  SOCIAL_MEDIA_MANAGER: "social-media-managers",
  FITNESS_TRAINER: "fitness-trainers",
  CATERING_SERVICES: "catering-services",
  UGC_CONTENT_CREATOR: "ugc-content-creators",
  CUSTOMER: "customers",
  COMPANY: "companies",
  JOB_SEEKER: "jobseeker",
};

function getNameFromStorage(): string {
  if (typeof window === "undefined") return "User";
  const keys = ["nxtgauge_signup_profile_v1", "nxtgauge_auth_user", "nxtgauge_user"];
  for (const key of keys) {
    try {
      const raw = window.localStorage.getItem(key) || window.sessionStorage.getItem(key);
      if (!raw) continue;
      const parsed = JSON.parse(raw);
      const name =
        parsed?.name || parsed?.first_name || parsed?.user?.name || parsed?.user?.first_name;
      if (name) return String(name);
    } catch {
      /* ignore */
    }
  }
  return "User";
}

function getEmailFromStorage(): string {
  if (typeof window === "undefined") return "";
  const keys = ["nxtgauge_signup_profile_v1", "nxtgauge_auth_user", "nxtgauge_user"];
  for (const key of keys) {
    try {
      const raw = window.localStorage.getItem(key) || window.sessionStorage.getItem(key);
      if (!raw) continue;
      const parsed = JSON.parse(raw);
      const email = String(parsed?.email || parsed?.user?.email || "")
        .trim()
        .toLowerCase();
      if (email) return email;
    } catch {
      // ignore invalid payload
    }
  }
  return "";
}

const EXPLORE_ROLES = [
  { key: "PHOTOGRAPHER", name: "Photographer" },
  { key: "MAKEUP_ARTIST", name: "Makeup Artist" },
  { key: "TUTOR", name: "Tutor" },
  { key: "DEVELOPER", name: "Developer" },
  { key: "VIDEO_EDITOR", name: "Video Editor" },
  { key: "UGC_CONTENT_CREATOR", name: "UGC Content Creator" },
  { key: "GRAPHIC_DESIGNER", name: "Graphic Designer" },
  { key: "SOCIAL_MEDIA_MANAGER", name: "Social Media Manager" },
  { key: "FITNESS_TRAINER", name: "Fitness Trainer" },
  { key: "CATERING_SERVICES", name: "Catering Services" },
];

function normalizeRole(value: string): RoleKey {
  const up = String(value || "")
    .trim()
    .toUpperCase()
    .replace(/\s+/g, "_");
  return (ROLE_OPTIONS.find((r) => r === up) || "JOB_SEEKER") as RoleKey;
}

function normalizeSidebarKey(value: string): string {
  const SIDEBAR_KEY_MAP: Record<string, string> = {
    dashboard: 'my dashboard',
    profile: 'my profile',
    portfolio: 'my portfolio',
    leads: 'leads',
    my_responses: 'my responses',
    responses: 'my responses',
    credits: 'credits',
    explore_nxtgauge: 'explore nxtgauge',
    explore: 'explore nxtgauge',
    verification: 'verification',
    verification_status: 'verification',
    help_center: 'help center',
    support: 'help center',
    help: 'help center',
    settings: 'settings',
    switch_services: 'switch services',
    switch_service: 'switch services',
    logout: 'logout',
    jobs: 'jobs',
    job_postings: 'jobs',
    applications: 'applications',
    my_applications: 'my applications',
    shortlisted_candidates: 'shortlisted candidates',
    my_requirements: 'my requirements',
    requirements: 'my requirements',
    received_responses: 'received responses',
    shortlisted_responses: 'shortlisted responses',
    saved_jobs: 'saved jobs',
  };
  const key = String(value || "").trim().toLowerCase();
  const mapped = SIDEBAR_KEY_MAP[key];
  if (mapped) return mapped;
  if (!key) return "my dashboard";
  if (key === "my dashboard" || key === "dashboard") return "my dashboard";
  if (key === "my profile" || key === "profile") return "my profile";
  if (key === "my portfolio" || key === "portfolio") return "my portfolio";
  if (key === "lead" || key === "leads") return "leads";
  if (key === "my response" || key === "responses" || key === "response") return "my responses";
  if (key === "credit" || key === "credits") return "credits";
  if (key.includes("explore")) return "explore nxtgauge";
  if (key === "verification" || key === "verify") return "verification";
  if (key === "help centre" || key === "support" || key === "help") return "help center";
  if (key === "setting" || key === "settings") return "settings";
  if (key === "switch service" || key === "switch role" || key === "switch roles" || key === "switch services") return "switch services";
  if (key === "logout" || key === "log out" || key === "sign out") return "logout";
  if (key === "job" || key === "jobs") return "jobs";
  if (key === "application" || key === "applications" || key === "job applications") return "applications";
  if (key === "shortlisted candidate" || key === "shortlisted candidates") return "shortlisted candidates";
  if (key === "requirement" || key === "requirements" || key === "my requirement" || key === "my requirements") return "my requirements";
  if (key === "received response" || key === "received responses") return "received responses";
  if (key === "shortlisted response" || key === "shortlisted responses") return "shortlisted responses";
  if (key === "my application" || key === "my applications") return "my applications";
  if (key === "saved job" || key === "saved jobs") return "saved jobs";
  return key;
}

function resolveRuntimeSidebarKeys(runtimeSidebar: string[]): string[] {
  if (!runtimeSidebar || runtimeSidebar.length === 0) return [];
  return runtimeSidebar.map(item => normalizeSidebarKey(item));
}

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

function firstNonJobSeekerRole(roleKeys: string[]): RoleKey | null {
  for (const roleKey of roleKeys) {
    const normalized = normalizeRole(roleKey);
    if (normalized !== "JOB_SEEKER") return normalized;
  }
  return null;
}

function getInitialRoleFromStorage(): RoleKey {
  if (typeof window === "undefined") return "JOB_SEEKER";
  const keys = ["nxtgauge_signup_profile_v1", "nxtgauge_auth_user", "nxtgauge_user"];
  for (const key of keys) {
    try {
      const raw = window.localStorage.getItem(key) || window.sessionStorage.getItem(key);
      if (!raw) continue;
      const parsed = JSON.parse(raw);
      const preferred = normalizeRole(String(parsed?.selectedProfessionalRole || ""));
      if (ROLE_OPTIONS.includes(preferred) && preferred !== "JOB_SEEKER") return preferred;
      const found = normalizeRole(
        String(
          parsed?.roleKey ||
            parsed?.role ||
            parsed?.active_role ||
            parsed?.user?.active_role ||
            parsed?.user?.roles?.[0] ||
            ""
        )
      );
      if (ROLE_OPTIONS.includes(found)) return found;
    } catch {
      // ignore invalid payload
    }
  }
  return "JOB_SEEKER";
}

function resolveRoleForDashboard(rawRole: string | null | undefined): RoleKey {
  const raw = String(rawRole || "").trim();
  if (raw) {
    return normalizeRole(raw);
  }
  const normalized = normalizeRole(raw);
  const preferred = getInitialRoleFromStorage();
  if (preferred !== "JOB_SEEKER") {
    return preferred;
  }
  return normalized;
}

async function fetchJson(path: string, includeAuth = false): Promise<any | null> {
  try {
    const isServer = typeof window === "undefined";
    const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
    const target = isServer ? `${SERVER_API_BASE}${path}` : `${API_GATEWAY}${cleanPath}`;
    const headers: Record<string, string> = {};
    if (includeAuth) {
      const token = typeof getToken === "function" ? getToken() : null;
      if (token) headers["Authorization"] = `Bearer ${token}`;
    }
    const res = await fetch(target, {
      headers,
      credentials: "include",
    });
    if (!res.ok) return null;
    return await res.json();
  } catch {
    return null;
  }
}

  async function loadRoleBundle(role: RoleKey): Promise<RuntimeBundle | null> {
    if (typeof window === "undefined") {
      return null;
    }
    const urlParams = new URLSearchParams(window.location.search);
    const urlRole = urlParams.get("role");
    const effectiveRole = urlRole ? normalizeRole(urlRole) : role;
    const apiPath = effectiveRole && effectiveRole !== "JOB_SEEKER"
      ? `/api/runtime-config?role=${encodeURIComponent(effectiveRole)}`
      : "/api/runtime-config";
    const runtime = await fetchJson(apiPath, true);
    if (!runtime) return null;
    const runtimeRole = normalizeRole(String(runtime?.role || runtime?.user?.active_role || role));
    const runtimeRenderMode = String(
      runtime?.dashboard_config?.render_mode ?? runtime?.dashboardConfig?.render_mode ?? runtime?.render_mode ?? ""
    ).toLowerCase();
    const runtimeSidebar = asStringArray(
      runtime?.dashboard_config?.sidebar_items ??
        runtime?.dashboard_config?.sidebarItems ??
        runtime?.dashboardConfig?.sidebar_items ??
        runtime?.dashboardConfig?.sidebarItems ??
        runtime?.sidebar_items ??
        runtime?.sidebarItems
    );
    const runtimeTabs = asStringArray(runtime?.dashboard_config?.tabs ?? runtime?.dashboardConfig?.tabs ?? runtime?.tabs);
    const runtimeWidgetsRaw = Array.isArray(runtime?.dashboard_config?.widgets)
      ? runtime.dashboard_config.widgets
      : Array.isArray(runtime?.dashboardConfig?.widgets)
        ? runtime.dashboardConfig.widgets
        : Array.isArray(runtime?.widgets)
          ? runtime.widgets
          : [];
    const runtimeWidgets = runtimeWidgetsRaw
      .map((item: any) =>
        String(typeof item === "string" ? item : item?.key || item?.id || "").trim()
      )
      .filter(Boolean);
    const runtimeFields = asStringArray(runtime?.dashboard_config?.fields ?? runtime?.dashboardConfig?.fields ?? runtime?.fields);

    return {
      role: runtimeRole,
      status: "ACTIVE",
      sidebarItems: runtimeSidebar,
      tabs: runtimeTabs,
      widgets: runtimeWidgets,
      fields: runtimeFields,
      verificationStatus:
        String(
          runtime?.verification_status || runtime?.user?.verification_status || ""
        ).toUpperCase() || undefined,
      source: "dashboard-config",
      renderMode: runtimeRenderMode === "preview" ? "preview" : undefined,
      dashboardConfig: runtime?.dashboard_config ?? runtime?.dashboardConfig ?? null,
    };
  }

function mergeSidebar(
  _role: RoleKey,
  runtimeSidebar: string[],
  userRoles: string[] = [],
  verificationStatus?: string,
  wizardEnabled = false
): string[] {
  const base = ROLE_BASED_SIDEBAR[_role] || [];
  const fromRuntime = runtimeSidebar.map((item) => String(item || "").trim()).filter(Boolean);
  const source = fromRuntime.length ? fromRuntime : base;
  const map = new Map<string, string>();
  for (const item of source) {
    const key = normalizeSidebarKey(item);
    if (!map.has(key)) map.set(key, item);
  }
  let merged = Array.from(map.values());

  // Runtime config remains source of truth; only hide switch-services when single-role.
  if (userRoles.length <= 1) {
    merged = merged.filter((item) => normalizeSidebarKey(item) !== "switch services");
  }

  const status = String(verificationStatus || "").toUpperCase();
  const approved = status === "APPROVED" || status === "COMPLETED";
  if (!approved && status) {
    // Once a role's verification wizard is enabled (admin-configurable, see
    // OnboardingSchemaEditor), My Profile / My Portfolio move inside the
    // wizard itself and stay hidden from the sidebar until approved — the
    // wizard is the only way to complete them pre-approval. Roles that
    // haven't been rolled out to the wizard yet keep the old behavior
    // (profile/portfolio remain directly accessible) so they aren't left
    // with no way to fill in their profile at all.
    const restricted = new Set([
      "help center",
      "settings",
      "verification",
      ...(wizardEnabled ? [] : ["my profile"]),
      ...(!wizardEnabled && (PROFESSIONAL_ROLE_SET.has(_role) || _role === "JOB_SEEKER")
        ? ["my portfolio", "credits"]
        : []),
    ]);
    merged = merged.filter((item) => restricted.has(item.trim().toLowerCase()));
  }
  return merged;
}

// FIX_APPLIED_V13_ROLE_FROM_URL_PROTECTION
export default function RuntimeDashboardPage() {
  const navigate = useNavigate();
  const location = useLocation();
  const auth = useAuth();
  const [hydrated, setHydrated] = createSignal(false);
  const [role, setRole] = createSignal<RoleKey>("JOB_SEEKER");
  const [activeSidebar, setActiveSidebar] = createSignal("My Dashboard");
  const [activeTab, setActiveTab] = createSignal("overview");
  const [userName, setUserName] = createSignal("User");
  const [userId, setUserId] = createSignal("");
  const [urlRoleLocked, setUrlRoleLocked] = createSignal(false);
  const [roleReconcileAttempted, setRoleReconcileAttempted] = createSignal(false);
  const [verificationStatusOverride, setVerificationStatusOverride] = createSignal<string | undefined>(undefined);

  const isAdmin = createMemo(() => {
    const user = auth.user();
    return user?.roles?.some(r => r === 'ADMIN' || r === 'SUPER_ADMIN') ?? false;
  });

  onMount(() => {
    setHydrated(true);
    const urlParams = new URLSearchParams(window.location.search);
    const roleParam = urlParams.get("role");
    const navParam = urlParams.get("nav");
    if (navParam) {
      // Allow deep-linking into a sidebar page via ?nav=notifications etc.
      const matched = Object.values(ROLE_BASED_SIDEBAR)
        .flat()
        .find((item) => normalizeSidebarKey(item) === navParam.toLowerCase());
      if (matched) setActiveSidebar(matched);
    }
    if (roleParam) {
      setUrlRoleLocked(true);
      setRole(normalizeRole(roleParam));
    } else {
      const storedRole = getInitialRoleFromStorage();
      setRole(storedRole);
    }
    setUserName(getNameFromStorage());
    if (auth.user()) {
      const u = auth.user()!;
      if (u.full_name) setUserName(u.full_name);
      if (u.id) setUserId(u.id);
    }
  });

  // FE-003: Keep role in sync with browser back/forward navigation.
  // onMount() fires only once on initial mount; when the user presses Back the
  // SolidJS router updates location.search (popstate) without remounting the
  // component, so the role signal would stay at whatever it was last set to
  // instead of reflecting the ?role= param that the back-navigation restored.
  // This effect watches location.search reactively and syncs the role signal
  // whenever the URL changes after the initial hydration.
  createEffect(() => {
    if (!hydrated()) return; // skip pre-hydration run; onMount already handles the first read
    const urlParams = new URLSearchParams(location.search);
    const roleParam = urlParams.get("role");
    if (roleParam) {
      const newRole = normalizeRole(roleParam);
      if (newRole !== role()) {
        setUrlRoleLocked(true);
        setRole(newRole);
        // Reset sidebar and override so the new role's UI is shown cleanly
        setActiveSidebar("My Dashboard");
        setVerificationStatusOverride(undefined);
      }
    }
  });

  createEffect(() => {
    const u = auth.user();
    // If role was explicitly set from URL, never let auth.user() override it
    if (u && !urlRoleLocked()) {
      if (u.full_name && userName() === "User") setUserName(u.full_name);
      if (u.id && !userId()) setUserId(u.id);
      if (u.active_role) {
        const authRole = resolveRoleForDashboard(u.active_role);
        const preferredRole = getInitialRoleFromStorage();
        if (authRole === "JOB_SEEKER" && preferredRole !== "JOB_SEEKER") {
          setRole(preferredRole);
        } else {
          setRole(authRole);
        }
      }
    }
  });

  createEffect(() => {
    if (urlRoleLocked() || roleReconcileAttempted()) return;
    if (role() !== "JOB_SEEKER") {
      setRoleReconcileAttempted(true);
      return;
    }

    setRoleReconcileAttempted(true);
    void (async () => {
      try {
        const authEmail = String(auth.user()?.email || "")
          .trim()
          .toLowerCase();
        const email = authEmail || getEmailFromStorage();
        if (!email) return;

        const checkRes = await fetch("/api/auth/check-email", {
          method: "POST",
          headers: { "Content-Type": "application/json", Accept: "application/json" },
          credentials: "include",
          body: JSON.stringify({ email }),
        });
        const checkPayload = await checkRes.json().catch(() => ({}));
        if (!checkRes.ok || !checkPayload?.exists) return;

        const discoveredRoles = asStringArray(checkPayload?.roles).map((item) =>
          normalizeRole(String(item))
        );
        const discoveredActive = normalizeRole(
          String(checkPayload?.active_role || checkPayload?.role || "")
        );
        const targetRole =
          discoveredActive !== "JOB_SEEKER"
            ? discoveredActive
            : firstNonJobSeekerRole(discoveredRoles);
        if (!targetRole || targetRole === "JOB_SEEKER") return;

        const token = getToken();
        if (token) {
          const switchRes = await fetch("/api/auth/switch-role", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              Accept: "application/json",
              Authorization: `Bearer ${token}`,
            },
            credentials: "include",
            body: JSON.stringify({ role_key: targetRole }),
          });
          const switchPayload = await switchRes.json().catch(() => ({}));
          const switchedToken = String(switchPayload?.access_token || "").trim();
          if (switchRes.ok && switchedToken && typeof window !== "undefined") {
            window.sessionStorage.setItem("nxtgauge_access_token", switchedToken);
            window.sessionStorage.setItem("nxtgauge_frontend_access_token", switchedToken);
          }
        }

        if (typeof window !== "undefined") {
          const storageKeys = ["nxtgauge_signup_profile_v1", "nxtgauge_auth_user", "nxtgauge_user"];
          for (const key of storageKeys) {
            const raw = window.localStorage.getItem(key);
            if (!raw) continue;
            try {
              const parsed = JSON.parse(raw);
              parsed.active_role = targetRole;
              parsed.selectedProfessionalRole = targetRole;
              parsed.role = String(targetRole).toLowerCase();
              parsed.roleKey = String(targetRole).toLowerCase();
              window.localStorage.setItem(key, JSON.stringify(parsed));
            } catch {
              // ignore malformed storage payloads
            }
          }
        }

        setRole(targetRole);
        navigate(`/dashboard?role=${encodeURIComponent(targetRole)}`, { replace: true });
      } catch {
        // best-effort reconciliation only
      }
    })();
  });

  const [bundle] = createResource(() => role(), loadRoleBundle);
  const [wizardEnabledForRole] = createResource(
    () => role(),
    async (r) => Boolean((await fetchOnboardingSchemaForRole(r))?.enableWizardFlow)
  );
  // Pre-fetch verification status alongside the bundle so the sidebar filter
  // is correct from the first render.  Without this, "My Profile" briefly
  // appears in the sidebar for wizard-enabled roles, the user can click it,
  // and then gets immediately kicked back to "Verification" when the status
  // arrives and the sidebar recalculates — FE-001.
  const [earlyVerificationStatus] = createResource(
    () => role(),
    async (r) => {
      const data = await fetchJson(`/api/me/verification-status?roleKey=${encodeURIComponent(r)}`, true);
      if (!data) return undefined;
      return String(data.status ?? "").toUpperCase() || undefined;
    }
  );
  const activeSidebarKey = createMemo(() => normalizeSidebarKey(activeSidebar()));

  createEffect(() => {
    role();
    setVerificationStatusOverride(undefined);
  });

  const effectiveVerificationStatus = createMemo(
    // Priority: explicit override (from ProfilePage callback) > bundle field >
    // eagerly-fetched pre-render status (FE-001 fix).
    () => verificationStatusOverride() ?? bundle()?.verificationStatus ?? earlyVerificationStatus()
  );

  const sidebarItems = createMemo(() =>
    mergeSidebar(
      role(),
      bundle()?.sidebarItems || [],
      bundle()?.userRoles || [],
      effectiveVerificationStatus(),
      wizardEnabledForRole() ?? false
    )
  );

  createEffect(() => {
    const runtimeRole = bundle()?.role;
    if (runtimeRole && runtimeRole !== role() && !urlRoleLocked()) {
      setRole(runtimeRole);
    }
  });

  createEffect(() => {
    const first = sidebarItems()[0] || "";
    const current = activeSidebar();
    const currentKey = current.toLowerCase();
    const isDashboard = currentKey === "my dashboard";
    const exists = sidebarItems().some((item) => item.toLowerCase() === currentKey);
    if (!exists && !isDashboard && first) setActiveSidebar(first);
  });

  const tabs = createMemo(() => {
    const fromRuntime = bundle()?.tabs || [];
    return fromRuntime.length > 0 ? fromRuntime : ["overview"];
  });

  createEffect(() => {
    role();
    const firstTab = tabs()[0] || "overview";
    setActiveTab((prev) => (prev ? prev : firstTab));
  });

  // Block the dashboard shell until all three sidebar-determining resources
  // have resolved.  This ensures the sidebar filter is correct on first
  // render and "My Profile" is never shown when it would immediately redirect
  // (FE-001 — company wizard mode + NOT_SUBMITTED).
  const loading = createMemo(
    () => !hydrated() || bundle.loading || earlyVerificationStatus.loading || wizardEnabledForRole.loading
  );
  const ready = createMemo(() => !loading());

  const liveData = createMemo(() => {
    const prefix = ROLE_PREFIXES[role()];
    if (!prefix) return undefined;
    return { userName: userName(), userId: userId(), rolePrefix: prefix };
  });

  const forcePreviewFromConfig = createMemo(() => bundle()?.renderMode === "preview");

  const isRealPage = createMemo(() => {
    if (forcePreviewFromConfig()) return false;
    const key = activeSidebarKey();
    if (key === "my dashboard") {
      if (PROFESSIONAL_ROLE_SET.has(role())) return true;
      if (role() === "COMPANY") return true;
      if (role() === "JOB_SEEKER") return true;
      if (role() === "CUSTOMER") return true;
      if ((bundle()?.widgets?.length ?? 0) > 0) return false;
    }
    if (BASE_REAL_PAGES.includes(key)) return true;
    if (COMMON_REAL_PAGES.includes(key)) return true;
    if (COMMON_REAL_PAGES_EXTRA.includes(key)) return true;
    if (role() === "COMPANY" && COMPANY_REAL_PAGES.includes(key)) return true;
    if (role() === "CUSTOMER" && CUSTOMER_REAL_PAGES.includes(key)) return true;
    if (role() === "JOB_SEEKER" && JOB_SEEKER_REAL_PAGES.includes(key)) return true;
    if (PROFESSIONAL_ROLE_SET.has(role()) && PROFESSIONAL_REAL_PAGES.includes(key)) return true;
    return false;
  });

  return (
    <RequireAuth>
      <SessionTimer />
      <main style={{ "min-height": "100vh", background: "#F3F4F6" }}>
        <Show when={loading()}>
          <div style={cardStyle}>Loading dashboard…</div>
        </Show>

        <Show when={ready()}>
          {/* ── Real pages: DashboardShell + actual components ── */}
          <Show when={isRealPage()}>
            <DashboardShell
              sidebarItems={sidebarItems()}
              activeSidebar={activeSidebar()}
              onSidebarSelect={setActiveSidebar}
              roleKey={role()}
              userName={userName()}
              isAdmin={isAdmin()}
              verificationApproved={["APPROVED", "COMPLETED"].includes(String(effectiveVerificationStatus() || '').toUpperCase())}
            >
              <Switch>
                <Match when={activeSidebarKey() === "my dashboard"}>
                  <MyDashboardPage
                    roleKey={role()}
                    userName={userName()}
                    widgetKeys={bundle()?.widgets || []}
                    verificationStatus={effectiveVerificationStatus()}
                    onNavigate={setActiveSidebar}
                  />
                </Match>
                <Match when={activeSidebarKey() === "my profile"}>
                  <ProfilePage
                    roleKey={role()}
                    runtimeFields={bundle()?.fields || []}
                    onVerificationStatusChange={(status) => setVerificationStatusOverride(String(status || "").toUpperCase())}
                    onNavigate={setActiveSidebar}
                  />
                </Match>
                <Match when={activeSidebarKey() === "my portfolio"}>
                  <PortfolioPage
                    roleKey={role()}
                    runtimeTabs={bundle()?.tabs || []}
                    runtimeFields={bundle()?.fields || []}
                  />
                </Match>
                <Match when={activeSidebarKey() === "verification"}>
                  <VerificationStatusPage
                    roleKey={role()}
                    onNavigate={setActiveSidebar}
                    onVerificationStatusChange={(status) => setVerificationStatusOverride(String(status || "").toUpperCase())}
                    runtimeFields={bundle()?.fields || []}
                    runtimeTabs={bundle()?.tabs || []}
                  />
                </Match>
                <Match when={activeSidebarKey() === "settings"}>
                  <SettingsPage roleKey={role()} />
                </Match>
                <Match when={activeSidebarKey() === "notifications"}>
                  <NotificationsPage />
                </Match>
                <Match when={activeSidebarKey() === "credits"}>
                  <CreditsPage roleKey={role()} dashboardConfig={bundle()?.dashboardConfig} />
                </Match>
                <Match when={activeSidebarKey() === "explore nxtgauge"}>
                  <ExploreServicesPage />
                </Match>
                <Match when={activeSidebarKey() === "help center"}>
                  <HelpCenterDashboardPage roleKey={role()} />
                </Match>
                <Match when={activeSidebarKey() === "switch services"}>
                  <SwitchServicesPage />
                </Match>
                <Match when={activeSidebarKey() === "logout"}>
                  <LogoutPage />
                </Match>
                <Match when={role() === "COMPANY" && activeSidebarKey() === "jobs"}>
                  <CompanyJobsPage />
                </Match>
                <Match
                  when={role() === "COMPANY" && activeSidebarKey() === "applications"}
                >
                  <CompanyApplicationsPage />
                </Match>
                <Match
                  when={
                    role() === "COMPANY" &&
                    activeSidebarKey() === "shortlisted candidates"
                  }
                >
                  <CompanyShortlistedCandidatesPage />
                </Match>
                <Match
                  when={
                    role() === "CUSTOMER" && activeSidebarKey() === "my requirements"
                  }
                >
                  <CustomerRequirementsPage />
                </Match>
                <Match
                  when={
                    role() === "CUSTOMER" && activeSidebarKey() === "received responses"
                  }
                >
                  <CustomerResponsesPage mode="received" />
                </Match>
                <Match
                  when={
                    role() === "CUSTOMER" &&
                    activeSidebarKey() === "shortlisted responses"
                  }
                >
                  <CustomerResponsesPage mode="shortlisted" />
                </Match>
                <Match
                  when={
                    role() === "JOB_SEEKER" && activeSidebarKey() === "my applications"
                  }
                >
                  <JobSeekerApplicationsPage />
                </Match>
                <Match when={role() === "JOB_SEEKER" && activeSidebarKey() === "jobs"}>
                  <JobSeekerJobsPage />
                </Match>
                <Match
                  when={role() === "JOB_SEEKER" && activeSidebarKey() === "saved jobs"}
                >
                  <JobSeekerSavedJobsPage />
                </Match>
                <Match
                  when={
                    PROFESSIONAL_ROLE_SET.has(role()) && activeSidebarKey() === "leads"
                  }
                >
                  <ProfessionalLeadsPage roleKey={role()} />
                </Match>
                <Match
                  when={
                    PROFESSIONAL_ROLE_SET.has(role()) &&
                    activeSidebarKey() === "my responses"
                  }
                >
                  <ProfessionalResponsesPage roleKey={role()} />
                </Match>
              </Switch>
            </DashboardShell>
          </Show>

          {/* ── All other views: DashboardDesignPreview mock ── */}
          <Show when={!isRealPage()}>
            <DashboardDesignPreview
              status={bundle()?.status ?? "ACTIVE"}
              sidebarItems={sidebarItems()}
              activeSidebar={activeSidebar()}
              onSidebarSelect={setActiveSidebar}
              tabs={tabs()}
              activeTab={activeTab()}
              onTabSelect={setActiveTab}
              widgets={bundle()?.widgets || []}
              fields={bundle()?.fields || []}
              roleKey={role()}
              exploreRoles={EXPLORE_ROLES}
              hidePreviewHeader
              liveData={liveData()}
              mode={undefined}
            />
          </Show>
        </Show>
      </main>
    </RequireAuth>
  );
}

const cardStyle = {
  border: "1px solid #E5E7EB",
  "border-radius": "12px",
  padding: "16px",
  background: "#fff",
  color: "#111827",
} as const;
