import { compose } from 'redux';
import { connect } from 'react-redux';
import {
  change,
  Field,
  FieldArray,
  formValueSelector,
  reduxForm,
  reset,
  SubmissionError
} from 'redux-form';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import Alert from 'react-bootstrap/Alert';
import Col from 'react-bootstrap/Col';
import { useToasts } from 'react-toast-notifications';
import FormEditor from '../shared/forms/editor';
import FormSelect from '../shared/forms/select';
import FormOptions from './options';
import Segment from '../shared/segment';
import { createCard } from '../../redux/actions/card';
import FormCheckbox from '../shared/forms/checkbox';

function CardForm(props) {
  const { handleSubmit, pristine, submitting, error } = props;
  const { addToast } = useToasts();

  return (
    <Segment>
      {/* form error */}
      {error && !pristine && (
        <Alert variant='danger' className='text-center'>
          {error}
        </Alert>
      )}

      {/* form */}
      <Form noValidate onSubmit={handleSubmit(submit.bind(null, props, addToast))}>
        <Form.Row>
          <Col sm={6} className='my-1'>
            <Field
              required
              horizontal
              name='lesson'
              label='درس'
              component={FormSelect}
              options={props.lessons.map(({ id, name }) => ({ key: id, text: name, value: id }))}
            />
          </Col>
          <Col sm={6} className='my-1'>
            <Field
              required
              horizontal
              name='chapter'
              label='فصل'
              component={FormSelect}
              options={props.chapters.map(({ id, name }) => ({ key: id, text: name, value: id }))}
            />
          </Col>
        </Form.Row>

        <Field name='starred' label='ستاره دار' component={FormCheckbox} />
        <Field required name='question' label='متن سوال' component={FormEditor} />
        <Field required name='answer' label='جواب' component={FormEditor} />
        <FieldArray name='options' component={FormOptions} />
        <Button type='submit' disabled={pristine || submitting} className='float-right'>
          ایجاد فلش کارت
        </Button>
      </Form>
    </Segment>
  );
}

async function submit(props, addToast, values) {
  try {
    await props.createCard(values);
    addToast('فلش کارت شما با موفقیت ساخته شد.', { appearance: 'success' });
    await props.reset('create-card');
    await props.change('lesson', values.lesson);
    await props.change('chapter', values.chapter);
    window.scrollTo({ top: 0, behavior: 'smooth' });
  } catch (error) {
    const errorMessage = error.message;
    throw new SubmissionError({ _error: errorMessage });
  }
}

function validate(values) {
  const { lesson, chapter, question, answer, options } = values;
  const errors = {};
  if (!lesson) errors.lesson = 'وارد کردن درس لازم است.';
  if (!chapter) errors.chapter = 'وارد کردن فصل لازم است.';
  if (!question || !question.trim()) errors.question = 'وارد کردن متن سوال لازم است.';
  if (!answer || !answer.trim()) errors.answer = 'وارد کردن جواب سوال لازم است.';

  function addOptionError(errorMessage) {
    if (!('options' in errors)) errors.options = { _error: [] };
    errors.options._error.push(errorMessage);
  }

  if (!options || options.length < 2) {
    addOptionError('حداقل دو گزینه لازم است.');
    addOptionError('یک گزینه درست لازم است.');
  }

  if (options) {
    const correctOptionCount = options.reduce((count, { isCorrect }) => count + +isCorrect, 0);
    if (correctOptionCount === 0) addOptionError('یک گزینه درست لازم است.');
    if (correctOptionCount > 1) addOptionError('تعداد گزینه درست بیشتر از یک مورد است.');
    if (checkDuplicateOption(options)) addOptionError('گزینه تکراری مجاز نیست.');

    if (
      question &&
      answer &&
      (question === answer ||
        question.replaceAll('&nbsp;', '').replaceAll(' ', '') ===
          answer.replaceAll('&nbsp;', '').replaceAll(' ', ''))
    ) {
      if (!options.some(({ text }) => ['صحیح', 'درست', 'بلی'].includes(text))) {
        errors._error =
          'سوال و جواب (بدون یکی از گزینه های "بلی"، "درست" یا "صحیح") نمی‌توانند یکسان باشند.';
      }
    }
    for (let i = 0; i < options.length; i++) {
      const option = options[i];
      if (!option.text || !option.text.trim()) {
        if (!('options' in errors)) errors.options = {};
        errors.options[i] = { text: 'متن گزینه نمی‌نواند خالی باشد.' };
      }
    }
  }
  return errors;
}

function checkDuplicateOption(options) {
  const optionTextSet = new Set();
  for (let i = 0; i < options.length; i++) {
    const optionText = options[i].text.trim();
    if (!optionText) continue;
    if (optionTextSet.has(optionText)) return true;
    optionTextSet.add(optionText);
  }
  return false;
}

function mapStateToProps(state, { lessons }) {
  let chapters = [];
  const selector = formValueSelector('create-card');
  const selectedLessonId = selector(state, 'lesson');
  if (selectedLessonId) {
    const selectedLesson = lessons.find(lesson => lesson.id.toString() === selectedLessonId);
    chapters = selectedLesson.chapters;
  }
  const initialValues = {
    options: [
      { text: '', isCorrect: false, weight: 100 },
      { text: '', isCorrect: false, weight: 100 }
    ]
  };
  return { chapters, initialValues };
}

export default compose(
  connect(mapStateToProps, { change, reset, createCard }),
  reduxForm({ form: 'create-card', validate })
)(CardForm);
