import {
  Controller,
  type UseControllerProps,
  useFormContext,
} from 'react-hook-form';

import { IconExclamationCircle } from '@material-hu/icons/tabler';
import FormHelperText from '@material-hu/mui/FormHelperText';
import Stack from '@material-hu/mui/Stack/Stack';
import Typography from '@material-hu/mui/Typography/Typography';

import RadioBase from '@material-hu/components/design-system/RadioButton/RadioBase';
import Table from '@material-hu/components/design-system/Table';
import TableBody from '@material-hu/components/design-system/Table/components/TableBody';
import TableCell from '@material-hu/components/design-system/Table/components/TableCell';
import TableContainer from '@material-hu/components/design-system/Table/components/TableContainer';
import TableHead from '@material-hu/components/design-system/Table/components/TableHead';
import TableRow from '@material-hu/components/design-system/Table/components/TableRow';

import useRules, { type RulesOptions } from 'src/hooks/useRules';
import {
  type CheckboxGridValue,
  type Option,
  type Question,
  type Row,
} from 'src/types/forms';
import { useLokaliseTranslation } from 'src/utils/i18n';

export type FormRadioGridProps = Omit<UseControllerProps, 'rules'> &
  Partial<Question> & {
    disabled?: boolean;
    rules?: RulesOptions;
  };

const FormRadioGrid = ({
  name,
  defaultValue,
  options,
  rows,
  disabled = false,
  rules = {},
}: FormRadioGridProps) => {
  const { t } = useLokaliseTranslation('validations');
  const {
    control,
    setValue,
    watch,
    trigger,
    formState: { isSubmitted, errors },
  } = useFormContext();

  const { requiredCheckboxGrid } = rules;
  const checkboxGridRules = useRules({
    ...rules,
    requiredCheckboxGrid:
      requiredCheckboxGrid && rows && options ? { rows, options } : undefined,
  });

  const value: CheckboxGridValue = watch(name, defaultValue) || {};

  const isChecked = (row: Row, option: Option) =>
    !!value && !!value[row.id] && value[row.id][0] === option.description;

  const handleChange = (row: Row, option: Option) => {
    const newValue: CheckboxGridValue = { ...value };

    if (isChecked(row, option)) {
      delete newValue[row.id];
    } else {
      newValue[row.id] = [option.description];
    }

    setValue(name, newValue);
    if (isSubmitted) {
      trigger(name);
    }
  };

  return (
    <Controller
      name={name}
      rules={checkboxGridRules}
      control={control}
      defaultValue={defaultValue}
      render={() => (
        <Stack>
          <TableContainer>
            <Table>
              <TableHead>
                <TableRow headerRow>
                  <TableCell
                    align="center"
                    headerCell
                    sx={{ borderRight: '1px solid', borderColor: 'divider' }}
                  />
                  {options?.map(option => (
                    <TableCell
                      key={option.id}
                      align="center"
                      headerCell
                    >
                      {option.description}
                    </TableCell>
                  ))}
                </TableRow>
              </TableHead>
              <TableBody>
                {rows?.map(row => (
                  <TableRow
                    key={row.id}
                    sx={{
                      '&:last-child td, &:last-child th': { borderBottom: 0 },
                    }}
                  >
                    <TableCell
                      id={`row-${row.id}`}
                      sx={{ borderRight: '1px solid', borderColor: 'divider' }}
                    >
                      <Typography
                        variant="globalS"
                        noWrap
                      >
                        {row.description}
                      </Typography>
                    </TableCell>
                    {options?.map(option => (
                      <TableCell key={option.id}>
                        <Stack
                          onClick={() => {
                            if (!disabled) handleChange(row, option);
                          }}
                          sx={{
                            width: 1,
                            display: 'flex',
                            justifyContent: 'center',
                            alignItems: 'center',
                            cursor: disabled ? 'default' : 'pointer',
                          }}
                        >
                          <RadioBase
                            value={option.description}
                            checked={isChecked(row, option)}
                            disabled={disabled}
                            sx={{ width: 'fit-content', pointerEvents: 'none' }}
                          />
                        </Stack>
                      </TableCell>
                    ))}
                  </TableRow>
                ))}
              </TableBody>
            </Table>
          </TableContainer>
          {errors[name] && (
            <FormHelperText
              sx={{
                mx: 0,
                mt: 1,
                '& *': {
                  color: ({ palette }) =>
                    `${palette.new?.text.feedback.error} !important`,
                },
              }}
            >
              <Stack
                component="span"
                sx={{
                  alignItems: 'flex-start',
                  flexDirection: 'row',
                  gap: 0.5,
                  '& > svg': {
                    minWidth: '16px',
                    height: '22px',
                  },
                }}
              >
                <IconExclamationCircle size="1rem" />
                <Typography
                  variant="globalS"
                  sx={{ flex: 1 }}
                >
                  {t('required')}
                </Typography>
              </Stack>
            </FormHelperText>
          )}
        </Stack>
      )}
    />
  );
};

export default FormRadioGrid;
