/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import { FC, useState, useEffect } from 'react';
import { Modal, Button, Form } from 'react-bootstrap';
import { useTranslation } from 'react-i18next';

import classNames from 'classnames';

import { putFlagReviewAction } from '@/services';
import { usePageUsers } from '@/hooks';
import { useCaptchaPlugin } from '@/utils/pluginKit';
import { Editor, TagSelector, Mentions, TextArea } from '@/components';
import {
  // matchedUsers,
  parseUserInfo,
  handleFormError,
  parseEditMentionUser,
  scrollToElementTop,
} from '@/utils';
import type * as Type from '@/common/interface';

import './index.scss';

interface Props {
  originalData: {
    id: string;
    flag_id: string;
    question_id?: string;
    answer_id?: string;
    title: string;
    content: string;
    tags: Type.Tag[];
  };
  objectType: Type.FlagReviewItem['object_type'] | '';
  visible: boolean;
  handleClose: () => void;
  callback?: () => void;
}

interface FormDataItem {
  title: Type.FormValue<string>;
  tags: Type.FormValue<Type.Tag[]>;
  content: Type.FormValue<string>;
}

const initFormData = {
  title: {
    value: '',
    isInvalid: false,
    errorMsg: '',
  },
  tags: {
    value: [],
    isInvalid: false,
    errorMsg: '',
  },
  content: {
    value: '',
    isInvalid: false,
    errorMsg: '',
  },
};

