/**
 * @format
 */
import {
  Button,
  FormLabel,
  Input,
  Select,
  Box,
  FormControl,
  HStack,
  InputGroup,
  InputRightAddon,
  Heading,
  InputLeftAddon,
  Text,
  Flex
} from '@chakra-ui/react'
import {AnyFunction} from '@chakra-ui/utils'
import React, {ReactNode, useEffect, useRef, useState} from 'react'
import {FormInputDataIntf, KeyValue, SelectBoxDataIntf} from '../types/types'
import {
  getPseudoRandomId,
  removeLetters,
  removeLettersLeaveDots,
  sqmToSqft
} from '../common/utils'

export interface ButtonWithIconProps {
  /**
   * Is this the principal call to action on the page?
   */
  variant?: 'primary' | 'outline' | 'menu' | 'ghost'

  /**
   * How large should the button be?
   */
  size?: 'xs' | 'sm' | 'md' | 'lg'

  /**
   * Show loading icon
   */
  isLoading?: boolean

  /**
   * Makes the button enabled or disabled
   */
  isDisabled?: boolean

  /**
   * Optional click handler
   */
  clickHandler?: () => void

  /**
   * The icon object. This can be an image element or SVG element of type HTMLOrSVGImageElement
   */
  icon: React.ReactElement<HTMLOrSVGImageElement>

  /**
   * Position of the icon with respect to the text
   */
  iconPosition?: 'left' | 'right'
  /**
   * Any other chakra prop for the button
   */
  props?: KeyValue
  children: ReactNode
}
interface ButtonProps {
  /**
   * Is this the principal call to action on the page?
   */
  variant?: 'primary' | 'outline' | 'menu' | 'ghost'

  /**
   * How large should the button be?
   */
  size?: 'xs' | 'sm' | 'md' | 'lg'

  /**
   * Show loading icon
   */
  isLoading?: boolean

  /**
   * Makes the button enabled or disabled
   */
  isDisabled?: boolean

  /**
   * Optional click handler
   */
  clickHandler?: () => void

  /**
   * Any other chakra prop for the button
   */
  props?: KeyValue

  /**
   * Content of the button
   */
  children: ReactNode
}
export const PGButton = ({
  variant = 'outline',
  children,
  size = 'md',
  clickHandler,
  isLoading = false,
  isDisabled = false,
  props
}: ButtonProps) => (
  <Button
    size={size}
    isLoading={isLoading}
    isDisabled={isDisabled}
    onClick={clickHandler}
    variant={variant}
    {...props}
  >
    {children}
  </Button>
)

export const ButtonWithIcon = ({
  iconPosition = 'left',
  icon,
  variant,
  children,
  clickHandler,
  isLoading = false,
  isDisabled = false,
  size = 'md',
  props
}: ButtonWithIconProps) => (
  <Button
    isLoading={isLoading}
    isDisabled={isDisabled}
    onClick={clickHandler}
    leftIcon={iconPosition === 'left' ? icon : <></>}
    rightIcon={iconPosition === 'right' ? icon : <></>}
    variant={variant}
    size={size}
    {...props}
  >
    {children}
  </Button>
)
export const TextBox = ({
  value,
  props,
  changeHandler
}: {
  value: string
  props: FormInputDataIntf
  changeHandler: any
  isNumber?: boolean
}) => {
  const id = getPseudoRandomId()

  return (
    <FormControl isRequired={props.htmlValidations?.required}>
      {props.title && <FormLabel htmlFor={id}>{props.title}</FormLabel>}
      <Input
        id={id}
        name={props.name}
        value={value}
        placeholder={props.placeholder || ''}
        onChange={changeHandler}
      />
    </FormControl>
  )
}

