import { duration, utc } from "moment";
import React, { Component } from "react";
import DatePicker from "react-datepicker";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";
import {
  Container,
  Dropdown,
  Form,
  Header,
  Label,
  Message,
  TextArea
} from "semantic-ui-react";

import {
  setFormEmployeeUUID,
  setFormPriceUUID,
  setFormShiftStartTime,
  setFormShiftDuration,
  setFormShiftNote,
  setClearCShiftState,
  setFormShiftDates
} from "../../../actions/cShift/reducer.actions";
import { createMultipleCShiftRequest } from "../../../actions/cShift/saga.actions";
import Error from "../../Shared/Error";

import "react-datepicker/dist/react-datepicker.css";
import "./shiftStartTimeOverrides.css";

const CShiftDurationOptions = [];
for (let min = 60; min <= 480; min += 30) {
  let displayText = duration(min, "minutes").humanize();
  if (min % 60) {
    displayText = duration(Math.floor(min / 60), "hours").humanize();
    displayText += ` and ${duration(min % 60, "minutes").humanize()}`;
  }
  CShiftDurationOptions.push({
    key: min,
    value: min,
    text: displayText
  });
}

class ClientAddShiftForm extends Component {
  componentWillMount = () => {
    this.props.dispatch(setClearCShiftState());
  };

  changeSelectedEmployee = (e, { value }) => {
    if (value !== this.props.employeeUUID) {
      this.props.dispatch(setFormPriceUUID(""));
    }
    this.props.dispatch(setFormEmployeeUUID(value));
  };

  changeSelectedPrice = (e, { value }) => {
    this.props.dispatch(setFormPriceUUID(value));
  };

  /**
   * change handler for shift start time selector.
   * @param momentTime - instance of moment (but we only care about the time)
   */
  changeShiftStartTime = momentTime => {
    this.props.dispatch(setFormShiftStartTime(momentTime));
  };

  changeShiftDuration = (e, { value }) => {
    this.props.dispatch(setFormShiftDuration(value));
  };

  changeShiftNote = event => {
    this.props.dispatch(setFormShiftNote(event.target.value));
  };

  /**
   * change handler for shift date selector
   * @param momentDate - instance of moment (but we only care about the day)
   */
  handleSelectDate = momentDate => {
    const shiftDatesCopy = { ...this.props.shiftDates };
    const key = momentDate.format("YYYY-MM-DD");
    if (shiftDatesCopy.hasOwnProperty(key)) {
      delete shiftDatesCopy[key];
    } else {
      shiftDatesCopy[key] = momentDate;
    }
    this.props.dispatch(setFormShiftDates(shiftDatesCopy));
  };

  onSubmitShifts = event => {
    event.preventDefault();
    // change this into interable cshift post request bodies
    const { priceUUID, startTime, duration, note, shiftDates } = this.props;
    const postRequestBodies = [];
    for (let shiftDateString in shiftDates) {
      const dynamicStartTime = utc(startTime);
      const startDate = shiftDates[shiftDateString];
      dynamicStartTime.set({
        year: startDate.get("year"),
        month: startDate.get("month"),
        date: startDate.get("date")
      });
      const dynamicEndTime = utc(dynamicStartTime);
      dynamicEndTime.add(duration, "minutes");
      postRequestBodies.push({
        get_price_uuid: priceUUID,
        set_start: dynamicStartTime.format(),
        set_end: dynamicEndTime.format(),
        description: note ? note : undefined
      });
    }
    this.props.dispatch(createMultipleCShiftRequest(postRequestBodies));
  };

