"use client";

import type { ElementType, ReactNode } from "react";

import Box from "@mui/material/Box";
import FormControl from "@mui/material/FormControl";
import MenuItem from "@mui/material/MenuItem";
import OutlinedInput from "@mui/material/OutlinedInput";
import Select, { type SelectChangeEvent } from "@mui/material/Select";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";
import type { SxProps, Theme } from "@mui/material/styles";

import { dashboardAssets } from "@/components/dashboard/dashboard-assets";
import { DashboardAssetIcon } from "@/components/dashboard/dashboard-asset-icon";
import { AppCheckbox } from "@/components/ui/checkbox";

export type DropdownOption = {
  label: string;
  value: string;
  logo?: string | null;
};

export type DropdownProps = {
  label: string;
  options: DropdownOption[];
  value: string | string[];
  width?: number | string;
  multiple?: boolean;
  showCheckbox?: boolean;
  displayMode?: "count" | "join" | "single";
  menuMinWidth?: number;
  menuMaxHeight?: number;
  disabled?: boolean;
  /**
   * Called once when the menu closes. A multi-select menu stays open while the
   * user ticks options, so this is the moment to save the whole selection.
   */
  onClose?: () => void;
  /** Replaces the closed-state label, e.g. to show a logo or a status badge. */
  renderTrigger?: (selectedValues: string[]) => ReactNode;
  /** Extra styles for the closed trigger, e.g. to drop the border in a table. */
  triggerSx?: SxProps<Theme>;
  /**
   * MUI Select end icon. Defaults to hidden so triggers can draw their own
   * chevron; pass the same icon as status cells when you want the standard arrow.
   */
  IconComponent?: ElementType;
  onChange: (value: string | string[]) => void;
};

function DropdownChevron() {
  return (
    <DashboardAssetIcon
      src={dashboardAssets.chevronDownSmall}
      width={8}
      height={5}
      sx={{ flexShrink: 0, pointerEvents: "none" }}
    />
  );
}

function DropdownTriggerValue({ text }: { text: string }) {
  return (
    <Box
      sx={{
        display: "flex",
        alignItems: "center",
        justifyContent: "space-between",
        gap: 1.5,
        width: "100%",
        minWidth: 0,
      }}
    >
      <Box
        component="span"
        sx={{
          flex: 1,
          minWidth: 0,
          overflow: "hidden",
          textOverflow: "ellipsis",
          whiteSpace: "nowrap",
        }}
      >
        {text}
      </Box>
      <DropdownChevron />
    </Box>
  );
}

