import React, {useState} from 'react';

import {ADD_RESPONSE} from './query';
import {GetForm_getForm} from './__generated__/GetForm';
import {AddResponseInput, FieldRef} from '../../__generated__/globalTypes';

import {Button, Input, DatePicker, Radio, Rate, message} from 'antd';
import {PageHeader, Row, Col, Card, Result} from 'antd';
import {Form, Typography} from 'antd';
import {useMutation} from '@apollo/client';
import update from 'immutability-helper';
import NetPromoterScore from './NetPromoterScore';

export function SyForm(props: SyFormProps) {
  const [state, setState] = useState<SyFormState>({
    form: {id: props.data.id},
    entries: props.data.fields.map(field => ({
      field: {
        id: field.id,
      },
    })),
    submitted: false,
  });

  const [form] = Form.useForm();

  const [submit, {loading}] = useMutation(ADD_RESPONSE);

  if (state.submitted) {
    return (
      <Card type="inner">
        <Result
          status="success"
          title="Thank you!"
          subTitle="Your response has been recorded."
        />
      </Card>
    );
  }

  const handleChange = (idx: number) => ({
    DatePicker: (event: any) => {
      const value = event;
      setState(state =>
        update(state, {
          entries: {[idx]: {$merge: {date: value}}},
        })
      );
    },
    Input: (event: any) => {
      const value = event.target.value;
      setState(state =>
        update(state, {
          entries: {[idx]: {$merge: {text: value}}},
        })
      );
    },
    NetPromoterScore: (event: any) => {
      const value = event.target.value;
      setState(state =>
        update(state, {
          entries: {[idx]: {$merge: {netPromoterScore: value}}},
        })
      );
    },
    Radio: (event: any) => {
      const value = event.target.value;
      setState(state =>
        update(state, {
          entries: {[idx]: {$merge: {singleChoice: {id: value}}}},
        })
      );
    },
    Rate: (event: any) => {
      const value = event;
      setState(state =>
        update(state, {
          entries: {[idx]: {$merge: {rating: value}}},
        })
      );
    },
  });

  const createField = (field: FieldRef, idx: number) => {
    switch (field.type) {
      case 'Date':
        return (
          <DatePicker mode="date" onChange={handleChange(idx).DatePicker} />
        );
      case 'NetPromoterScore':
        return (
          <NetPromoterScore onChange={handleChange(idx).NetPromoterScore} />
        );
      case 'Rating':
        return (
          <Rate
            allowClear
            count={field.count!}
            onChange={handleChange(idx).Rate}
          />
        );
      case 'SingleChoice':
        return (
          <Radio.Group onChange={handleChange(idx).Radio}>
            {field.options!.map(option => (
              <Radio
                key={option.id!}
                value={option.id}
                style={{
                  display: 'block',
                  height: '30px',
                  lineHeight: '30px',
                }}
              >
                {option.title}
              </Radio>
            ))}
          </Radio.Group>
        );
      case 'Text':
        return (
          <Input
            placeholder="Write something..."
            onChange={handleChange(idx).Input}
          />
        );
    }
  };

  const createFieldItem = (field: any, idx: number): JSX.Element => (
    <Form.Item
      style={{margin: 0}}
      name={field.id}
      rules={[{required: field.required, message: 'This field is required.'}]}
    >
      {createField(field, idx)}
    </Form.Item>
  );

  async function handleSubmit() {
    await form.validateFields();
    try {
      await submit({
        variables: {
          response: {
            form: state.form,
            entries: state.entries,
          } as AddResponseInput,
        },
      });
      setState(state => update(state, {$merge: {submitted: true}}));
    } catch (e) {
      console.error(e);
      message.error('Internal error: could not submit response');
    }
  }

  const fields = props.data.fields.map((field, idx) => {
    return (
      <Row gutter={[16, 16]} key={field.id}>
        <Col span={24}>
          <Card key={idx} type="inner" style={{borderRadius: '4px'}}>
            <Row gutter={[16, 16]}>
              <Col span={24}>
                <SyTitle title={field.title} required={field.required} />
              </Col>
            </Row>
            <Row gutter={[16, 16]}>
              <Col span={24}>{createFieldItem(field, idx)}</Col>
            </Row>
          </Card>
        </Col>
      </Row>
    );
  });

  const submitButton = (
    <Row gutter={[16, 16]}>
      <Col span={24} style={{textAlign: 'right'}}>
        <Form.Item>
          <Button htmlType="submit" loading={loading} type="primary">
            Submit
          </Button>
        </Form.Item>
      </Col>
    </Row>
  );

  return (
    <PageHeader ghost={true} title={props.data.title}>
      <Form form={form} onFinish={handleSubmit}>
        {fields}
        {submitButton}
      </Form>
    </PageHeader>
  );
}

type SyFormProps = {
  data: GetForm_getForm;
};

type SyFormState = {
  form: {id: string};
  entries: any[];
  submitted: boolean;
};

function SyTitle(props: SyTitleProps) {
  return (
    <Typography.Text style={{margin: 0, color: 'black', fontSize: '16px'}}>
      {props.title}
      {props.required ? <span style={{color: 'red'}}> *</span> : null}
    </Typography.Text>
  );
}

type SyTitleProps = {
  title: string;
  required: boolean;
};