import Switch from "@mui/material/Switch";

const baseSwitchSx = {
    "--switch-width": "40px",
    "--switch-height": "24px",
    "--switch-thumb-size": "18px",
    "--switch-padding": "3px",
    "--switch-translate-x": "16px",
    margin: 0,
};

function cssContent(value) {
    return `"${String(value ?? "")
        .replace(/\\/g, "\\\\")
        .replace(/"/g, '\\"')}"`;
}

function labeledSwitchSx(checkedLabel, uncheckedLabel) {
    const labelLength = Math.max(
        Array.from(String(checkedLabel || "")).length,
        Array.from(String(uncheckedLabel || "")).length,
    );
    const width = Math.max(56, Math.min(84, 34 + labelLength * 11));

    return {
        "--switch-width": `${width}px`,
        "--switch-height": "26px",
        "--switch-thumb-size": "20px",
        "--switch-padding": "3px",
        "--switch-translate-x": `${width - 26}px`,
        width: "var(--switch-width)",
        height: "var(--switch-height)",
        padding: 0,
        overflow: "visible",
        "& .MuiSwitch-switchBase": {
            padding: "var(--switch-padding)",
            "&.Mui-checked": {
                transform: "translateX(var(--switch-translate-x))",
            },
        },
        "& .MuiSwitch-thumb": {
            width: "var(--switch-thumb-size)",
            height: "var(--switch-thumb-size)",
        },
        "& .MuiSwitch-track": {
            overflow: "hidden",
            position: "relative",
            "&::before, &::after": {
                position: "absolute",
                top: 0,
                bottom: 0,
                display: "flex",
                alignItems: "center",
                fontSize: "10px",
                fontWeight: 720,
                letterSpacing: 0,
                lineHeight: 1,
                whiteSpace: "nowrap",
                pointerEvents: "none",
                transition: "opacity 180ms cubic-bezier(0.2, 0, 0, 1)",
            },
            "&::before": {
                left: 5,
                right: 20,
                justifyContent: "flex-start",
                color: "var(--active-contrast)",
                content: cssContent(checkedLabel),
                opacity: 0,
            },
            "&::after": {
                right: 5,
                left: 20,
                justifyContent: "flex-end",
                color: "var(--text-tertiary)",
                content: cssContent(uncheckedLabel),
                opacity: 1,
            },
        },
        "& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track::before": {
            opacity: 1,
        },
        "& .MuiSwitch-switchBase.Mui-checked + .MuiSwitch-track::after": {
            opacity: 0,
        },
    };
}

function mergeInputSlotProps(slotInputProps, fallbackInputProps) {
    if (!fallbackInputProps) {
        return slotInputProps;
    }
    if (typeof slotInputProps === "function") {
        return (ownerState) => ({
            ...fallbackInputProps,
            ...slotInputProps(ownerState),
        });
    }
    return {
        ...fallbackInputProps,
        ...slotInputProps,
    };
}

export function AdminSwitch({ checkedLabel, inputProps, label, slotProps, sx, uncheckedLabel, ...props }) {
    const hasInlineLabel = Boolean(checkedLabel || uncheckedLabel);
    const switchLabelSx = hasInlineLabel ? labeledSwitchSx(checkedLabel, uncheckedLabel) : null;
    const mergedSx = Array.isArray(sx)
        ? [baseSwitchSx, switchLabelSx, ...sx].filter(Boolean)
        : [baseSwitchSx, switchLabelSx, sx].filter(Boolean);
    const fallbackInputProps = label || inputProps || slotProps?.input
        ? {
              role: "switch",
              ...(label ? { "aria-label": label } : null),
              ...inputProps,
          }
        : undefined;
    const mergedSlotProps =
        fallbackInputProps || slotProps
            ? {
                  ...slotProps,
                  input: mergeInputSlotProps(slotProps?.input, fallbackInputProps),
              }
            : undefined;

    return <Switch {...props} slotProps={mergedSlotProps} sx={mergedSx} />;
}
