import React, { useEffect, useState } from 'react'
import Layout from '../../../../components/layout'
import Input from '../../../../components/input'
import Select from '../../../../components/select'
import { Booking } from '../../../../db/booking'
import { BILL_STATUS, MILAGE_TARIFS } from '../../../../db/enums'
import { getMilageMax } from '../../../../db/index'
import { daysFormatFrontend } from '../../../../helpers/date'
import { getBillTotal, createBill, patchBill } from '../../../../helpers/bill'
import { getBookingStatus } from '../../../../helpers/booking'
import { getServerSideBooking } from '../../../../lib/getServerSideProps'

export const getServerSideProps = async (context) => {
  const milageMax = await getMilageMax()
  const serverSideBookingProps = await getServerSideBooking(context)
  return {
    props: {
      ...serverSideBookingProps.props,
      milageMax,
    },
  }
}

const milageTarifOptions = Object.values(MILAGE_TARIFS).map((tarif) => {
  return (
    <option value={tarif} key={tarif}>
      {getTarifLabel(tarif)}
    </option>
  )
})

const billStatusOptions = Object.values(BILL_STATUS).map((status) => {
  return (
    <option value={status} key={status}>
      {getBillStatusLabel(status)}
    </option>
  )
})

function getTarifLabel(tarif: MILAGE_TARIFS) {
  switch (tarif) {
    case MILAGE_TARIFS.EXTERN:
      return 'Extern'
    case MILAGE_TARIFS.INTERN:
      return 'Intern'
    case MILAGE_TARIFS.NOCHARGE:
      return 'Frei von Kosten'
    default:
      return 'Keine'
  }
}

function getBillStatusLabel(status: BILL_STATUS) {
  switch (status) {
    case BILL_STATUS.UNINVOICED:
      return 'Nicht gestellt'
    case BILL_STATUS.INVOICED:
      return 'Gestellt'
    case BILL_STATUS.PAID:
      return 'Bezahlt'
    default:
      return 'Unbekannt!!!'
  }
}