  render() {
    const {
      isSendingCShiftRequest,
      cShiftRequestErrors,
      cShiftRequestSuccess,
      selfUser,
      employeeUUID,
      priceUUID,
      startTime,
      duration,
      note,
      shiftDates
    } = this.props;

    if (!selfUser.client) {
      return <Redirect to="/" />;
    }

    const employeeChoices = selfUser.client.employees
      .filter(employee => !employee.deleted && !!employee.approved)
      .map(({ uuid, provider }) => ({
        key: uuid,
        value: uuid,
        text: provider.email
      }));

    const priceChoices = [];
    if (employeeUUID) {
      const employee = selfUser.client.employees.find(emp => {
        return emp && emp.uuid === employeeUUID;
      });
      priceChoices.push(
        ...employee.prices
          .filter(price => !price.deleted)
          .map(({ amount, uuid, work_type }) => ({
            key: uuid,
            value: uuid,
            text: `${work_type.label} ($${amount}/hr)`,
            content: (
              <Header>
                <Label
                  circular
                  empty
                  style={{
                    backgroundColor: work_type.color,
                    borderColor: work_type.color
                  }}
                />
                {work_type.label}
                <Header.Subheader
                  style={{ paddingLeft: "2em" }}
                  content={`Hourly Rate: ${amount}`}
                />
              </Header>
            )
          }))
      );
    }

    const selectedShiftDates = Object.keys(shiftDates).map(
      key => shiftDates[key]
    );
    return (
      <ClientAddShiftFormView
        isSendingCShiftRequest={isSendingCShiftRequest}
        cShiftRequestErrors={cShiftRequestErrors}
        cShiftRequestSuccess={!!cShiftRequestSuccess.length}
        user={selfUser}
        employeeChoices={employeeChoices}
        priceChoices={priceChoices}
        employeeUUID={employeeUUID}
        priceUUID={priceUUID}
        startTime={startTime}
        duration={duration}
        note={note}
        selectedShiftDates={selectedShiftDates}
        changeSelectedEmployee={this.changeSelectedEmployee}
        changeSelectedPrice={this.changeSelectedPrice}
        changeShiftStartTime={this.changeShiftStartTime}
        changeShiftDuration={this.changeShiftDuration}
        changeShiftNote={this.changeShiftNote}
        handleSelectDate={this.handleSelectDate}
        onSubmitShifts={this.onSubmitShifts}
      />
    );
  }
}

function mapStateToProps(state) {
  return { ...state.cShift, selfUser: state.user.selfUser };
}

const ClientAddShiftFormView = ({
  isSendingCShiftRequest,
  cShiftRequestErrors,
  cShiftRequestSuccess,
  user,
  employeeChoices,
  priceChoices,
  employeeUUID,
  priceUUID,
  startTime,
  duration,
  note,
  selectedShiftDates,
  changeSelectedEmployee,
  changeSelectedPrice,
  changeShiftStartTime,
  changeShiftDuration,
  changeShiftNote,
  handleSelectDate,
  onSubmitShifts
}) => (
  <Container>
    <Header>Schedule Shifts</Header>
    <Form
      loading={isSendingCShiftRequest}
      onSubmit={onSubmitShifts}
      error={!!cShiftRequestErrors.length}
      success={!!cShiftRequestSuccess}
    >
      <Form.Group widths="equal">
        <Form.Field>
          <label>Employee</label>
          <Dropdown
            onChange={changeSelectedEmployee}
            options={employeeChoices}
            placeholder="Select employee"
            selection
            fluid
            search
            noResultsMessage="No approved employees found."
            value={employeeUUID}
          />
        </Form.Field>
        <Form.Field>
          <label>Price</label>
          <Dropdown
            onChange={changeSelectedPrice}
            options={priceChoices}
            placeholder="Select price"
            selection
            fluid
            search
            disabled={!employeeUUID}
            noResultsMessage="No prices for given employee."
            value={priceUUID}
          />
        </Form.Field>
        <Form.Field>
          <label>Shift Start Time</label>
          <DatePicker
            selected={startTime}
            onChange={changeShiftStartTime}
            showTimeSelect
            showTimeSelectOnly
            timeIntervals={30}
            dateFormat="LT Z"
            timeFormat="hh:mm"
            placeholderText="Select shift start time"
          />
        </Form.Field>
        <Form.Field>
          <label>Shift Duration</label>
          <Dropdown
            onChange={changeShiftDuration}
            options={CShiftDurationOptions}
            placeholder="Select duration"
            selection
            fluid
            value={duration}
          />
        </Form.Field>
      </Form.Group>
      <Form.Field>
        <label>Note</label>
        <TextArea
          placeholder="Employee notes"
          value={note}
          onChange={changeShiftNote}
        />
      </Form.Field>
      <Form.Field style={{ textAlign: "center" }}>
        <label>Dates</label>
        <DatePicker
          inline
          onSelect={handleSelectDate}
          highlightDates={selectedShiftDates}
          monthsShown={2}
          // https://github.com/Hacker0x01/react-datepicker/pull/1360
          peekNextMonth={false} // this is broken? Fixed in PR 1360
          minDate={utc(new Date()).add(1, "day")}
          maxDate={utc(new Date())
            .add(1, "month")
            .endOf("month")}
        />
      </Form.Field>
      {!!cShiftRequestErrors.length && (
        <Error header="" error={cShiftRequestErrors[0]} />
      )}
      <Message success>
        <Message.Header>Add Shift successful!</Message.Header>
        <p>Shifts successfully scheduled.</p>
        {!!cShiftRequestSuccess && (
          <Redirect to="/user/profile/client/shifts" />
        )}
      </Message>
      <Form.Button>Schedule Shift</Form.Button>
    </Form>
  </Container>
);

export default connect(mapStateToProps)(ClientAddShiftForm);
