import {
  Icon,
  Input,
  Switch,
  TextArea,
  Typography,
  DropdownCalendar,
  DropdownTimeSelector,
  InlineMessage,
  TimezoneSelect
} from '@komi-app/components'
import When from '@komi-app/when'

import { Button } from 'antd'
import ImageUpload from 'components/ImageUpload'
import usePatchableState from 'hooks/usePatchableState'
import React, { useEffect, useMemo, useState } from 'react'
import * as yup from 'yup'
import StepLayout from './StepLayout'
import FormSectionLayout from './FormSectionLayout'
import { dcaMetadataStepSchema, DCAFormStepsProps } from './schemas'
import classNames from 'classnames'
import { addingHttpsPrefix } from 'utils/string'
import { ModuleType } from '@komi-app/shared-types'
import { useFeatureIsOn, FLAGS } from '@komi-app/flags-sdk'

type FormState<TValues> = {
  values: TValues
  patchValues: (patch: Partial<TValues>) => void
  touched: Record<keyof TValues, boolean>
  patchTouched: (patch: Partial<Record<keyof TValues, boolean>>) => void
  errors: Partial<Record<keyof TValues, string>>
}

export interface DcaMetadataStepProps {
  initialValues: DCAFormStepsProps
  onChange: (values: DCAFormStepsProps) => void
  Preview: React.ReactNode
  onCancel: () => void
  onSubmit: () => void
}

function getYupErrors<FormValues>(
  values: FormValues
): Partial<Record<keyof FormValues, string>> {
  try {
    dcaMetadataStepSchema.validateSync(values, { abortEarly: false })
    return {}
  } catch (err) {
    if (err instanceof yup.ValidationError) {
      const errors = Object.fromEntries(err.inner.map(e => [e.path, e.message]))
      return errors
    } else {
      throw err
    }
  }
}

