import React, { useCallback, useState } from 'react';
import {
  Button,
  Flex,
  Form,
  Grid,
  Separator,
  Box,
  toast,
  Dialog,
} from '../../atoms';
import { DatePickerButton, TimeSelect } from '../../molecules';
import { getTimeOption, parseTimeOption } from '../../utils';

export interface EditCoachingTimeProps {
  defaultStartAt?: Date;
  defaultEndAt?: Date;
  onClickSave?: (startAt: Date, endAt: Date) => void;
  onClickCancel?: () => void;
  sessionNumber?: number;
}

interface Values {
  startTime: string;
  endTime: string;
  date: Date;
}

const getValueFromDefaultValue = (args: {
  startAt?: Date;
  endAt?: Date;
}): Values => {
  return {
    startTime: args.startAt ? getTimeOption(args.startAt) : '00:00',
    endTime: args.endAt ? getTimeOption(args.endAt) : '00:00',
    date: args.startAt || new Date(),
  };
};

const getDateFromValue = (date: Date, time: string): Date => {
  const { hour, minute } = parseTimeOption(time);
  return new Date(
    date.getFullYear(),
    date.getMonth(),
    date.getDate(),
    hour,
    minute
  );
};

export function EditCoachingTime(
  props: EditCoachingTimeProps
): React.ReactElement {
  const { defaultEndAt, defaultStartAt, onClickCancel } = props;

  const [values, setValues] = useState<Values>(() => {
    return getValueFromDefaultValue({
      startAt: defaultStartAt,
      endAt: defaultEndAt,
    });
  });

  const [timeError, setTimeError] = useState('');

  const checkTimeError = useCallback(
    (startTime: string, endTime: string): boolean => {
      const error =
        startTime >= endTime
          ? '시작시간을 종료시간보다 빠르게 선택해주세요.'
          : '';
      if (error) {
        setTimeError(error);
        return false;
      }
      return true;
    },
    []
  );

  const onChangeStartTime = useCallback(
    (v: string) => {
      checkTimeError(v, values.endTime);
      setValues((prev) => ({
        ...prev,
        startTime: v,
      }));
    },
    [checkTimeError, values.endTime]
  );

  const onChangeEndTime = useCallback(
    (v: string) => {
      checkTimeError(values.startTime, v);
      setValues((prev) => ({
        ...prev,
        endTime: v,
      }));
    },
    [checkTimeError, values.startTime]
  );

  const onChangeDate = useCallback((date: Date | null) => {
    date &&
      setValues((prev) => ({
        ...prev,
        date,
      }));
  }, []);

  const onClickSave = useCallback(() => {
    if (checkTimeError(values.startTime, values.endTime)) {
      const startAt = getDateFromValue(values.date, values.startTime);
      const endAt = getDateFromValue(values.date, values.endTime);
      props.onClickSave && props.onClickSave(startAt, endAt);
    } else {
      toast.error('입력 값이 유효하지 않습니다.');
    }
  }, [checkTimeError, props, values.date, values.endTime, values.startTime]);

  return (
    <Box width={{ initial: '100%' }}>
      <Form.Root>
        <Form.Field name="date">
          <Form.Label variant="caption">날짜</Form.Label>
          <DatePickerButton
            maxDate={new Date()}
            onChange={onChangeDate}
            selected={values.date}
            size={{ initial: 'large', xs: 'medium' }}
          />
        </Form.Field>
        <Grid
          align="center"
          columns={{
            initial: '1fr 0 1fr',
            xs: '1fr auto 1fr',
          }}
          gapX="3"
          gapY="2"
          justify="center"
          mb={{ initial: '5', xs: '4' }}
          mt="5"
          width="100%"
        >
          <Form.Field name="startTime">
            <Form.Label variant="caption">시작 시간</Form.Label>
          </Form.Field>
          <div />
          <Form.Field name="endTime">
            <Form.Label variant="caption">종료 시간</Form.Label>
          </Form.Field>
          <TimeSelect
            onValueChange={onChangeStartTime}
            size={{ initial: '3', xs: '2' }}
            value={values.startTime}
          />
          <Box overflow="hidden">
            <Separator />
          </Box>

          <TimeSelect
            onValueChange={onChangeEndTime}
            size={{ initial: '3', xs: '2' }}
            value={values.endTime}
          />
          <Form.Field name="startEndTime" style={{ gridColumn: '1/span 3' }}>
            <Form.Message forceMatch={Boolean(timeError)}>
              {timeError}
            </Form.Message>
          </Form.Field>
        </Grid>
        <Flex gap="3" justify="end">
          <Dialog.Close>
            <Button onClick={onClickCancel} type="button" variant="outline">
              취소하기
            </Button>
          </Dialog.Close>
          <Dialog.Close>
            <Button onClick={onClickSave} type="button">
              저장하기
            </Button>
          </Dialog.Close>
        </Flex>
      </Form.Root>
    </Box>
  );
}
