import { useAppState } from '@/components/AppStateProvider';
import { useSx } from '@/hooks';
import { InputLabel, Tooltip, Typography } from '@mui/material';
import { styled } from '@mui/material/styles';
import { get } from 'lodash';
import React, { Children, PropsWithChildren, useMemo } from 'react';
import { FieldTitle, useRecordContext, useResourceContext } from 'react-admin';

type StyledFieldProps = {
  theme?: any;
  fullWidth?: boolean;
};

const StyledField = styled('div')(({ theme, fullWidth }: StyledFieldProps) => ({
  borderBottom: `1px solid ${theme.palette.divider}`,
  paddingTop: theme.spacing(1),
  paddingBottom: theme.spacing(1),
  marginBottom: theme.spacing(1),
  whiteSpace: 'nowrap',
  overflow: 'hidden',
  textOverflow: 'ellipsis',
  width: fullWidth ? '100%' : 'auto',
  [theme.breakpoints.down('sm')]: {
    whiteSpace: 'normal',
    overflow: 'visible',
    textOverflow: 'inherit'
  }
}));

type BasicFieldProps = {
  source: string;
  defaultValue: any;
  record: any;
};

function BasicField({ source, defaultValue = '&nbsp;', ...props }: BasicFieldProps): JSX.Element {
  const record = useRecordContext(props);
  const value = get(record, source, defaultValue);
  return <Typography {...props} dangerouslySetInnerHTML={{ __html: value && value !== null ? value : defaultValue }} />;
}

type ContentWrapperProps = PropsWithChildren<{
  title: string | boolean;
}>;

function ContentWrapper({ title, children }: ContentWrapperProps): JSX.Element | null {
  if (children === null || children === undefined) return null;
  if (typeof title === 'string' || title === true) {
    return (
      <Tooltip title={title} placement="top">
        {children as React.ReactElement<any, any>}
      </Tooltip>
    );
  }
  return children as React.ReactElement<any, any>;
}

function ReadonlyField({
  label,
  source,
  defaultValue = '&nbsp;',
  children = <BasicField source={''} defaultValue={undefined} record={undefined} />,
  tooltip: _tooltip,
  ...props
}: ReadonlyFieldProps): JSX.Element {
  const Child = Children.only(children);
  const { getCurrentDialog } = useAppState();
  const record = useRecordContext(props);
  const resource = useResourceContext(props as any);
  // WARN: This is a hack to get the resource from the dialog, but it's not the best way to do it.
  const dialogResource = getCurrentDialog();

  const tooltip = useMemo(() => {
    if (_tooltip === false) return false;
    if (typeof _tooltip === 'function') return _tooltip(record);
    if (typeof _tooltip === 'string') {
      return get(record, _tooltip, _tooltip);
    }
    return _tooltip;
  }, [record, _tooltip]);

  const sx = useSx(props, { width: props?.fullWidth ? '100%' : 'auto' });
  return (
    <ContentWrapper title={tooltip}>
      <>
        <InputLabel sx={{ pt: 1 }}>
          <FieldTitle label={label} source={source} resource={dialogResource || resource} />
        </InputLabel>
        <StyledField {...props}>
          {React.isValidElement(Child)
            ? React.cloneElement(Child, {
                ...Child.props,
                source,
                record,
                defaultValue,
                resource: dialogResource || resource,
                sx
              })
            : null}
        </StyledField>
      </>
    </ContentWrapper>
  );
}

type ReadonlyFieldProps = PropsWithChildren<{
  defaultValue: any;
  tooltip: string | boolean | ((record: any) => string);
  source: string;
  label: string;
  name: string;
  fullWidth?: boolean;
}>;

export { ReadonlyField };
export type { ReadonlyFieldProps };