const Index: FC<Props> = ({
  originalData,
  visible = false,
  objectType,
  handleClose,
  callback,
}) => {
  const { t } = useTranslation('translation', { keyPrefix: 'ask' });
  const [formData, setFormData] = useState<FormDataItem>(initFormData);
  const [focusEditor, setFocusEditor] = useState(false);
  const [loaded, setLoaded] = useState(false);
  const pageUsers = usePageUsers();

  const editCaptcha = useCaptchaPlugin('edit');

  const onClose = (bol) => {
    if (bol) {
      callback?.();
    }
    setFormData(initFormData);
    handleClose();
    setLoaded(false);
  };

  const handleInput = (data: Partial<FormDataItem>) => {
    if (!loaded) {
      return;
    }
    setFormData({
      ...formData,
      ...data,
    });
  };

  const checkValidated = (): boolean => {
    let bol = true;
    const { title, tags, content } = formData;
    if (objectType === 'question') {
      if (!title.value) {
        bol = false;
        formData.title = {
          value: title.value,
          isInvalid: true,
          errorMsg: t('form.fields.title.msg.empty', {
            keyPrefix: 'ask',
          }),
        };
      }

      if (!tags.value.length) {
        bol = false;
        formData.tags = {
          value: tags.value,
          isInvalid: true,
          errorMsg: t('form.fields.tags.msg.empty', {
            keyPrefix: 'ask',
          }),
        };
      }
    }

    if (!content.value || Array.from(content.value.trim()).length < 6) {
      bol = false;
      formData.content = {
        value: content.value,
        isInvalid: true,
        errorMsg: t('form.fields.answer.feedback.characters', {
          keyPrefix: 'edit_answer',
        }),
      };
    } else {
      formData.content = {
        value: content.value,
        isInvalid: false,
        errorMsg: '',
      };
    }

    setFormData({
      ...formData,
    });

    if (!bol) {
      const errObj = Object.keys(formData).filter(
        (key) => formData[key].isInvalid,
      );
      const ele = document.getElementById(errObj[0]);
      scrollToElementTop(ele);
    }

    return bol;
  };

  const submitFlagReviewAction = () => {
    const params: Type.PutFlagReviewParams = {
      title: formData.title.value,
      content: formData.content.value,
      tags: formData.tags.value,
      operation_type: 'edit_post',
      flag_id: originalData.flag_id,
    };
    if (objectType === 'answer') {
      delete params.title;
      delete params.tags;
    }
    if (objectType === 'comment') {
      const { value } = formData.content;
      // const users = matchedUsers(value);
      // const userNames = unionBy(users.map((user) => user.userName));
      const commentMarkDown = parseUserInfo(value);

      // params.mention_username_list = userNames;
      params.content = commentMarkDown;

      delete params.title;
      delete params.tags;
    }
    if (objectType === 'question') {
      const imgCode = editCaptcha?.getCaptcha();
      if (imgCode?.verify) {
        params.captcha_code = imgCode.captcha_code;
        params.captcha_id = imgCode.captcha_id;
      }
    }
    putFlagReviewAction(params)
      .then(async () => {
        await editCaptcha?.close();
        onClose(true);
      })
      .catch((err) => {
        if (err.isError) {
          editCaptcha?.handleCaptchaError(err.list);
          const data = handleFormError(err, formData);
          setFormData({ ...data });

          const ele = document.getElementById(err.list[0].error_field);
          scrollToElementTop(ele);
        }
      });
  };

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    event.stopPropagation();

    if (!checkValidated()) {
      return;
    }

    if (!editCaptcha) {
      submitFlagReviewAction();
      return;
    }

    editCaptcha.check(() => submitFlagReviewAction());
  };

  const handleSelected = (val) => {
    if (!loaded) {
      return;
    }
    setFormData({
      ...formData,
      content: {
        value: val,
        errorMsg: '',
        isInvalid: false,
      },
    });
  };

  useEffect(() => {
    if (!visible) {
      return;
    }

    formData.title.value = originalData.title;
    formData.content.value = originalData.content;
    formData.tags.value = originalData.tags.map((item) => {
      return {
        ...item,
        parsed_text: '',
        original_text: '',
      };
    });
    setFormData({ ...formData });
    setLoaded(true);
  }, [visible]);

  return (
    <Modal
      show={visible}
      onHide={() => onClose(false)}
      className="w-100"
      dialogClassName="edit-post-modal">
      <Modal.Header closeButton>
        <Modal.Title>
          {t('edit_post', { keyPrefix: 'page_review' })}
        </Modal.Title>
      </Modal.Header>
      <Form noValidate onSubmit={handleSubmit}>
        <Modal.Body>
          {objectType === 'question' && (
            <Form.Group controlId="title" className="mb-3">
              <Form.Label>{t('form.fields.title.label')}</Form.Label>
              <Form.Control
                type="text"
                value={formData.title.value}
                isInvalid={formData.title.isInvalid}
                onChange={(e) => {
                  handleInput({
                    title: {
                      value: e.target.value,
                      isInvalid: false,
                      errorMsg: '',
                    },
                  });
                }}
                placeholder={t('form.fields.title.placeholder')}
                autoFocus
                contentEditable
              />

              <Form.Control.Feedback type="invalid">
                {formData.title.errorMsg}
              </Form.Control.Feedback>
            </Form.Group>
          )}

          {objectType !== 'comment' && (
            <Form.Group controlId="body">
              <Form.Label>
                {objectType === 'question'
                  ? t('form.fields.body.label')
                  : t('form.fields.answer.label')}
              </Form.Label>
              <Form.Control
                defaultValue={formData.content.value}
                isInvalid={formData.content.isInvalid}
                hidden
              />
              <Editor
                value={formData.content.value}
                onChange={(value) => {
                  handleInput({
                    content: { value, errorMsg: '', isInvalid: false },
                  });
                }}
                className={classNames(
                  'form-control p-0',
                  focusEditor ? 'focus' : '',
                )}
                onFocus={() => {
                  setFocusEditor(true);
                }}
                onBlur={() => {
                  setFocusEditor(false);
                }}
              />
              <Form.Control.Feedback type="invalid">
                {formData.content.errorMsg}
              </Form.Control.Feedback>
            </Form.Group>
          )}

          {objectType === 'question' && (
            <Form.Group controlId="tags" className="my-3">
              <Form.Label>{t('form.fields.tags.label')}</Form.Label>
              <TagSelector
                value={formData.tags.value}
                onChange={(value) => {
                  handleInput({
                    tags: { value, errorMsg: '', isInvalid: false },
                  });
                }}
                showRequiredTag
                maxTagLength={5}
                isInvalid={formData.tags.isInvalid}
                errMsg={formData.tags.errorMsg}
              />
            </Form.Group>
          )}

          {objectType === 'comment' && (
            <div className="w-100">
              <div
                className={classNames('custom-form-control', {
                  'is-invalid': formData.content.isInvalid,
                })}>
                <Form.Label>Comment</Form.Label>
                <Mentions
                  pageUsers={pageUsers.getUsers()}
                  onSelected={handleSelected}>
                  <TextArea
                    size="sm"
                    rows={4}
                    value={parseEditMentionUser(formData.content.value)}
                    onChange={(e) => {
                      handleInput({
                        content: {
                          value: e.target.value,
                          errorMsg: '',
                          isInvalid: false,
                        },
                      });
                    }}
                  />
                </Mentions>
              </div>
              <Form.Control.Feedback type="invalid">
                {formData.content.errorMsg}
              </Form.Control.Feedback>
            </div>
          )}
        </Modal.Body>
        <Modal.Footer>
          <Button variant="secondary" onClick={() => onClose(false)}>
            {t('close', { keyPrefix: 'btns' })}
          </Button>
          <Button variant="primary" type="submit">
            {t('submit', { keyPrefix: 'btns' })}
          </Button>
        </Modal.Footer>
      </Form>
    </Modal>
  );
};

export default Index;
