"use client";

import Box from "@mui/material/Box";
import Skeleton from "@mui/material/Skeleton";
import {
  alpha,
  useTheme,
  type SxProps,
  type Theme,
} from "@mui/material/styles";

type SkeletonSize = number | string;

export type DashboardSkeletonProps = {
  cardCount?: number;
  showAction?: boolean;
  showSidebar?: boolean;
  sidebarWidth?: number;
  sx?: SxProps<Theme>;
};

type SkeletonBlockProps = {
  width?: SkeletonSize;
  height: SkeletonSize;
  borderRadius?: SkeletonSize;
  sx?: SxProps<Theme>;
};

const DEFAULT_CARD_COUNT = 5;
const DEFAULT_SIDEBAR_WIDTH = 288;

function getSxArray(sx?: SxProps<Theme>) {
  if (!sx) return [];

  return Array.isArray(sx) ? sx : [sx];
}

// Pick skeleton block / sidebar accent colors that are visible against the
// current background, in both light and dark mode.
function useSkeletonTokens() {
  const theme = useTheme();
  const isDark = theme.palette.mode === "dark";

  return {
    blockColor: isDark
      ? alpha(theme.palette.common.white, 0.08)
      : "#e9eaeb",
    sidebarBorder: theme.palette.divider,
    activeMenuBg: isDark
      ? alpha(theme.palette.primary.main, 0.16)
      : "#eff8ff",
    sidebarBg: theme.palette.background.paper,
    sidebarPanelBg: isDark
      ? alpha(theme.palette.common.white, 0.04)
      : "#f5f6f8",
    mainBg: theme.palette.background.paper,
    rootBg: theme.palette.background.paper,
  };
}

function SkeletonBlock({
  width = "100%",
  height,
  borderRadius = 12,
  sx,
}: SkeletonBlockProps) {
  const { blockColor } = useSkeletonTokens();

  return (
    <Skeleton
      animation="wave"
      variant="rectangular"
      sx={[
        {
          width,
          height,
          borderRadius,
          bgcolor: blockColor,
          transform: "none",
        },
        ...getSxArray(sx),
      ]}
    />
  );
}

function SidebarMenuRow({ active = false }: { active?: boolean }) {
  const { activeMenuBg } = useSkeletonTokens();

  return (
    <Box
      sx={{
        display: "flex",
        alignItems: "center",
        gap: 2,
        width: "100%",
        height: 40,
        px: 2,
        borderRadius: "8px",
        bgcolor: active ? activeMenuBg : "transparent",
      }}
    >
      <SkeletonBlock width={18} height={18} borderRadius={4} />
      <SkeletonBlock
        width={active ? 126 : 150}
        height={10}
        borderRadius={8}
      />
      {active ? (
        <SkeletonBlock
          width={14}
          height={14}
          borderRadius={4}
          sx={{ ml: "auto" }}
        />
      ) : null}
    </Box>
  );
}

function DashboardSidebarSkeleton({ width }: { width: number }) {
  const { sidebarBg, sidebarBorder, sidebarPanelBg } = useSkeletonTokens();

  return (
    <Box
      component="aside"
      sx={{
        display: { xs: "none", lg: "flex" },
        flexDirection: "column",
        flexShrink: 0,
        width,
        minHeight: "100vh",
        px: 3,
        pt: 2.5,
        pb: 3,
        bgcolor: sidebarBg,
        borderRight: `1px solid ${sidebarBorder}`,
      }}
    >
      <Box sx={{ display: "flex", alignItems: "center", gap: 1.5 }}>
        <SkeletonBlock width={96} height={44} borderRadius={4} />
        <Box
          sx={{
            width: 1,
            height: 28,
            bgcolor: sidebarBorder,
          }}
        />
        <SkeletonBlock width={120} height={11} borderRadius={8} />
      </Box>

      <Box
        sx={{
          mx: -3,
          mt: 2,
          height: 1,
          bgcolor: sidebarBorder,
        }}
      />

      <Box sx={{ mt: 4 }}>
        <SkeletonBlock width={86} height={12} borderRadius={8} />

        <Box
          sx={{ mt: 2.5, display: "flex", flexDirection: "column", gap: 2 }}
        >
          <SidebarMenuRow active />
          <SidebarMenuRow />
          <SidebarMenuRow />
          <SidebarMenuRow />
          <SidebarMenuRow />
        </Box>
      </Box>

      <Box
        sx={{
          mt: "auto",
          width: "100%",
          minHeight: 236,
          borderRadius: "16px",
          bgcolor: sidebarPanelBg,
          px: 2,
          pt: 2,
          pb: 2.5,
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
        }}
      >
        <SkeletonBlock
          width={20}
          height={20}
          borderRadius="50%"
          sx={{ alignSelf: "flex-end" }}
        />
        <SkeletonBlock
          width={56}
          height={56}
          borderRadius={12}
          sx={{ mt: 1 }}
        />
        <SkeletonBlock width={78} height={12} borderRadius={8} sx={{ mt: 2 }} />
        <SkeletonBlock
          width={152}
          height={10}
          borderRadius={8}
          sx={{ mt: 1.5 }}
        />
        <SkeletonBlock
          width={126}
          height={10}
          borderRadius={8}
          sx={{ mt: 0.75 }}
        />
        <SkeletonBlock
          width="100%"
          height={40}
          borderRadius={8}
          sx={{ mt: "auto" }}
        />
      </Box>
    </Box>
  );
}