export function Dropdown({
  label,
  options,
  value,
  width = 153,
  multiple = false,
  showCheckbox = false,
  displayMode = "single",
  menuMinWidth,
  menuMaxHeight,
  disabled = false,
  onClose,
  renderTrigger,
  triggerSx,
  IconComponent,
  onChange,
}: DropdownProps) {
  const showSelectIcon = Boolean(IconComponent);
  const theme = useTheme();
  const isDark = theme.palette.mode === "dark";
  // A checkbox dropdown can also be single-select. Wrap its one value in an
  // array so the selected item, including the empty "All" option, is checked.
  const selectedValues = Array.isArray(value) ? value : [value];
  const hasValue = Array.isArray(value) ? value.length > 0 : Boolean(value);
  const resolvedMenuMaxHeight = menuMaxHeight ?? 232;

  const menuPaperSx = showCheckbox
    ? {
        mt: 1,
        minWidth: menuMinWidth ?? 386,
        maxWidth: menuMinWidth ?? 386,
        borderRadius: "12px",
        border: `1px solid ${isDark ? alpha("#ffffff", 0.12) : "#f5f5f5"}`,
        bgcolor: isDark ? "#101828" : "#ffffff",
        boxShadow: isDark
          ? "0 12px 30px rgba(0, 0, 0, 0.5)"
          : "0px 0px 10.6px rgba(0, 0, 0, 0.1)",
        overflow: "hidden",
        "& .MuiList-root": {
          maxHeight: resolvedMenuMaxHeight,
          overflowY: "auto",
          py: 0.5,
          scrollbarWidth: "thin",
          scrollbarColor: isDark
            ? `${alpha("#ffffff", 0.4)} ${alpha("#ffffff", 0.12)}`
            : "#a4a7ae #e9eaeb",
          "&::-webkit-scrollbar": {
            width: 6,
          },
          "&::-webkit-scrollbar-track": {
            background: isDark ? alpha("#ffffff", 0.12) : "#e9eaeb",
            borderRadius: "3px",
          },
          "&::-webkit-scrollbar-thumb": {
            background: isDark ? alpha("#ffffff", 0.4) : "#a4a7ae",
            borderRadius: "3px",
          },
        },
        "& .MuiMenuItem-root": {
          minHeight: 40,
          px: 1.5,
          py: 1.25,
          gap: 1.5,
          color: isDark ? alpha("#ffffff", 0.86) : "#414651",
          "&:hover": {
            bgcolor: isDark ? alpha("#ffffff", 0.06) : alpha("#000000", 0.04),
          },
          "&.Mui-selected": {
            bgcolor: "transparent",
          },
          "&.Mui-selected:hover": {
            bgcolor: isDark ? alpha("#ffffff", 0.06) : alpha("#000000", 0.04),
          },
        },
      }
    : {
        mt: 1,
        borderRadius: "14px",
        border: `1px solid ${theme.palette.divider}`,
        bgcolor: theme.palette.background.paper,
        boxShadow:
          theme.palette.mode === "dark"
            ? "0 12px 30px rgba(0, 0, 0, 0.5)"
            : "0 12px 30px rgba(15, 23, 42, 0.12)",
        maxHeight: 320,
        "& .MuiMenuItem-root": {
          minHeight: 48,
          px: 1.5,
          color: theme.palette.text.primary,
        },
        "& .MuiMenuItem-root:hover": {
          bgcolor: theme.palette.action.hover,
        },
        "& .MuiMenuItem-root.Mui-selected": {
          bgcolor: alpha(theme.palette.primary.main, 0.16),
        },
        "& .MuiMenuItem-root.Mui-selected:hover": {
          bgcolor: alpha(theme.palette.primary.main, 0.24),
        },
      };

  const handleChange = (event: SelectChangeEvent<string | string[]>) => {
    const selectedValue = event.target.value;

    if (multiple) {
      onChange(
        Array.isArray(selectedValue) ? selectedValue : selectedValue.split(","),
      );
      return;
    }

    onChange(String(selectedValue));
  };

  const getDisplayText = (selectedValue: unknown) => {
    if (multiple) {
      const items = Array.isArray(selectedValue)
        ? (selectedValue as string[])
        : [];

      if (items.length === 0) {
        return label;
      }

      if (displayMode === "count") {
        return `${label} (${items.length})`;
      }

      if (displayMode === "join") {
        return options
          .filter((option) => items.includes(option.value))
          .map((option) => option.label)
          .join(", ");
      }

      return (
        options.find((option) => option.value === items[0])?.label ?? label
      );
    }

    const itemValue = String(selectedValue ?? "");

    if (!itemValue) {
      return label;
    }

    return options.find((option) => option.value === itemValue)?.label ?? label;
  };

  const renderValue = (selectedValue: unknown) => {
    if (renderTrigger) {
      return renderTrigger(
        Array.isArray(selectedValue)
          ? (selectedValue as string[])
          : [String(selectedValue ?? "")].filter(Boolean),
      );
    }

    return <DropdownTriggerValue text={getDisplayText(selectedValue)} />;
  };

  return (
    <FormControl size="small" sx={{ width }} disabled={disabled}>
      <Select
        multiple={multiple}
        displayEmpty
        disabled={disabled}
        value={value}
        onChange={handleChange}
        onClose={onClose}
        input={<OutlinedInput notched={false} />}
        renderValue={renderValue}
        IconComponent={IconComponent ?? (() => null)}
        MenuProps={{
          slotProps: {
            paper: {
              sx: menuPaperSx,
            },
          },
        }}
        sx={[
          {
            height: 40,
            borderRadius: "6px",
            bgcolor: theme.palette.background.paper,
            color: hasValue
              ? theme.palette.text.primary
              : theme.palette.text.secondary,
            fontSize: 13,
            fontWeight: 500,
            "& .MuiOutlinedInput-notchedOutline": {
              borderColor: theme.palette.divider,
            },
            "&:hover .MuiOutlinedInput-notchedOutline": {
              borderColor: theme.palette.text.secondary,
            },
            "&.Mui-focused .MuiOutlinedInput-notchedOutline": {
              borderColor: theme.palette.primary.main,
              borderWidth: 1,
            },
            "& .MuiSelect-select": {
              display: "flex",
              alignItems: "center",
              minHeight: "40px !important",
              px: 1.5,
              py: 0,
              pr: showSelectIcon ? "28px !important" : "12px !important",
            },
            "& .MuiSelect-icon": showSelectIcon
              ? {
                  fontSize: 20,
                  color: theme.palette.text.secondary,
                  right: 0,
                }
              : {
                  display: "none",
                },
          },
          ...(Array.isArray(triggerSx)
            ? triggerSx
            : triggerSx
              ? [triggerSx]
              : []),
        ]}
      >
        {options.map((option) => (
          <MenuItem key={option.value} value={option.value} dense>
            {showCheckbox ? (
              <AppCheckbox
                checked={selectedValues.includes(option.value)}
                tabIndex={-1}
                sx={{
                  mr: 0,
                  flexShrink: 0,
                }}
              />
            ) : null}

            <Box
              sx={{
                display: "flex",
                alignItems: "center",
                gap: 1.25,
                minWidth: 0,
                flex: 1,
              }}
            >
              {option.logo !== undefined ? (
                <Box
                  component="img"
                  src={option.logo || dashboardAssets.primaryAgencyAvatar}
                  alt=""
                  sx={{
                    width: 24,
                    height: 24,
                    borderRadius: "50%",
                    objectFit: "cover",
                    flexShrink: 0,
                  }}
                />
              ) : null}

              <Typography
                noWrap
                sx={{
                  fontSize: showCheckbox ? 13 : 14,
                  fontWeight: 500,
                  color: showCheckbox
                    ? isDark
                      ? alpha("#ffffff", 0.86)
                      : "#414651"
                    : "inherit",
                  minWidth: 0,
                }}
              >
                {option.label}
              </Typography>
            </Box>
          </MenuItem>
        ))}
      </Select>
    </FormControl>
  );
}
