import {useState, MouseEvent} from "react"
import {Button} from "../../atoms"
import {CustomWheel} from "../../molecules"
import {DatePickerProps, CustomWheelType} from "../../props"
import styles from "./styles.module.sass"

const MINUTES = Array.from({length: 60}, (_, i) => `${i + 1}`.padStart(2, "0"))
const HOURS = Array.from({length: 12}, (_, i) => `${i + 1}`.padStart(2, "0"))
const MERIDIANS = ["AM", "PM"]
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "July", "Aug", "Sept", "Oct", "Nov", "Dec"]

export const DateTimePicker = ({maxDate, minDate, selDate, type, onSelectDate, onCancel}: DatePickerProps) => {
  const startDate = minDate || new Date()
  selDate = selDate || startDate
  const endDate = maxDate || new Date(startDate.getFullYear() + 1, startDate.getMonth(), startDate.getDate())

  const noOfYears = endDate.getFullYear() - startDate.getFullYear() + 1
  const YEARS = new Array(noOfYears).fill(startDate.getFullYear()).map((value, index) => value + index)
  const [currentDate, setCurrentDate] = useState(selDate)
  const [date, setDate] = useState(selDate)

  const onDateChange = (type: CustomWheelType, position: number) => {
    let newDate: Date | undefined = undefined

    if (type === "days") newDate = new Date(date.getFullYear(), date.getMonth(), days[position])
    else if (type === "months") {
      const maxDayInSelectedMonth = new Date(date.getFullYear(), MONTHS.indexOf(months[position + 1]), 0).getDate()
      const day = Math.min(date.getDate(), maxDayInSelectedMonth)
      newDate = new Date(date.getFullYear(), MONTHS.indexOf(months[position]), day)
    } else if (type === "years") {
      const maxDayInSelectedMonth = new Date(startDate.getFullYear() + position, date.getMonth(), 0).getDate()
      const day = Math.min(date.getDate(), maxDayInSelectedMonth)
      newDate = new Date(startDate.getFullYear() + position, date.getMonth(), day)
    } else if (type === "hours") {
      newDate = new Date(
        date.getFullYear(),
        date.getMonth(),
        date.getDate(),
        Number(HOURS[position]),
        date.getMinutes()
      )
    } else if (type === "minutes") {
      newDate = new Date(
        date.getFullYear(),
        date.getMonth(),
        date.getDate(),
        date.getHours(),
        Number(MINUTES[position])
      )
    } else if (type === "meridians") {
      newDate = new Date(
        date.getFullYear(),
        date.getMonth(),
        date.getDate(),
        date.getHours() + (!position ? 0 : 12),
        date.getMinutes()
      )
    }

    if (newDate) {
      setDate(newDate)
      setCurrentDate(newDate)
    }
  }

  const daysArr = new Array(new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate())
    .fill(1)
    .map((value, index) => value + index)

  let days = [...daysArr]
  if (
    date.getFullYear() === startDate.getFullYear() &&
    date.getFullYear() === endDate.getFullYear() &&
    date.getMonth() === startDate.getMonth() &&
    date.getMonth() === endDate.getMonth()
  ) {
    days = daysArr.slice(
      minDate ? daysArr.indexOf(startDate.getDate()) : daysArr.indexOf(startDate.getDate() + 1),
      daysArr.indexOf(endDate.getDate()) + 1
    )
  } else if (date.getFullYear() === startDate.getFullYear() && date.getMonth() === startDate.getMonth()) {
    days = daysArr.slice(minDate ? daysArr.indexOf(startDate.getDate()) : daysArr.indexOf(startDate.getDate() + 1))
  } else if (date.getFullYear() === endDate.getFullYear() && date.getMonth() === endDate.getMonth()) {
    days = daysArr.slice(0, daysArr.indexOf(endDate.getDate()) + 1)
  }

  let months = MONTHS
  if (date.getFullYear() === startDate.getFullYear() && date.getFullYear() === endDate.getFullYear()) {
    months = MONTHS.slice(startDate.getMonth(), endDate.getMonth() + 1)
  } else if (date.getFullYear() === startDate.getFullYear()) {
    months = MONTHS.slice(startDate.getMonth())
  } else if (date.getFullYear() === endDate.getFullYear()) {
    months = MONTHS.slice(0, endDate.getMonth() + 1)
  }

  const stopPropagation = (e: MouseEvent<HTMLDivElement>) => e.stopPropagation()

  const handleCancel = () => {
    const body = document.querySelector("body")
    if (body) {
      body.style.overflow = "unset"
    }
    if (onCancel) onCancel()
  }

  const onSelect = () => {
    if (onSelectDate) onSelectDate(currentDate)
  }

  return (
    <section className={styles.datepicker_container}>
      <div className={styles.datepicker_wrapper} onClick={stopPropagation}>
        {type === "date" ? (
          <div className={styles.date_picker}>
            <CustomWheel
              type="years"
              items={YEARS}
              selected={date.getFullYear() - startDate.getFullYear()}
              onChange={onDateChange}
            />
            <CustomWheel
              type="months"
              items={months}
              selected={months.indexOf(MONTHS[date.getMonth()])}
              onChange={onDateChange}
            />
            <CustomWheel type="days" items={days} selected={days.indexOf(date.getDate())} onChange={onDateChange} />
          </div>
        ) : (
          <div className={styles.date_picker}>
            <CustomWheel
              type="hours"
              items={HOURS}
              selected={
                HOURS.indexOf(
                  date.getHours() > 12
                    ? (date.getHours() - 12).toString().padStart(2, "0")
                    : date.getHours().toString().padStart(2, "0")
                ) + 1
              }
              onChange={onDateChange}
            />
            <CustomWheel
              type="minutes"
              items={MINUTES}
              selected={MINUTES.indexOf(date.getMinutes().toString().padStart(2, "0")) + 1}
              onChange={onDateChange}
            />
            <CustomWheel
              type="meridians"
              items={MERIDIANS}
              selected={date.getHours() > 12 ? 2 : 1}
              onChange={onDateChange}
            />
          </div>
        )}
        <section className={`${styles.button_wrapper} flex-center`}>
          <Button buttonType="danger-outlined" onClick={handleCancel}>
            Cancel
          </Button>
          <Button onClick={onSelect}>OK</Button>
        </section>
      </div>
    </section>
  )
}