const DcaMetadataStep = ({
  initialValues,
  onChange,
  Preview,
  onCancel,
  onSubmit
}: DcaMetadataStepProps) => {
  const [touched, patchTouched, setTouched] = usePatchableState<
    Record<keyof DCAFormStepsProps, boolean>
  >({
    type: false,
    secretLink: false,
    secretCode: false,
    imagePath: false,
    isImageVisible: false,
    title: false,
    subtitle: false,
    countdownExpiry: false,
    showCountdown: false,
    countdownExpiryPlainDate: false,
    countdownExpiryPlainTime: false,
    countdownExpiryTimezone: false,
    contactMethods: false,
    additionalContactMethods: false,
    talentName: false
  })
  const [values, setValues] = useState(initialValues)

  function patchValues(patch: Partial<DCAFormStepsProps>) {
    const newValues = { ...values, ...patch }
    setValues(newValues)
    onChange(newValues)
  }

  const errors = useMemo(() => getYupErrors(values), [values])
  useEffect(() => {
    //Prepend "https://" to link if applicable
    const updatedURL = addingHttpsPrefix(values.secretLink)
    setValues({ ...values, secretLink: updatedURL })
  }, [values.secretLink])

  const form: FormState<DCAFormStepsProps> = {
    values,
    patchValues,
    touched,
    patchTouched,
    errors
  }
  return (
    <StepLayout
      Preview={Preview}
      Controls={
        <>
          <Button
            className="ant-btn-sm ant-btn-uppercase"
            data-testid="previous-button"
            onClick={onCancel}
          >
            Cancel
          </Button>
          <Button
            className="ant-btn-sm ant-btn-uppercase"
            data-testid="next-button"
            type="primary"
            onClick={() => {
              setTouched({
                title: true,
                subtitle: true,
                secretLink: true,
                secretCode: true,
                isImageVisible: true,
                imagePath: true,
                countdownExpiryPlainDate: true,
                countdownExpiryPlainTime: true,
                countdownExpiryTimezone: true,
                showCountdown: true,
                type: true,
                countdownExpiry: true,
                contactMethods: false,
                additionalContactMethods: false,
                talentName: false
              })
              if (dcaMetadataStepSchema.isValidSync(values)) {
                onSubmit()
              }
            }}
          >
            Next
          </Button>
        </>
      }
      Form={
        <div className="step-1">
          <FormSectionLayout
            label="Image"
            disabled={!values.isImageVisible}
            switchComponent={
              <SwitchField
                label="Image toggle"
                form={form}
                name="isImageVisible"
              />
            }
          >
            {({ disabled }) => (
              <div
                className={classNames('image-upload', {
                  'image-upload--disabled': disabled
                })}
              >
                <ImageUpload
                  className="image-upload-dropzone"
                  photo={{
                    url: values.imagePath ?? undefined
                  }}
                  onUploadSuccess={e => {
                    if (typeof e.url === 'string') {
                      patchValues({ imagePath: e.url })
                    }
                  }}
                  onRemove={() => patchValues({ imagePath: undefined })}
                  dropAspect={564 / 564}
                  hideUpdate={false}
                  content={
                    <div>
                      <div className="height--32 flex-center">
                        <Icon name="addFilled" fill="#257ffc" />
                      </div>
                    </div>
                  }
                />
                <div className="image-upload-label">
                  <Typography.Heading level={5}>Image</Typography.Heading>
                  <Typography.Body level={1} color="gray-700">
                    Use a size that&rsquo;s at least 360 x 360 pixels and 6Mb or
                    less
                  </Typography.Body>
                  {touched.imagePath && errors.imagePath && (
                    <Typography.Body
                      level={2}
                      color="feedback-error"
                      data-testid="image-upload-error"
                    >
                      {errors.imagePath}
                    </Typography.Body>
                  )}
                </div>
              </div>
            )}
          </FormSectionLayout>

          <FormSectionLayout label="Content">
            <TextField
              label="Title"
              placeholder="E.g. “Subscribe to get my latest updates”"
              form={form}
              name="title"
            />
            {values.type === ModuleType.DATA_CAPTURE_SIGNUP && (
              <TextField
                label="Description (optional)"
                placeholder="E.g. “Receive news, announcement and much more”"
                form={form}
                name="subtitle"
                as={TextArea}
              />
            )}
            {values.type === ModuleType.DATA_CAPTURE_COUPON_CODE && (
              <TextField
                label={'Secret Code'}
                placeholder={'Enter your code'}
                form={form}
                name="secretCode"
              />
            )}

            <React.Fragment>
              <When
                value={values.type === ModuleType.DATA_CAPTURE_SECRET_LINK}
                then={
                  <TextField
                    label={'Secret Link'}
                    placeholder={'Enter your link'}
                    form={form}
                    name="secretLink"
                  />
                }
              />
              <When
                value={values.type === ModuleType.DATA_CAPTURE_COUPON_CODE}
                then={
                  <TextField
                    label={'Code Redemption Link (optional)'}
                    placeholder={'Enter your link to redeem your code'}
                    form={form}
                    name="secretLink"
                  />
                }
              />
            </React.Fragment>
          </FormSectionLayout>

          {values.type !== ModuleType.DATA_CAPTURE_SIGNUP && (
            <FormSectionLayout
              label="Countdown"
              disabled={!form.values.showCountdown}
              switchComponent={
                <SwitchField
                  label="Countdown toggle"
                  form={form}
                  name="showCountdown"
                />
              }
            >
              {({ disabled }) => (
                <>
                  <InlineMessage
                    closeable
                    type="info"
                    message={
                      'This module will be automatically hidden when the countdown ends.'
                    }
                  />
                  <div className="date-time-fields-wrapper">
                    <DropdownCalendar
                      minDate={Date.now()}
                      label="Select a date"
                      placeholder="Select a date"
                      disabled={disabled}
                      error={
                        touched['countdownExpiryPlainDate']
                          ? errors['countdownExpiryPlainDate'] || ''
                          : ''
                      }
                      value={values.countdownExpiryPlainDate}
                      onValueChange={v => {
                        patchTouched({ countdownExpiryPlainDate: true })
                        patchValues({ countdownExpiryPlainDate: v })
                      }}
                    />
                    <DropdownTimeSelector
                      label="Select time"
                      placeholder="Select time"
                      disabled={disabled}
                      value={values.countdownExpiryPlainTime}
                      error={
                        touched['countdownExpiryPlainTime']
                          ? errors['countdownExpiryPlainTime'] || ''
                          : ''
                      }
                      onValueChange={v => {
                        patchTouched({ countdownExpiryPlainTime: true })
                        patchValues({ countdownExpiryPlainTime: v })
                      }}
                    />
                  </div>
                  <div>
                    <TimezoneSelect
                      initialValue={values.countdownExpiryTimezone}
                      handleSelect={v => {
                        patchTouched({ countdownExpiryTimezone: true })
                        patchValues({ countdownExpiryTimezone: v.primaryName })
                      }}
                    />
                  </div>
                </>
              )}
            </FormSectionLayout>
          )}
        </div>
      }
    />
  )
}

type FilterByType<T, V> = keyof {
  [P in keyof T as T[P] extends V ? P : never]: P
}
function TextField({
  label,
  placeholder,
  form: { values, patchValues, touched, patchTouched, errors },
  name,
  as = Input
}: {
  label: string
  placeholder: string
  form: FormState<DCAFormStepsProps>
  name: FilterByType<DCAFormStepsProps, string>
  as?: typeof Input | typeof TextArea
}) {
  const Component = as
  return (
    <Component
      label={label}
      placeholder={placeholder}
      value={values[name]}
      onValueChange={v => patchValues({ [name]: v })}
      onBlur={() => patchTouched({ [name]: true })}
      error={touched[name] ? errors[name] || '' : ''}
      rows={4}
    ></Component>
  )
}
function SwitchField({
  label,
  form: { values, patchValues, patchTouched },
  name
}: {
  label: string
  form: FormState<DCAFormStepsProps>
  name: FilterByType<DCAFormStepsProps, boolean>
}) {
  return (
    <Switch
      aria-label={label}
      checked={values[name]}
      onCheckedChange={v => {
        patchValues({ [name]: v })
        patchTouched({ [name]: true })
      }}
    />
  )
}

export default DcaMetadataStep
