import React, { useState, useEffect, useMemo, useRef, useCallback } from "react";
import { useNavigate } from "react-router-dom";
import axiosInstance from "../../../utils/axiosConfig";
import {
  DASHBOARD_STATS_URL,
  DASHBOARD_HARM_DISTRIBUTIONS_URL,
  DASHBOARD_OBSERVATIONS_OPEN_CLOSED_URL,
  DASHBOARD_RPN_AUDIT_COUNTS_URL,
  DASHBOARD_SIO_OIO_CA_STATS_URL,
} from "../../../utils/config";
import { getDisplayNameFromToken } from "../../../utils/authUtils";
import { useTheme } from "../../../contexts/ThemeContext";
import {
  STORAGE_KEY,
  LAYOUT_STORAGE_KEY,
  WIDGET_OPTIONS,
  loadSelectedWidgets,
  saveSelectedWidgets,
  loadLayout,
  saveLayout,
  getDefaultGridSize,
  getWidgetGridLimits,
  resolveOverlaps,
  GRID_COLS,
  GRID_ROW_HEIGHT_PX,
  GRID_COL_WIDTH_PX,
} from "../../../utils/personalizedDashboardUtils";
import StatCard from "../dashboard/common/StatCard";
import AnswersTrendChart from "../dashboard/pages/AnswersTrendChart";
import SeverityOfHarmPieChart from "../dashboard/pages/SeverityOfHarmPieChart";
import LikelihoodOfHarmPieChart from "../dashboard/pages/LikelihoodOfHarmPieChart";
import ObservationsOpenClosedBarChart from "../dashboard/pages/ObservationsOpenClosedBarChart";
import RpnAuditBarChart from "../dashboard/pages/RpnAuditBarChart";
import SioOioCaCharts from "../dashboard/pages/SioOioCaCharts";
import TopSitesList from "../dashboard/pages/TopSitesList";
import RecentActivities from "../dashboard/pages/RecentActivities";
import RARecentAssessments from "../dashboard/pages/RARecentAssessments";
import RAStatusBreakdown from "../dashboard/pages/RAStatusBreakdown";
import RADashboardTrendChart from "../dashboard/pages/RADashboardTrendChart";
import RALocationDrilldownPie from "../dashboard/pages/RALocationDrilldownPie";
import { buildTrendSeriesData, TREND_GRANULARITY } from "../../../utils/raDashboardTrendSeries";
import { buildCategoryMapsFromStatuses, categorizeExecutorRow } from "../../../utils/raExecutorAssignmentCategories";
import "../dashboard/styles/Dashboard.css";
import "../dashboard/styles/AddToPersonalizedButton.css";
import "./styles/MasterDashboard.css";
import "./styles/PersonalizedDashboard.css";
import "./styles/MasterDashboardTheme.css";

// Keep project definitions in sync with MasterDashboard sidebar
const PROJECTS = [
  {
    id: "sat",
    name: "SAT - Safety Audit Observation",
    description:
      "Site Audit & Ticketing – Manage audits, forms, tickets, and compliance in one place.",
    available: true,
    icon: "clipboard",
  },
  {
    id: "project-2",
    name: "Asset Management",
    description: "Coming soon.",
    available: false,
    icon: "box",
  },
  {
    id: "project-3",
    name: "Permit to Work (PTW)",
    description: "Coming soon.",
    available: false,
    icon: "box",
  },
  {
    id: "project-4",
    name: "Action Item Management (CAPA)",
    description: "Coming soon.",
    available: false,
    icon: "box",
  },
  {
    id: "project-5",
    name: "SWI/SOP Management",
    description: "Coming soon.",
    available: false,
    icon: "box",
  },
  {
    id: "project-6",
    name: "HSE - Learning Management System",
    description: "Coming soon.",
    available: false,
    icon: "box",
  },
  {
    id: "risk-assessment",
    name: "Risk Assessment",
    description: "Comprehensive risk management – Analyze, evaluate, and mitigate potential hazards efficiently.",
    available: true,
    icon: "clipboard",
  },
];

// Map each project ID to the route for its main application entry point.
// Must mirror MasterDashboard.getProjectRoute so the menu feels consistent.
const getProjectRoute = (projectId) => {
  if (projectId === "sat") return "/dashboard";
  if (projectId === "risk-assessment") return "http://localhost:5173";
  // TODO: add real routes for other applications when they are implemented
  return null; // means "coming soon"
};

const defaultAnswersTrend = () =>
  Array.from({ length: 6 }, (_, i) => ({
    month: ["Jan", "Feb", "Mar", "Apr", "May", "Jun"][i],
    answers: 0,
    submissions: 0,
    audits: 0,
  }));

const defaultTopSites = () => [];
const defaultRecentActivities = () => [];

