import { Box, CircularProgress, Typography, alpha, styled } from '@mui/material'
import { ReactNode } from 'react'
import { Control, useController } from 'react-hook-form'
import * as yup from 'yup'
import {
  FormDatePicker,
  FormMultiSelect,
  FormRadioGroup,
  FormSingleCheckbox,
  FormSingleSelect,
  FormTextField,
} from '../HookForm'

export const generateYupSchema = (options: {
  fieldGroups: any[][]
  fieldArrayGroups?: any[]
  extraValidations?: any
}) => {
  const flatArray = options.fieldGroups.flat()

  const validations = flatArray
    ?.filter(
      (item) => item?.required !== undefined || item?.validation !== undefined,
    )
    ?.reduce((acc, curr) => {
      return {
        [curr.name]:
          curr?.validation ??
          yup.string().required(`${curr?.label} is required`),
        ...acc,
      }
    }, {})

  return yup.object().shape({ ...validations, ...options.extraValidations })
}

type FormTypes =
  | 'FormTextField'
  | 'Display'
  | 'FormSingleSelect'
  | 'FormRadioGroup'
  | 'FormDatePicker'
  | 'FormMultiSelect'
  | 'Loader'
  | 'FormSingleCheckbox'

export interface Field {
  render: FormTypes
  name: string
  label?: string
  required?: boolean
  elementProps?: any
  disabled?: boolean
  validation?: any
}

export interface Option {
  label: string | ReactNode
  value: any
}

export interface RenderFormProps {
  fields: Field[]
  dropdowns?: { [x: string]: Option[] }
  control: Control<any, any>
  cols: number
  data?: any
  fieldArrayOptions?: { index: number; name: string }
  gap?: string | number
}

const RenderForm = ({
  fields,
  dropdowns,
  control,
  cols,
  data = null,
  fieldArrayOptions,
  gap = '20px 1rem',
}: RenderFormProps) => {
  return (
    <>
      <Box
        sx={{
          display: 'grid',
          gridTemplateColumns: `repeat(${cols}, 1fr)`,
          gap,
          width: '100%',
        }}
      >
        {fields?.map((item, index) => (
          <RenderFormField
            key={index}
            field={item}
            control={control}
            dropdown={dropdowns ? dropdowns[item?.name] : null}
            elementProps={item?.elementProps}
            value={data ? data[item?.name] : null}
            fieldArrayOptions={fieldArrayOptions}
          />
        ))}
      </Box>
    </>
  )
}
export default RenderForm

interface RenderFormFieldProps {
  field: Field
  control: Control<any, any>
  dropdown: Option[] | null
  elementProps: any
  value: any
  fieldArrayOptions?: { index: number; name: string }
}

const RenderFormField = ({
  field,
  control,
  dropdown,
  elementProps,
  value,
  fieldArrayOptions,
}: RenderFormFieldProps) => {
  const name = fieldArrayOptions?.name
    ? `${fieldArrayOptions?.name}.${fieldArrayOptions?.index}.${field?.name}`
    : field?.name

  const { field: fieldData } = useController({ name: field.name, control })
  switch (field.render) {
    case 'FormTextField':
      return (
        <FormTextField
          control={control}
          name={name}
          label={field?.label}
          required={field?.required}
          disabled={field?.disabled}
          {...elementProps}
        />
      )

    case 'FormSingleSelect':
      return (
        <FormSingleSelect
          options={dropdown}
          control={control}
          name={name}
          label={field?.label}
          required={field?.required}
          disabled={field?.disabled}
          {...elementProps}
        />
      )
    case 'FormDatePicker':
      return (
        <FormDatePicker
          control={control}
          name={name}
          label={field?.label}
          required={field?.required}
          disabled={field?.disabled}
          {...elementProps}
        />
      )
    case 'FormRadioGroup':
      return (
        <FormRadioGroup
          row={true}
          options={dropdown}
          control={control}
          name={name}
          label={field?.label}
          required={field?.required}
          disabled={field?.disabled}
          {...elementProps}
        />
      )
    case 'FormMultiSelect':
      return (
        <FormMultiSelect
          control={control}
          label={field?.label}
          required={field?.required}
          disabled={field?.disabled}
          name={name}
          options={dropdown}
          {...elementProps}
        />
      )

    case 'Display':
      return (
        <Display
          label={field?.label}
          value={fieldData.value}
          disabled={field?.disabled}
        />
      )

    case 'Loader':
      return <CircularProgress />

    case 'FormSingleCheckbox':
      return (
        <FormSingleCheckbox
          control={control}
          label={field?.label}
          required={field?.required}
          disabled={field?.disabled}
          name={name}
          checked={fieldData.value ?? false}
          {...elementProps}
        />
      )

    default:
      return <>{field?.label}</>
  }
}

const Display = ({ label, value, disabled }) => {
  return (
    <Box>
      <Typography variant="subtitle2">{label}</Typography>
      <StyledTypography variant="body1" marginTop={'5px'} disabled={disabled}>
        {value ?? '-'}
      </StyledTypography>
    </Box>
  )
}

const StyledTypography = styled(Typography, {
  shouldForwardProp(propName) {
    return propName !== 'disabled'
  },
})<{ disabled: boolean }>(({ theme, disabled }) => ({
  color: disabled
    ? alpha(theme.palette.secondary.main, 0.4)
    : theme.palette.secondary.main,
}))