export const CurrencyBox = ({
  value,
  props,
  changeHandler
}: {
  value: string
  props: FormInputDataIntf
  changeHandler: any
}) => {
  const id = getPseudoRandomId()

  return (
    <FormControl isRequired={props.htmlValidations?.required}>
      {props.title && <FormLabel htmlFor={id}>{props.title}</FormLabel>}
      <InputGroup>
        <InputLeftAddon children={props.currencySymbol} />
        <Input
          id={id}
          name={props.name}
          value={value}
          placeholder={props.placeholder || ''}
          onChange={changeHandler}
        />
      </InputGroup>
    </FormControl>
  )
}
export const LandArea = ({
  sqftValue,
  sqmValue,
  props,
  changeHandler
}: {
  sqftValue: string
  sqmValue: string
  props: FormInputDataIntf
  changeHandler: any
}) => {
  const id = getPseudoRandomId()
  type supportedLandAreaTypes = 'sqft' | 'sqm' | undefined
  const [currentUnit, setCurrenUnit] = useState<supportedLandAreaTypes>(
    props.defaultLandAreaType
  )
  const sqftRef = useRef<any>(null)
  const sqmRef = useRef<any>(null)

  return (
    <FormControl isRequired={props.htmlValidations?.required}>
      {props.title && <FormLabel htmlFor={id}>{props.title}</FormLabel>}
      <InputGroup key={props.name}>
        {currentUnit === 'sqft' && (
          <Input
            key={`sqft_${props.name}`}
            id={`${id}_sqft`}
            ref={sqftRef}
            name={`${props.name}_sqft`}
            value={
              currentUnit === 'sqft'
                ? sqftValue
                : sqmToSqft(parseInt(sqmValue, 10))
            }
            placeholder={props.placeholder || ''}
            onChange={(e: React.FormEvent<EventTarget>) => {
              changeHandler(e)
            }}
          />
        )}
        {currentUnit === 'sqm' && (
          <Input
            id={`${id}_sqm`}
            key={`sqm_${props.name}`}
            ref={sqmRef}
            name={`${props.name}_sqm`}
            value={currentUnit === 'sqm' ? sqmValue : ''}
            placeholder={props.placeholder || ''}
            onChange={(e: React.FormEvent<EventTarget>) => {
              changeHandler(e)
            }}
          />
        )}

        <InputRightAddon
          onClick={() => {
            setCurrenUnit(currentUnit === 'sqft' ? 'sqm' : 'sqft')
          }}
          children={currentUnit}
        />
      </InputGroup>
    </FormControl>
  )
}
export const SelectBox = ({
  props,
  changeHandler
}: {
  props: FormInputDataIntf
  changeHandler: any
}) => {
  const id = getPseudoRandomId()

  return (
    <Box mt={4}>
      {props.title !== null && (
        <FormLabel htmlFor={id}>{props.title}</FormLabel>
      )}
      <Select
        width={['100%', '100%', '100%', '100% !important']}
        mx={0}
        fontSize={'16px !important'}
        id={id}
        name={props.name}
        placeholder={props.placeholder || ''}
        onChange={changeHandler}
      >
        {props.selectData &&
          props.selectData.map((obj: SelectBoxDataIntf) => (
            <option key={obj.key} value={obj.key}>
              {obj.value}
            </option>
          ))}
      </Select>
    </Box>
  )
}
export const FormComponent = ({
  inputData,
  submitHandler,
  cancelHandler
}: // formState
{
  inputData: Array<FormInputDataIntf>
  submitHandler: AnyFunction
  cancelHandler?: AnyFunction
  // formState: KeyValue
}) => {
  const [formData, setFormData] = useState<any>([])

  const addNormalFormData = (obj: FormInputDataIntf) => {
    const appendValue: any = []

    if (
      obj.type !== 'submit' &&
      obj.type !== 'cancel' &&
      obj.type !== 'heading'
    ) {
      if (obj.type === 'area') {
        appendValue[`${obj.name}_sqft`] = ''
        appendValue[`${obj.name}_sqm`] = ''
      } else {
        appendValue[obj.name] = obj.defaultValue || ''
      }
    }

    setFormData((prev: any) => ({
      ...prev,
      ...appendValue
    }))
  }
  useEffect(() => {
    inputData.forEach((obj: any) => {
      if (obj.type !== 'row') {
        addNormalFormData(obj)
      } else if (obj.type === 'row') {
        obj.columns.forEach((col: FormInputDataIntf) => {
          addNormalFormData(col)
        })
      }
    })
  }, [])

  const moreFilterFieldsOnChange = (e: React.FormEvent<EventTarget>) => {
    const targetElm = e.target as HTMLInputElement
    const {name, value} = targetElm
    setFormData((prev: any) => ({
      ...prev,
      [name]: value
    }))
  }

  const mapElements = (_obj: FormInputDataIntf, rowObj?: any) => {
    const obj = _obj

    if (rowObj && rowObj.required) {
      if (!obj.htmlValidations) {
        obj.htmlValidations = {required: true}
      }
    }

    const id = `${getPseudoRandomId()}_${_obj.name}`

    return (
      <React.Fragment key={`${id}_fragment`}>
        {obj.type === 'heading' && (
          <Heading variant="size18" mt="30px" {...obj.styleProps}>
            {obj.title}
          </Heading>
        )}
        {obj.type === 'text' && (
          <TextBox
            key={id}
            value={formData[obj.name]}
            {...obj.styleProps}
            props={obj}
            changeHandler={moreFilterFieldsOnChange}
          />
        )}
        {obj.type === 'number' && (
          <TextBox
            key={id}
            value={removeLetters(formData[obj.name])}
            {...obj.styleProps}
            props={obj}
            changeHandler={moreFilterFieldsOnChange}
          />
        )}
        {obj.type === 'currency' && (
          <CurrencyBox
            key={id}
            value={removeLettersLeaveDots(formData[obj.name])}
            {...obj.styleProps}
            props={obj}
            changeHandler={moreFilterFieldsOnChange}
          />
        )}
        {obj.type === 'area' && (
          <LandArea
            key={id}
            sqftValue={removeLettersLeaveDots(formData[`${obj.name}_sqft`])}
            sqmValue={removeLettersLeaveDots(formData[`${obj.name}_sqm`])}
            {...obj.styleProps}
            props={obj}
            changeHandler={moreFilterFieldsOnChange}
          />
        )}
        {obj.type === 'selectBox' && (
          <SelectBox
            changeHandler={moreFilterFieldsOnChange}
            props={obj}
            {...obj.styleProps}
          />
        )}
        {obj.type === 'cancel' && (
          <Button
            {...obj.styleProps}
            minW={['100px', '100px', '100px', '200px', '200px']}
            onClick={() => {
              if (cancelHandler) {
                cancelHandler()
                console.log('cancelClicked')
              }
            }}
          >
            {obj.title}
          </Button>
        )}
        {obj.type === 'submit' && (
          <Button
            {...obj.styleProps}
            variant="primary"
            minW={['100px', '100px', '100px', '200px', '200px']}
            type="submit"
          >
            {obj.title}
          </Button>
        )}
      </React.Fragment>
    )
  }

  return (
    <>
      {Object.keys(formData).length && (
        <form
          onSubmit={(e: React.FormEvent<EventTarget>) => {
            submitHandler(e, formData)
            e.preventDefault()
          }}
        >
          {inputData.map((obj: any) => (
            <Box mt={4} key={`boxHolder_${obj.name || obj.type}`}>
              {/* Single column layout */}
              {obj.type !== 'row' && mapElements(obj)}

              {/* Dual column layout */}
              {obj.type === 'row' && (
                <>
                  <FormLabel>
                    <Flex>
                      {obj.rowTitle}{' '}
                      {obj.required && (
                        <Text color="primary" pl="2">
                          *
                        </Text>
                      )}
                    </Flex>
                  </FormLabel>
                  <HStack spacing={'18px'}>
                    {obj.columns.map((colObj: FormInputDataIntf) =>
                      mapElements(colObj, obj)
                    )}
                  </HStack>
                </>
              )}
            </Box>
          ))}
        </form>
      )}
    </>
  )
}
export const WrapperBox = ({children}: {children: ReactNode}) => (
  <Box p="32px">{children}</Box>
)