const statIcons = {
  audits: (
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
      <circle cx="11" cy="11" r="7" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      <path d="m20 20-4.35-4.35" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  ),
  compliance: (
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path d="M20 6L9 17l-5-5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  ),
  findings: (
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      <line x1="12" y1="9" x2="12" y2="13" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      <line x1="12" y1="17" x2="12.01" y2="17" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  ),
  answers: (
    <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      <path d="M14 2v6h6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      <path d="M16 13H8" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      <path d="M16 17H8" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
      <path d="M10 9H8" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    </svg>
  ),
};

const sioPctIcon = (
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M12 2v4m0 12v4M2 12h4m12 0h4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    <circle cx="12" cy="12" r="4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
  </svg>
);
const oioPctIcon = (
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
    <circle cx="12" cy="12" r="3" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
    <path d="M12 2v2m0 16v2M2 12h2m16 0h2" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
  </svg>
);
const sioPaPctIcon = (
  <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
    <path d="M20 6L9 17l-5-5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
  </svg>
);

function PersonalizedDashboard() {
  const navigate = useNavigate();
  const displayName = getDisplayNameFromToken();
  const { theme, toggleTheme } = useTheme();
  const [loggingOut, setLoggingOut] = useState(false);
  const [sidebarOpen, setSidebarOpen] = useState(false);
  const [selectedWidgets, setSelectedWidgets] = useState(loadSelectedWidgets);
  const [addChartOpen, setAddChartOpen] = useState(false);
  const [dashboardData, setDashboardData] = useState(null);
  const [severityOfHarmData, setSeverityOfHarmData] = useState([]);
  const [likelihoodOfHarmData, setLikelihoodOfHarmData] = useState([]);
  const [observationsOpenClosedData, setObservationsOpenClosedData] = useState([]);
  const [rpnAuditCountsData, setRpnAuditCountsData] = useState([]);
  const [sioOioCaData, setSioOioCaData] = useState(null);
  const [riskAssessments, setRiskAssessments] = useState([]);
  const [raStatuses, setRaStatuses] = useState([]);
  const [raCountries, setRaCountries] = useState([]);
  const [raTrendGranularity, setRaTrendGranularity] = useState(TREND_GRANULARITY.MONTH);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  const [layout, setLayout] = useState(() => loadLayout(loadSelectedWidgets()));
  const [resizing, setResizing] = useState({ id: null, startX: 0, startY: 0, startW: 0, startH: 0 });
  const [draggedWidgetId, setDraggedWidgetId] = useState(null);
  const [dragOverWidgetId, setDragOverWidgetId] = useState(null);
  const addChartWrapRef = useRef(null);
  const gridRef = useRef(null);

  useEffect(() => {
    const handleEscape = (e) => {
      if (e.key === "Escape") {
        setSidebarOpen(false);
        setAddChartOpen(false);
      }
    };
    if (sidebarOpen || addChartOpen) {
      document.addEventListener("keydown", handleEscape);
      document.body.style.overflow = sidebarOpen ? "hidden" : "";
    }
    return () => {
      document.removeEventListener("keydown", handleEscape);
      document.body.style.overflow = "";
    };
  }, [sidebarOpen, addChartOpen]);

  useEffect(() => {
    if (!addChartOpen) return;
    const handleClickOutside = (e) => {
      if (addChartWrapRef.current && !addChartWrapRef.current.contains(e.target)) {
        setAddChartOpen(false);
      }
    };
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, [addChartOpen]);


  useEffect(() => {
    let cancelled = false;
    const fetchDashboard = async () => {
      setLoading(true);
      setError(null);
      try {
        // Each call is isolated — SAT/ORAC may reject Master login JWTs; never block the page.
        const empty = (data) => ({ data });
        const [statsRes, harmRes, obsRes, rpnCountsRes, sioOioCaRes, raRes, raStatusRes, raCountriesRes] =
          await Promise.all([
            axiosInstance.get(DASHBOARD_STATS_URL).catch(() => empty({ data: null })),
            axiosInstance.get(DASHBOARD_HARM_DISTRIBUTIONS_URL).catch(() => empty({ data: {} })),
            axiosInstance.get(DASHBOARD_OBSERVATIONS_OPEN_CLOSED_URL).catch(() => empty({ data: [] })),
            axiosInstance.get(DASHBOARD_RPN_AUDIT_COUNTS_URL).catch(() => empty({ data: [] })),
            axiosInstance.get(DASHBOARD_SIO_OIO_CA_STATS_URL).catch(() => empty({})),
            axiosInstance.get("/api/orac/orac_assessments/").catch(() => empty([])),
            axiosInstance.get("/api/orac/orac_assessments_status/").catch(() => empty([])),
            axiosInstance.get("/api/orac/lookup/countries").catch(() => empty([])),
          ]);
        if (cancelled) return;
        const data = statsRes.data?.data;
        if (data) setDashboardData(data);
        const harmData = harmRes.data?.data;
        if (harmData) {
          setSeverityOfHarmData(harmData.severityOfHarm || []);
          setLikelihoodOfHarmData(harmData.likelihoodOfHarm || []);
        }
        const obsData = obsRes.data?.data;
        if (Array.isArray(obsData)) setObservationsOpenClosedData(obsData);
        const rpnCounts = rpnCountsRes.data?.data;
        if (Array.isArray(rpnCounts)) setRpnAuditCountsData(rpnCounts);
        const sioOioCa = sioOioCaRes.data?.data ?? sioOioCaRes.data;
        if (sioOioCa && typeof sioOioCa === "object") setSioOioCaData(sioOioCa);
        const raData = raRes.data;
        if (Array.isArray(raData)) setRiskAssessments(raData);
        const rawStatuses = raStatusRes.data;
        const statusList = Array.isArray(rawStatuses) ? rawStatuses : rawStatuses?.data;
        if (Array.isArray(statusList)) setRaStatuses(statusList);
        const rawCountries = raCountriesRes.data;
        const countryList = Array.isArray(rawCountries) ? rawCountries : rawCountries?.data;
        if (Array.isArray(countryList)) setRaCountries(countryList);
      } catch (err) {
        if (!cancelled) {
          // Non-fatal: still show the personalised shell so navigation is usable.
          setError(err.response?.data?.message || err.message || "Failed to load dashboard");
          setDashboardData(null);
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    };
    fetchDashboard();
    return () => { cancelled = true; };
  }, []);

  const answersTrendData = useMemo(() => {
    if (!dashboardData?.answersTrend?.length) return defaultAnswersTrend();
    return dashboardData.answersTrend;
  }, [dashboardData]);

  const topSitesByCompliance = useMemo(() => {
    if (!dashboardData?.topSites?.length) return defaultTopSites();
    return dashboardData.topSites;
  }, [dashboardData]);

  const recentActivities = useMemo(() => {
    if (!dashboardData?.recentActivities?.length) return defaultRecentActivities();
    return dashboardData.recentActivities;
  }, [dashboardData]);

  const stats = useMemo(() => {
    const s = dashboardData?.stats;
    return [
      { label: "Total Audits", value: s ? String(s.totalAudits ?? 0) : "0", change: "+0", trend: "up", icon: statIcons.audits, description: "All audits created in the system (planned and in progress)." },
      { label: "Audit Completion Rate", value: s ? `${s.complianceRate ?? 0}%` : "0%", change: "+0%", trend: "up", icon: statIcons.compliance, description: "Percentage of audits that are closed based on audit status (audit completion rate). Click to view audits status.", to: "/audit-status" },
      { label: "Critical Findings", value: s ? String(s.auditsWithRpn32To128 ?? 0) : "0", subtitle: s ? `${s.auditsWithRpn32To128 ?? 0} audits with RPN 32–128` : "0 audits with RPN 32–128", change: "0", trend: "down", icon: statIcons.findings, description: "Audits with RPN 32–128. Click to view list.", to: "/critical-findings" },
      { label: "Total Users", value: s ? String(s.totalUsers ?? 0).replace(/\B(?=(\d{3})+(?!\d))/g, ",") : "0", subtitle: s ? `${s.totalUsers ?? 0} user${(s.totalUsers ?? 0) !== 1 ? "s" : ""} in system` : "0 users in system", change: "+0", trend: "up", icon: statIcons.answers, description: "Total users in the system. Click to view users list.", to: "/users" },
    ];
  }, [dashboardData?.stats]);

  const { raCompleted, raInProgress, raNotStarted, raTotal, raStatusGroups, raRecent } = useMemo(() => {
    const getLabel = (a) => a.assessment_status_name || `Status ${a.assessment_status_id}`;
    const completed = riskAssessments.filter((a) => getLabel(a).toLowerCase().includes('complete'));
    const inProgress = riskAssessments.filter((a) => {
      const l = getLabel(a).toLowerCase();
      return l.includes('progress') || l.includes('ongoing');
    });
    const notStarted = riskAssessments.filter((a) => {
      const l = getLabel(a).toLowerCase();
      return l.includes('not started') || a.assessment_status_id === 1;
    });

    const recent = riskAssessments.slice(0, 5);

    const statusGroups = {};
    riskAssessments.forEach((a) => {
      const key = a.assessment_status_id;
      if (!statusGroups[key]) {
        statusGroups[key] = { name: getLabel(a), count: 0 };
      }
      statusGroups[key].count++;
    });

    return {
      raCompleted: completed.length,
      raInProgress: inProgress.length,
      raNotStarted: notStarted.length,
      raTotal: riskAssessments.length,
      raStatusGroups: statusGroups,
      raRecent: recent,
    };
  }, [riskAssessments]);

  const raStatsWidgets = useMemo(() => {
    return {
      raStatsCompleted: { label: "RA: Completed", value: String(raCompleted), icon: statIcons.compliance, description: "All controls verified" },
      raStatsInProgress: { label: "RA: In Progress", value: String(raInProgress), icon: statIcons.audits, description: "With owners and reviewers" },
      raStatsNotStarted: { label: "RA: Not Started", value: String(raNotStarted), icon: statIcons.findings, description: "Ready to initiate" },
      raStatsTotal: { label: "RA: Total", value: String(raTotal), icon: statIcons.answers, description: "All assessments" },
    };
  }, [raCompleted, raInProgress, raNotStarted, raTotal]);

  const { executorMap } = useMemo(() => buildCategoryMapsFromStatuses(raStatuses), [raStatuses]);

  const assignedForTrend = useMemo(
    () => riskAssessments.filter((a) => a.executor_id || a.verifier_id),
    [riskAssessments]
  );

  const adminTrendData = useMemo(
    () =>
      buildTrendSeriesData(
        assignedForTrend,
        categorizeExecutorRow,
        executorMap,
        raTrendGranularity
      ),
    [assignedForTrend, executorMap, raTrendGranularity]
  );

  const sioOioCaPercentageStats = useMemo(() => {
    const d = sioOioCaData;
    const sioPct = d?.sioPercentage ?? 0;
    const oioPct = d?.oioPercentage ?? 0;
    const sioPaPct = d?.sioPaPercentage ?? 0;
    return [
      { label: "SIO %", value: `${sioPct.toFixed(1)}%`, icon: sioPctIcon, description: "Share of observations that are SIO (Significant Impact Observation) out of all SIO, OIO and CA." },
      { label: "OIO %", value: `${oioPct.toFixed(1)}%`, icon: oioPctIcon, description: "Share of observations that are OIO (Other Impact Observation) out of all SIO, OIO and CA." },
      { label: "SIO PA %", value: `${sioPaPct.toFixed(1)}%`, icon: sioPaPctIcon, description: "Percentage of SIO audits that are closed (SIO PA = SIO Preventive Action closed)." },
    ];
  }, [sioOioCaData]);

  const getLayoutGrid = (id) => {
    const g = layout[id];
    const limits = getWidgetGridLimits(id);
    const { w: defaultW, h: defaultH } = getDefaultGridSize(id);
    if (g && Number.isFinite(g.x) && Number.isFinite(g.y) && Number.isFinite(g.w) && Number.isFinite(g.h)) {
      return {
        x: g.x,
        y: g.y,
        w: Math.min(limits.maxW, Math.max(limits.minW, g.w)),
        h: Math.min(limits.maxH, Math.max(limits.minH, g.h)),
      };
    }
    return { x: 0, y: 0, w: defaultW, h: defaultH };
  };

  const addWidget = useCallback((id) => {
    if (!id || selectedWidgets.includes(id)) return;
    // Only Master-registered widgets can be rendered here.
    if (!WIDGET_OPTIONS.some((w) => w.id === id)) return;
    const next = [...selectedWidgets, id];
    setSelectedWidgets(next);
    saveSelectedWidgets(next);
    const newLayout = loadLayout(next);
    setLayout(newLayout);
    saveLayout(newLayout);
    setAddChartOpen(false);
  }, [selectedWidgets]);

  const removeWidget = (id) => {
    const next = selectedWidgets.filter((w) => w !== id);
    setSelectedWidgets(next);
    saveSelectedWidgets(next);
    setLayout((prev) => {
      const nextLayout = { ...prev };
      delete nextLayout[id];
      saveLayout(nextLayout);
      return nextLayout;
    });
  };

  const startResize = (id, e) => {
    e.preventDefault();
    e.stopPropagation();
    const grid = getLayoutGrid(id);
    setResizing({ id, startX: e.clientX, startY: e.clientY, startW: grid.w, startH: grid.h });
  };

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const widgetToAdd = params.get("addWidget");
    if (widgetToAdd && !selectedWidgets.includes(widgetToAdd)) {
      addWidget(widgetToAdd);
      window.history.replaceState({}, document.title, window.location.pathname);
    }
  }, [selectedWidgets, addWidget]);

  const handleDragStart = (e, id) => {
    e.dataTransfer.setData("widgetId", id);
    e.dataTransfer.effectAllowed = "move";
    setDraggedWidgetId(id);
  };

  const handleDragEnd = () => {
    setDraggedWidgetId(null);
    setDragOverWidgetId(null);
  };

  const handleDragOver = (e, targetId) => {
    e.preventDefault();
    e.dataTransfer.dropEffect = "move";
    if (draggedWidgetId && draggedWidgetId !== targetId) setDragOverWidgetId(targetId);
  };

  const handleDragLeave = () => {
    setDragOverWidgetId(null);
  };

  const handleDrop = (e, targetId) => {
    e.preventDefault();
    const draggedId = e.dataTransfer.getData("widgetId");
    setDraggedWidgetId(null);
    setDragOverWidgetId(null);
    if (!draggedId || draggedId === targetId) return;
    if (!layout[draggedId] || !layout[targetId]) return;
    setLayout((prev) => {
      const next = { ...prev };
      const a = { ...next[draggedId] };
      const b = { ...next[targetId] };
      const limitsA = getWidgetGridLimits(draggedId);
      const limitsB = getWidgetGridLimits(targetId);
      const aw = Math.min(limitsA.maxW, Math.max(limitsA.minW, b.w ?? a.w));
      const ah = Math.min(limitsA.maxH, Math.max(limitsA.minH, b.h ?? a.h));
      const bw = Math.min(limitsB.maxW, Math.max(limitsB.minW, a.w ?? b.w));
      const bh = Math.min(limitsB.maxH, Math.max(limitsB.minH, a.h ?? b.h));
      next[draggedId] = { x: b.x, y: b.y, w: aw, h: ah };
      next[targetId] = { x: a.x, y: a.y, w: bw, h: bh };
      const resolved = resolveOverlaps(next, selectedWidgets);
      saveLayout(resolved);
      return resolved;
    });
  };

  useEffect(() => {
    if (!resizing.id || !gridRef.current) return;
    const startX = resizing.startX;
    const startY = resizing.startY;
    const startW = resizing.startW;
    const startH = resizing.startH;
    const id = resizing.id;
    const limits = getWidgetGridLimits(id);
    const onMove = (e) => {
      const el = gridRef.current;
      const colWidth = el ? el.offsetWidth / GRID_COLS : GRID_COL_WIDTH_PX;
      const newW = Math.min(limits.maxW, Math.max(limits.minW, Math.round(startW + (e.clientX - startX) / colWidth)));
      const newH = Math.min(limits.maxH, Math.max(limits.minH, Math.round(startH + (e.clientY - startY) / GRID_ROW_HEIGHT_PX)));
      setLayout((prev) => {
        const current = prev[id] || {};
        const x = current.x ?? 0;
        const y = current.y ?? 0;
        const next = { ...prev, [id]: { ...current, x, y, w: newW, h: newH } };
        saveLayout(next);
        return next;
      });
    };
    const onUp = () => setResizing({ id: null, startX: 0, startY: 0, startW: 0, startH: 0 });
    document.body.style.userSelect = "none";
    document.body.style.cursor = "nwse-resize";
    document.addEventListener("mousemove", onMove);
    document.addEventListener("mouseup", onUp);
    return () => {
      document.body.style.userSelect = "";
      document.body.style.cursor = "";
      document.removeEventListener("mousemove", onMove);
      document.removeEventListener("mouseup", onUp);
    };
  }, [resizing.id, resizing.startX, resizing.startY, resizing.startW, resizing.startH]);

  const handleLogout = () => {
    if (window.confirm("Are you sure you want to sign out?")) {
      setLoggingOut(true);
      localStorage.removeItem("token");
      localStorage.removeItem("isAuthenticated");
      navigate("/login");
    }
  };

  const closeSidebar = () => setSidebarOpen(false);

  const STAT_WIDGET_INDEX = { statTotalAudits: 0, statComplianceRate: 1, statCriticalFindings: 2, statTotalUsers: 3 };
  const SIO_OIO_CA_PCT_INDEX = { sioPctCard: 0, oioPctCard: 1, sioPaPctCard: 2 };
  const NO_OUTER_CARD_WIDGETS = new Set([
    "statTotalAudits",
    "statComplianceRate",
    "statCriticalFindings",
    "statTotalUsers",
    "sioPctCard",
    "oioPctCard",
    "sioPaPctCard",
    "raStatsCompleted",
    "raStatsInProgress",
    "raStatsNotStarted",
    "raStatsTotal"
  ]);

  const renderWidget = (id) => {
    switch (id) {
      case "stats":
        return (
          <div className="personalized-dashboard-stats-grid">
            {stats.map((stat, index) => (
              <StatCard key={index} stat={stat} index={index} />
            ))}
          </div>
        );
      case "statTotalAudits":
      case "statComplianceRate":
      case "statCriticalFindings":
      case "statTotalUsers": {
        const idx = STAT_WIDGET_INDEX[id];
        const stat = stats[idx];
        return stat ? <StatCard stat={stat} index={idx} /> : null;
      }
      case "answersTrend":
        return <AnswersTrendChart data={answersTrendData} variant="auditsPerMonth" />;
      case "topSites":
        return <TopSitesList sites={topSitesByCompliance} />;
      case "recentActivities":
        return <RecentActivities activities={recentActivities} />;
      case "severityOfHarm":
        return <SeverityOfHarmPieChart data={severityOfHarmData} />;
      case "likelihoodOfHarm":
        return <LikelihoodOfHarmPieChart data={likelihoodOfHarmData} />;
      case "observationsOpenClosed":
        return <ObservationsOpenClosedBarChart data={observationsOpenClosedData} />;
      case "rpnAuditBar":
        return <RpnAuditBarChart data={rpnAuditCountsData} />;
      case "sioOioCaPie":
        return <SioOioCaCharts data={sioOioCaData} showOnly="pie" />;
      case "sioPctCard":
      case "oioPctCard":
      case "sioPaPctCard": {
        const idx = SIO_OIO_CA_PCT_INDEX[id];
        const stat = sioOioCaPercentageStats[idx];
        return stat ? <StatCard stat={stat} index={idx} /> : null;
      }
      case "raStatsCompleted":
      case "raStatsInProgress":
      case "raStatsNotStarted":
      case "raStatsTotal": {
        const stat = raStatsWidgets[id];
        return stat ? <StatCard stat={stat} /> : null;
      }
      case "raRecentAssessments":
        return <RARecentAssessments recent={raRecent} widgetId={id} />;
      case "raStatusBreakdown":
        return <RAStatusBreakdown statusGroups={raStatusGroups} widgetId={id} />;
      case "raTrendChart":
        return (
          <RADashboardTrendChart
            data={adminTrendData}
            hasAssignments={assignedForTrend.length > 0}
            granularity={raTrendGranularity}
            onGranularityChange={setRaTrendGranularity}
            subtitle="Assigned and completed assessments over time"
            seriesLabels={{ assigned: "Assigned", completed: "Completed" }}
          />
        );
      case "raLocationDrilldown":
        return <RALocationDrilldownPie assessments={riskAssessments} countries={raCountries} />;
      default:
        return null;
    }
  };

  const getWidgetLabel = (id) => WIDGET_OPTIONS.find((w) => w.id === id)?.label || id;
  const availableToAdd = WIDGET_OPTIONS.filter((w) => !selectedWidgets.includes(w.id));

  return (
    <div className="master-dashboard personalized-dashboard">
      <div
        className={`master-dashboard-overlay ${sidebarOpen ? "master-dashboard-overlay--open" : ""}`}
        onClick={closeSidebar}
        onKeyDown={(e) => e.key === "Enter" && closeSidebar()}
        role="button"
        tabIndex={-1}
        aria-hidden={!sidebarOpen}
        aria-label="Close menu"
      />

      <aside
        className={`master-dashboard-sidebar ${sidebarOpen ? "master-dashboard-sidebar--open" : ""}`}
        aria-label="Navigation"
        aria-hidden={!sidebarOpen}
      >
        <div className="master-dashboard-sidebar-header">
          <span className="master-dashboard-sidebar-title">Menu</span>
          <button
            type="button"
            className="master-dashboard-sidebar-close"
            onClick={closeSidebar}
            aria-label="Close sidebar"
          >
            <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
          </button>
        </div>
        <div className="master-dashboard-sidebar-user">
          {displayName && (
            <>
              <span className="master-dashboard-sidebar-user-label">Signed in as</span>
              <span className="master-dashboard-sidebar-user-name" title={displayName}>
                {displayName}
              </span>
            </>
          )}
        </div>
        <nav className="master-dashboard-sidebar-nav">
          <ul className="master-dashboard-sidebar-list">
            <li>
              <button
                type="button"
                className="master-dashboard-sidebar-item master-dashboard-sidebar-item--available"
                onClick={() => {
                  navigate("/");
                  closeSidebar();
                }}
              >
                <svg className="master-dashboard-sidebar-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                <span>Master Dashboard</span>
              </button>
            </li>
            <li>
              <button
                type="button"
                className="master-dashboard-sidebar-item master-dashboard-sidebar-item--active"
                onClick={() => closeSidebar()}
              >
                <svg className="master-dashboard-sidebar-icon" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <path d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                </svg>
                <span>Personalised Dashboard</span>
              </button>
            </li>
            {PROJECTS.map((project) => {
              const route = getProjectRoute(project.id);
              const isAvailable = project.available && !!route;
              return (
                <li key={project.id}>
                  <button
                    type="button"
                    className={`master-dashboard-sidebar-item ${
                      isAvailable
                        ? "master-dashboard-sidebar-item--available"
                        : "master-dashboard-sidebar-item--disabled"
                    }`}
                    onClick={() => {
                      if (!isAvailable) return;
                      if (route.startsWith("http")) {
                        window.location.href = route;
                      } else {
                        navigate(route);
                      }
                      closeSidebar();
                    }}
                    disabled={!isAvailable}
                    title={project.name}
                  >
                    <span className="master-dashboard-sidebar-icon">
                      {/* Reuse simple icons: user vs box */}
                      {project.icon === "clipboard" ? (
                        <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                          <path
                            d="M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"
                            stroke="currentColor"
                            strokeWidth="2"
                            strokeLinecap="round"
                            strokeLinejoin="round"
                          />
                        </svg>
                      ) : (
                        <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                          <path
                            d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"
                            stroke="currentColor"
                            strokeWidth="2"
                            strokeLinecap="round"
                            strokeLinejoin="round"
                          />
                          <path
                            d="M3.27 6.96 12 12.01l8.73-5.05M12 22.08V12"
                            stroke="currentColor"
                            strokeWidth="2"
                            strokeLinecap="round"
                            strokeLinejoin="round"
                          />
                        </svg>
                      )}
                    </span>
                    <span>{project.name}</span>
                  </button>
                </li>
              );
            })}
          </ul>
        </nav>
        <div className="master-dashboard-sidebar-footer">
          <button
            type="button"
            className="master-dashboard-sidebar-logout"
            onClick={() => {
              closeSidebar();
              handleLogout();
            }}
            disabled={loggingOut}
          >
            <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
              <path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4M16 17l5-5-5-5M21 12H9" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
            </svg>
            Sign out
          </button>
        </div>
      </aside>

      <div className="master-dashboard-topbar">
        <div className="master-dashboard-topbar-inner">
          <div className="master-dashboard-topbar-left">
            <button
              type="button"
              className="master-dashboard-menu-btn"
              onClick={() => setSidebarOpen(true)}
              aria-label="Open menu"
              aria-expanded={sidebarOpen}
            >
              <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M4 6h16M4 12h16M4 18h16" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </button>
            <button
              type="button"
              className="master-dashboard-menu-btn"
              onClick={toggleTheme}
              aria-label={theme === 'light' ? 'Switch to Night Mode' : 'Switch to Light Mode'}
              title={theme === 'light' ? 'Switch to Night Mode' : 'Switch to Light Mode'}
            >
              {theme === 'light' ? (
                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
              ) : (
                <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                  <circle cx="12" cy="12" r="5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
                  <path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
                </svg>
              )}
            </button>
          </div>
          <div className="master-dashboard-brand">
            <div className="master-dashboard-logo">
              <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
            </div>
            <span className="master-dashboard-brand-text">Personalised Dashboard</span>
          </div>
          <div className="master-dashboard-topbar-actions">
            {displayName && (
              <div className="master-dashboard-user-pill" title={displayName}>
                <span className="master-dashboard-user-avatar" aria-hidden>
                  {displayName
                    .split(/\s+/)
                    .map((s) => s[0])
                    .join("")
                    .slice(0, 2)}
                </span>
                <span className="master-dashboard-user-name">{displayName}</span>
              </div>
            )}
            <button
              type="button"
              className="master-dashboard-logout-btn"
              onClick={handleLogout}
              disabled={loggingOut}
              aria-label="Sign out"
            >
              <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4M16 17l5-5-5-5M21 12H9" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
              </svg>
              <span>Sign out</span>
            </button>
          </div>
        </div>
      </div>

      <main className="personalized-dashboard-main" aria-label="Personalised dashboard content">
        {loading ? (
          <div className="personalized-dashboard-loading">
            <div className="dashboard-loading-spinner" />
            <p>Loading dashboard…</p>
          </div>
        ) : (
          <>
            {error ? (
              <div className="personalized-dashboard-error" role="status">
                <p>
                  Some chart data could not be loaded. You can still manage your
                  personalised layout.
                </p>
              </div>
            ) : null}
            <div className="personalized-dashboard-toolbar">
              <div className="personalized-dashboard-add-chart-wrap" ref={addChartWrapRef}>
                <button
                  type="button"
                  className="personalized-dashboard-add-chart-btn"
                  onClick={(e) => {
                    e.stopPropagation();
                    setAddChartOpen((o) => !o);
                  }}
                  aria-expanded={addChartOpen}
                  aria-haspopup="listbox"
                  aria-label="Add chart from dashboard"
                >
                  <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
                    <path d="M12 5v14M5 12h14" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                  </svg>
                  Add chart
                </button>
                {addChartOpen && (
                  <div
                    className="personalized-dashboard-add-chart-dropdown"
                    role="listbox"
                    aria-label="Charts from dashboard"
                  >
                    {availableToAdd.length === 0 ? (
                      <p className="personalized-dashboard-add-chart-empty">All charts from the dashboard are already added.</p>
                    ) : (
                      availableToAdd.map((w) => (
                        <button
                          key={w.id}
                          type="button"
                          role="option"
                          className="personalized-dashboard-add-chart-option"
                          onClick={() => addWidget(w.id)}
                        >
                          <span className="personalized-dashboard-add-chart-option-label">{w.label}</span>
                          {w.description && <span className="personalized-dashboard-add-chart-option-desc">{w.description}</span>}
                        </button>
                      ))
                    )}
                  </div>
                )}
              </div>
            </div>
            {selectedWidgets.length === 0 ? (
              <div className="personalized-dashboard-empty">
                <p className="personalized-dashboard-empty-title">Build your dashboard</p>
                <p className="personalized-dashboard-empty-desc">Add charts using the button above to create your personalised view. Your choices are saved for next time.</p>
                <button
                  type="button"
                  className="personalized-dashboard-empty-btn"
                  onClick={() => setAddChartOpen(true)}
                >
                  Add your first chart
                </button>
              </div>
            ) : (
              <div
                ref={gridRef}
                className="personalized-dashboard-grid personalized-dashboard-grid--clickable-empty personalized-dashboard-grid--xy"
                onClick={(e) => {
                  if (e.target === e.currentTarget) setAddChartOpen(true);
                }}
                style={{
                  "--grid-cols": GRID_COLS,
                  "--grid-row-height": `${GRID_ROW_HEIGHT_PX}px`,
                }}
              >
            {selectedWidgets.map((id) => {
              const grid = getLayoutGrid(id);
              const isStats = id === "stats";
              const noOuterCard = NO_OUTER_CARD_WIDGETS.has(id);
              const isDragging = draggedWidgetId === id;
              const isDragOver = dragOverWidgetId === id;
              return (
                <div
                  key={id}
                  className={`personalized-dashboard-widget ${isStats ? "personalized-dashboard-widget--stats" : ""} ${noOuterCard ? "personalized-dashboard-widget--no-outer" : ""} ${id === "raLocationDrilldown" ? "personalized-dashboard-widget--align-start" : ""} ${resizing.id === id ? "personalized-dashboard-widget--resizing" : ""} ${isDragging ? "personalized-dashboard-widget--dragging" : ""} ${isDragOver ? "personalized-dashboard-widget--drag-over" : ""}`}
                  style={{
                    gridColumn: isStats ? "1 / -1" : `${grid.x + 1} / span ${grid.w}`,
                    gridRow: isStats ? `${grid.y + 1} / span ${grid.h}` : `${grid.y + 1} / span ${grid.h}`,
                  }}
                  data-widget-id={id}
                  onDragOver={(e) => handleDragOver(e, id)}
                  onDragLeave={handleDragLeave}
                  onDrop={(e) => handleDrop(e, id)}
                >
                  <div className="personalized-dashboard-widget-actions">
                    <div
                      className="personalized-dashboard-widget-drag-handle"
                      draggable
                      onDragStart={(e) => handleDragStart(e, id)}
                      onDragEnd={handleDragEnd}
                      role="button"
                      tabIndex={0}
                      aria-label={`Move ${getWidgetLabel(id)}`}
                      title="Drag to reorder"
                    >
                      <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="16" height="16">
                        <path d="M8 6h.01M8 12h.01M8 18h.01M16 6h.01M16 12h.01M16 18h.01" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                      </svg>
                    </div>
                    <button
                      type="button"
                      className="personalized-dashboard-widget-remove"
                      onClick={() => removeWidget(id)}
                      aria-label={`Remove ${getWidgetLabel(id)}`}
                      title="Remove"
                    >
                      <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="16" height="16">
                        <path d="M18 6L6 18M6 6l12 12" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                      </svg>
                    </button>
                  </div>
                  {!isStats && (
                    <div
                      className="personalized-dashboard-widget-resize-handle"
                      onMouseDown={(e) => startResize(id, e)}
                      role="button"
                      tabIndex={0}
                      aria-label={`Resize ${getWidgetLabel(id)}`}
                      title="Resize"
                      onKeyDown={(e) => {
                        if (e.key === "Enter" || e.key === " ") e.preventDefault();
                      }}
                    >
                      <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" width="16" height="16">
                        <path d="M15 15l4 4M15 9l4-4M9 15l-4 4M9 9L5 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
                      </svg>
                    </div>
                  )}
                  <div className="personalized-dashboard-widget-body">{renderWidget(id)}</div>
                </div>
              );
            })}
              </div>
            )}
          </>
        )}
      </main>

      <footer className="master-dashboard-footer">
        <div className="master-dashboard-footer-inner">
          <p className="master-dashboard-footer-text">
            Need help? Contact your administrator or platform support.
          </p>
          <p className="master-dashboard-footer-copy">&copy; {new Date().getFullYear()} Platform. All rights reserved.</p>
        </div>
      </footer>
    </div>
  );
}

export default PersonalizedDashboard;
