/* @aztlan/generator-front 1.1.4 */
import * as React from 'react'
import {
  useMemo, useEffect, useCallback,
} from 'react'

import * as PropTypes from 'prop-types'
import { InferProps } from 'prop-types'

import {
  useFormContext, useWatch,
} from 'react-hook-form'
import styleNames from '@aztlan/bem'
import {
  Field, useFieldsValidity,
} from '@aztlan/ui'
import { WEEKDAYS } from '../constants.js'
import { useTupleFormatOpeningHours } from '../hooks/index.js'

const baseClassName = styleNames.base
const componentClassName = 'add-item-form'

const fieldNameMap = {
  openDay        :'openDay',
  openHour       :'openHour',
  closesOnSameDay:'closesOnSameDay',
  closeDay       :'closeDay',
  closeHour      :'closeHour',
}

/**
 * description
 * @param {InferProps<typeof AddItemForm.propTypes>} props -
 * @returns {React.ReactElement} - Rendered AddItemForm
 */
function AddItemForm({
  id,
  className: userClassName,
  style,
  name,
  close,
  addOpeningHours,
  spanContentDesktop,
  spanLabelDesktop,
}: // ...otherProps
InferProps<typeof AddItemForm.propTypes>): React.ReactElement {
  const { setValue } = useFormContext()

  const sharedFieldProps = useMemo(
    () => ({
      spanContentDesktop,
      spanLabelDesktop,
    }),
    [
      spanContentDesktop,
      spanLabelDesktop,
    ],
  )

  const fields = useMemo(
    () => [
      {
        name   :`${name}.${fieldNameMap.openDay}`,
        label  :'Opens on',
        type   :'select',
        options:Object.values(WEEKDAYS).map((e) => ({
          value:e,
          label:e,
        })),
      },
      {
        name :`${name}.${fieldNameMap.openHour}`,
        label:'At',
        type :'time',
      },
      {
        name    :`${name}.${fieldNameMap.closesOnSameDay}`,
        label   :'Closes on the same day',
        type    :'checkbox',
        optional:true,
      },
      {
        name   :`${name}.${fieldNameMap.closeDay}`,
        label  :'Closes on',
        type   :'select',
        options:Object.values(WEEKDAYS).map((e) => ({
          value:e,
          label:e,
        })),
        condition:[
          [`${name}.${fieldNameMap.closesOnSameDay}`],
          ([closesOnSameDay]) => closesOnSameDay === false,
        ],
      },
      {
        name :`${name}.${fieldNameMap.closeHour}`,
        label:'At',
        type :'time',
        step :60,
      },
    ],
    [],
  )

  const fieldNames = [
    fieldNameMap.openDay,
    fieldNameMap.openHour,
    fieldNameMap.closeDay,
    fieldNameMap.closeHour,
    fieldNameMap.closesOnSameDay,
  ].map((e) => `${name}.${e}`)

  const fieldValues = useWatch({ name: fieldNames })

  /** Always set the closesOnSameDay to true on form open */
  useEffect(
    () => {
      setValue(
        `${name}.${fieldNameMap.closesOnSameDay}`, true,
      )
    }, [],
  )

  /** Always set the closeDay to the same as the openDay on closesOnSameDay changes */
  useEffect(
    () => {
      if (fieldValues[4]) {
        setValue(
          `${name}.${fieldNameMap.closeDay}`, fieldValues[0],
        )
      }
    }, [
      fieldValues[4],
      fieldValues[0],
    ],
  )

  const preparedData = useTupleFormatOpeningHours({
    openDay  :fieldValues[0],
    openTime :fieldValues[1],
    closeDay :fieldValues[4] ? fieldValues[0] : fieldValues[2],
    closeTime:fieldValues[3],
  })

  const { validateFields } = useFieldsValidity(fields)

  const submitSubformAndClose = useCallback(
    async () => {
      const valid = await validateFields()
      if (valid) {
        addOpeningHours(preparedData)
        close()
      }
    }, [
      addOpeningHours,
      close,
      preparedData,
      validateFields,
    ],
  )

  return (
    <div
      id={id}
      // onSubmit={methods.handleSubmit(onSubmit)}
      className={[
        baseClassName,
        componentClassName,
        userClassName,
        'grid container',
      ]
        .filter((e) => e)
        .join(' ')}
      style={style}
      // {...otherProps}
    >
      {fields.map(({
        name: fieldName, ...fieldProps
      }) => (
        <Field
          key={fieldName}
          name={fieldName}
          unregisterOnUnmount
          {...sharedFieldProps}
          {...fieldProps}
        />
      ))}
      <button
        onClick={submitSubformAndClose}
        type="button"
        aria-label="Add"
        className="span-3"
      >
        Add
      </button>
      <button
        onClick={close}
        type="button"
        aria-label="Close"
        className="span-3"
      >
        Close
      </button>
    </div>
  )
}

AddItemForm.propTypes = {
  /** The HTML id for this element */
  id:PropTypes.string,

  /** The HTML class names for this element */
  className:PropTypes.string,

  /** The React-written, css properties for this element. */
  style:PropTypes.objectOf(PropTypes.string),

  /** The name of the form */
  name:PropTypes.string.isRequired,

  /** The close function */
  close:PropTypes.func.isRequired,

  /** The addOpeningHours function */
  addOpeningHours:PropTypes.func.isRequired,

  /** The spanContentDesktop */
  spanContentDesktop:PropTypes.number.isRequired,

  /** The spanLabelDesktop */
  spanLabelDesktop:PropTypes.number.isRequired,
}

export default AddItemForm