function BookingBillPage({
  booking: bookingProp,
  milageMax,
}: {
  booking: Booking
  milageMax: number
}) {
  const [booking, setBooking] = useState(bookingProp)
  const [milageStart, setMilageStart] = useState(
    booking?.bill?.milageStart || milageMax
  )
  const [milageEnd, setMilageEnd] = useState(booking?.bill?.milageEnd)
  const [tarif, setTarif] = useState(
    booking?.bill?.tarif || MILAGE_TARIFS.EXTERN
  )
  const [status, setStatus] = useState(booking?.bill?.status)
  const [additionalCosts, setAdditionalCosts] = useState([])
  const [storingInProgress, setStoringInProgress] = useState(false)
  const [storingError, setStoringError] = useState(null)
  const milage =
    (0 < milageStart && milageStart < milageEnd && milageEnd - milageStart) || 0
  const total = getBillTotal({ tarif, milage, additionalCosts })

  // in case the props change, update the internal state
  useEffect(() => setBooking(bookingProp), [bookingProp])

  const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault()
    setStoringInProgress(true)
    setStoringError(null)

    try {
      const saveBill = !!booking.bill ? createBill : patchBill
      const bill = await saveBill(booking.uuid, {
        milageStart,
        milageEnd,
        milage,
        tarif,
        status,
        additionalCosts,
      })

      booking.bill = bill
      setBooking(booking)
    } catch (error) {
      setStoringError('Buchung konnte nicht gespeichert werden!')
      console.error('Failed to store booking', error)
    }
    setStoringInProgress(false)
  }

  const onAddAdditionalCost = function (
    event: React.MouseEvent<HTMLButtonElement>
  ) {
    event.preventDefault()
    setAdditionalCosts([...additionalCosts, { name: '', value: 0 }])
  }

  const onRemoveAdditionalCost = function (
    event: React.MouseEvent<HTMLButtonElement>,
    index: number
  ) {
    event.preventDefault()
    setAdditionalCosts([
      ...additionalCosts.slice(0, index),
      ...additionalCosts.slice(index + 1),
    ])
  }

  return (
    <Layout>
      {booking && (
        <form className="w-full" onSubmit={onSubmit}>
          <div>
            <strong>Buchungszeitraum:</strong>{' '}
            {daysFormatFrontend(booking.days)}
          </div>
          <div>
            <strong>Bucher:</strong> {booking.name}
          </div>
          <div>
            <strong>Buchungsstatus:</strong> {getBookingStatus(booking.status)}
          </div>
          <div>
            <Input
              label="Anfangskilometer"
              name="milageStart"
              required
              value={milageStart}
              type="number"
              onChange={(e: React.ChangeEvent<React.ElementRef<'input'>>) =>
                setMilageStart(Number(e.target.value))
              }
            />
            <Input
              label="Endkilometer"
              name="milageEnd"
              required
              value={milageEnd}
              type="number"
              onChange={(e: React.ChangeEvent<React.ElementRef<'input'>>) =>
                setMilageEnd(Number(e.target.value))
              }
            />
            <Input label="Gefahren" name="milage" readOnly value={milage} />
            <Select
              label="Rate"
              name="tarif"
              value={tarif}
              onChange={(e) => setTarif(e.target.value as MILAGE_TARIFS)}
            >
              {milageTarifOptions}
            </Select>
            <div className="mb-3">
              <button
                className="ibtn btn-gray mr-3"
                onClick={onAddAdditionalCost}
                title="Zusätzliche Kosten hinzufügen"
              >
                +
              </button>
              <label className="flabel inline">Zusätzliche Kosten</label>
            </div>
            {additionalCosts.map((_, index) => {
              return (
                <>
                  <div className="mb-3" key={`label${index}`}>
                    <button
                      className="ibtn btn-gray mr-3"
                      onClick={(event) => onRemoveAdditionalCost(event, index)}
                      title="Entfernen"
                    >
                      -
                    </button>
                    <label className="flabel inline">{`Kostenpunkt ${
                      index + 1
                    }`}</label>
                  </div>
                  <div className="ml-10 mb-3" key={`input{index}`}>
                    <Input
                      label={`Name`}
                      name={`additionalCostName${index}`}
                      key={`additionalCostName${index}`}
                      value={additionalCosts[index].name}
                      onChange={(event) => {
                        const newAdditonalCosts = [...additionalCosts]
                        newAdditonalCosts[index] = {
                          value: newAdditonalCosts[index].value,
                          name: event.target.value,
                        }
                        setAdditionalCosts(newAdditonalCosts)
                      }}
                    />
                    <Input
                      label={`Betrag`}
                      name={`additionalCostValue${index}`}
                      key={`additionalCostValue${index}`}
                      value={additionalCosts[index].value}
                      type="number"
                      onChange={(event) => {
                        const newAdditonalCosts = [...additionalCosts]
                        newAdditonalCosts[index] = {
                          name: newAdditonalCosts[index].name,
                          value: Number(event.target.value),
                        }
                        setAdditionalCosts(newAdditonalCosts)
                      }}
                    />
                  </div>
                </>
              )
            })}
            <Input label="Summe" name="total" readOnly value={total} />
          </div>
          <Select
            label="Status"
            name={status}
            value={status}
            onChange={(e) => setStatus(e.target.value as BILL_STATUS)}
          >
            {billStatusOptions}
          </Select>
          {storingError && (
            <div className="error-message flex-grow mt-6">{storingError}</div>
          )}
          <button
            type="submit"
            className="btn btn-blue mt-3"
            disabled={storingInProgress}
          >
            Rechnung {!!booking.bill ? 'Updaten' : 'Erstellen'}
          </button>
        </form>
      )}
    </Layout>
  )
}

BookingBillPage.auth = true

export default BookingBillPage
