import type { ReactNode } from "react";

import Box, { type BoxProps } from "@mui/material/Box";
import TextField, { type TextFieldProps } from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import { alpha, useTheme } from "@mui/material/styles";
import type { SxProps, Theme } from "@mui/material/styles";

type AppFormLabelProps = {
  children: ReactNode;
  required?: boolean;
  sx?: SxProps<Theme>;
};

type AppFormFieldProps = {
  children: ReactNode;
  label: ReactNode;
  required?: boolean;
  sx?: SxProps<Theme>;
};

export type AppFormTextFieldProps = TextFieldProps;

export type AppFormGridProps = BoxProps & {
  columns?: 1 | 2;
};

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

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

export function getFormBorderColor(theme: Theme) {
  return theme.palette.mode === "dark"
    ? alpha(theme.palette.common.white, 0.14)
    : "#E2E8F0";
}

export function getFormSoftBg(theme: Theme) {
  return theme.palette.mode === "dark"
    ? alpha(theme.palette.common.white, 0.04)
    : "#FAFAFA";
}

export function getFormInputSx(theme: Theme): SxProps<Theme> {
  return {
    "& .MuiOutlinedInput-root": {
      height: 40,
      borderRadius: "6px",
      bgcolor: theme.palette.background.paper,
      color: theme.palette.text.primary,
      fontSize: 12,
    },
    "& .MuiOutlinedInput-notchedOutline": {
      borderColor: getFormBorderColor(theme),
    },
    "&:hover .MuiOutlinedInput-notchedOutline": {
      borderColor:
        theme.palette.mode === "dark"
          ? alpha(theme.palette.common.white, 0.28)
          : "#CBD5E1",
    },
    "& .MuiInputBase-input": {
      fontSize: 12,
      color: theme.palette.text.primary,
      "&::placeholder": {
        color: theme.palette.text.secondary,
        opacity: 1,
      },
    },
  };
}

export function getFormSelectSx(theme: Theme): SxProps<Theme> {
  return {
    height: 40,
    borderRadius: "6px",
    bgcolor: theme.palette.background.paper,
    fontSize: 12,
    color: theme.palette.text.primary,
    "& .MuiOutlinedInput-notchedOutline": {
      borderColor: getFormBorderColor(theme),
    },
    "&:hover .MuiOutlinedInput-notchedOutline": {
      borderColor:
        theme.palette.mode === "dark"
          ? alpha(theme.palette.common.white, 0.28)
          : "#CBD5E1",
    },
    "&.Mui-focused .MuiOutlinedInput-notchedOutline": {
      borderColor: theme.palette.primary.main,
      borderWidth: "1px",
    },
    "& .MuiSelect-select": {
      height: 40,
      py: 0,
      display: "flex",
      alignItems: "center",
    },
    "& .MuiSelect-icon": {
      fontSize: 18,
      color: theme.palette.text.primary,
    },
  };
}

export function getFormSelectMenuProps(theme: Theme) {
  return {
    anchorOrigin: {
      vertical: "bottom" as const,
      horizontal: "left" as const,
    },
    transformOrigin: {
      vertical: "top" as const,
      horizontal: "left" as const,
    },
    slotProps: {
      paper: {
        sx: {
          mt: 0.6,
          maxHeight: 190,
          borderRadius: "10px",
          bgcolor: theme.palette.background.paper,
          color: theme.palette.text.primary,
          boxShadow:
            theme.palette.mode === "dark"
              ? "0px 12px 28px rgba(0,0,0,0.45)"
              : "0px 8px 24px rgba(16, 24, 40, 0.12)",
          border: `1px solid ${getFormBorderColor(theme)}`,
          overflow: "hidden",
          "& .MuiList-root": {
            py: 0.5,
            maxHeight: 190,
            overflowY: "auto",
            "&::-webkit-scrollbar": {
              width: 6,
            },
            "&::-webkit-scrollbar-thumb": {
              backgroundColor:
                theme.palette.mode === "dark"
                  ? alpha(theme.palette.common.white, 0.22)
                  : "#D1D5DB",
              borderRadius: 99,
            },
          },
          "& .MuiMenuItem-root": {
            minHeight: 42,
            px: 2,
            fontSize: 12,
            bgcolor: theme.palette.background.paper,
            color: theme.palette.text.primary,
            "&:hover": {
              bgcolor:
                theme.palette.mode === "dark"
                  ? alpha(theme.palette.primary.main, 0.12)
                  : "#F8FAFC",
            },
            "&.Mui-selected": {
              bgcolor:
                theme.palette.mode === "dark"
                  ? alpha(theme.palette.primary.main, 0.18)
                  : alpha(theme.palette.primary.main, 0.08),
            },
            "&.Mui-selected:hover": {
              bgcolor:
                theme.palette.mode === "dark"
                  ? alpha(theme.palette.primary.main, 0.24)
                  : alpha(theme.palette.primary.main, 0.12),
            },
          },
        },
      },
    },
  };
}

export function AppFormLabel({
  children,
  required = false,
  sx,
}: AppFormLabelProps) {
  const theme = useTheme();

  return (
    <Typography
      sx={[
        {
          fontSize: 12,
          fontWeight: required ? 600 : 500,
          color: theme.palette.text.primary,
          mb: 0.8,
        },
        ...getSxArray(sx),
      ]}
    >
      {children}
      {required ? (
        <Box component="span" sx={{ color: "#EF4444" }}>
          {" "}
          *
        </Box>
      ) : null}
    </Typography>
  );
}

export function AppFormField({
  children,
  label,
  required = false,
  sx,
}: AppFormFieldProps) {
  return (
    <Box sx={sx}>
      <AppFormLabel required={required}>{label}</AppFormLabel>
      {children}
    </Box>
  );
}

export function AppFormGrid({
  children,
  columns = 2,
  sx,
  ...props
}: AppFormGridProps) {
  return (
    <Box
      sx={[
        {
          display: "grid",
          gridTemplateColumns:
            columns === 2 ? { xs: "1fr", sm: "1fr 1fr" } : "1fr",
          gap: 2,
        },
        ...getSxArray(sx),
      ]}
      {...props}
    >
      {children}
    </Box>
  );
}

export function AppFormTextField({ sx, ...props }: AppFormTextFieldProps) {
  const theme = useTheme();

  return (
    <TextField
      fullWidth
      size="small"
      sx={[getFormInputSx(theme), ...getSxArray(sx)]}
      {...props}
    />
  );
}