function DashboardMainSkeleton({
  cardCount,
  hasSidebar,
  showAction,
}: {
  cardCount: number;
  hasSidebar: boolean;
  showAction: boolean;
}) {
  const cards = Array.from({ length: cardCount });
  const { mainBg } = useSkeletonTokens();

  return (
    <Box
      component="main"
      sx={{
        flex: 1,
        minWidth: 0,
        px: { xs: 2, md: 3 },
        pt: { xs: 3, lg: hasSidebar ? "102px" : 0 },
        pb: { xs: 3, md: 4 },
        bgcolor: mainBg,
      }}
    >
      <Box
        sx={{
          display: "flex",
          alignItems: "flex-start",
          justifyContent: "space-between",
          gap: 3,
          mb: { xs: 3, md: 4 },
        }}
      >
        <Box sx={{ width: "100%", maxWidth: 441 }}>
          <SkeletonBlock width={219} height={31} />
          <SkeletonBlock width="100%" height={11} sx={{ mt: 1.75 }} />
        </Box>

        {showAction ? (
          <SkeletonBlock
            width={148}
            height={40}
            sx={{ display: { xs: "none", sm: "block" }, flexShrink: 0 }}
          />
        ) : null}
      </Box>

      <Box
        sx={{
          display: "grid",
          gridTemplateColumns: {
            xs: "1fr",
            sm: "repeat(2, minmax(0, 1fr))",
            lg: "repeat(5, minmax(0, 1fr))",
          },
          gap: 2.5,
          mb: 2.5,
        }}
      >
        {cards.map((_, index) => (
          <SkeletonBlock key={index} height={100} />
        ))}
      </Box>

      <Box
        sx={{
          display: "grid",
          gridTemplateColumns: {
            xs: "1fr",
            lg: "minmax(0, 698fr) minmax(320px, 458fr)",
          },
          gap: 2.5,
        }}
      >
        <SkeletonBlock height={360} sx={{ height: { xs: 360, lg: 627 } }} />
        <SkeletonBlock height={360} sx={{ height: { xs: 360, lg: 627 } }} />
      </Box>
    </Box>
  );
}

export function DashboardSkeleton({
  cardCount = DEFAULT_CARD_COUNT,
  showAction = true,
  showSidebar = true,
  sidebarWidth = DEFAULT_SIDEBAR_WIDTH,
  sx,
}: DashboardSkeletonProps) {
  const { rootBg } = useSkeletonTokens();

  return (
    <Box
      sx={[
        {
          display: "flex",
          width: "100%",
          minHeight: "100vh",
          bgcolor: rootBg,
        },
        ...getSxArray(sx),
      ]}
    >
      {showSidebar ? <DashboardSidebarSkeleton width={sidebarWidth} /> : null}

      <DashboardMainSkeleton
        cardCount={cardCount}
        hasSidebar={showSidebar}
        showAction={showAction}
      />
    </Box>
  );
}
