<template>
  <FormTemplate
    :form-image="formImage"
    :form-id="formId"
    class="restaurants-order-container"
  >
    <div class="header">
      <Title tag="h1" class="title">{{ $_tr('title') }}</Title>

      <BaseText v-if="subtitle" class="subtitle" v-html="subtitle" />

      <BaseText :color="$_theme('colorPrimary')" class="closed">
        {{ $_tc('closed', [closedAfter, closedAfter > 12 ? 'pm' : 'am']) }}
      </BaseText>
    </div>

    <global-form
      :form-id="formId"
      :format-data="formatData"
      :prevent-submit="preventSubmit"
      :success-log="$_tr('logs.orderValidated')"
      endpoint="content/dishes_orders"
      class="form"
      @onRequestSuccess="handleSuccess"
      @onModalStep="openModal"
    >
      <template #fields>
        <input-day
          model-name="date"
          :form-id="formId"
          :default-value="defaultDate"
          :label="$_tr('form.date')"
          :clear-button="false"
          :rules="['required']"
          :use-asterisk="false"
          :disabled-dates="disabledDates"
          :to-date="true"
          class="date"
          @onInputMount="({ value }) => (selectedDate = value)"
          @onDataChange="({ value }) => (selectedDate = value)"
        />

        <div
          v-for="category in dishesCategories"
          :key="category.title"
          class="category"
        >
          <Title tag="h5" class="title">
            {{ category.title }}
          </Title>

          <input-parent
            v-for="dish in dishes(category)"
            :key="dish.uuid"
            :form-id="formId"
            :model-name="`dish_${dish.uuid}`"
          >
            <OrderDish
              v-bind="dish"
              :name="dish.title"
              :category="category.title"
              :form-id="formId"
              :parent="`dish_${dish.uuid}`"
              @onTotalPriceChange="handleDishTotalPriceChange"
            />
          </input-parent>
        </div>

        <div class="cost-comment">
          <input-text
            model-name="comment"
            :form-id="formId"
            :label="$_tr('form.comment')"
            class="comment"
          />

          <div class="total-container">
            <input-number
              model-name="cost"
              :form-id="formId"
              :label="$_tr('form.total')"
              :readonly="true"
              :default-value="0"
              :current-value="total"
              :rules="['required', 'min_value:1']"
              :use-asterisk="false"
              class="cost"
            />

            <div
              v-if="total > 0"
              class="currency"
              :class="`length-${total.toString().length}`"
            >
              €
            </div>
          </div>
        </div>

        <input-hidden
          model-name="author"
          :form-id="formId"
          :default-value="getUserInfos.uuid"
          :rules="['required']"
        />

        <input-hidden
          model-name="bundle"
          default-value="dishes_orders"
          :form-id="formId"
          :rules="['required']"
        />

        <input-hidden
          model-name="type"
          default-value="node"
          :form-id="formId"
          :rules="['required']"
        />

        <input-hidden
          model-name="fields"
          :form-id="formId"
          :default-value="['uuid', 'title']"
        />
      </template>

      <template #submitForm>
        <div class="credits">
          <input-number
            v-if="defaultCredits"
            model-name="after"
            :form-id="formId"
            :label="$_tr('form.after')"
            :standalone="true"
            :default-value="defaultCredits"
            :current-value="previewCredits"
            :readonly="true"
            :rules="['required']"
            :use-asterisk="false"
            class="input-credit"
          />

          <input-number
            v-if="defaultCredits"
            model-name="before"
            :form-id="formId"
            :label="$_tr('form.before')"
            :standalone="true"
            :default-value="defaultCredits"
            :readonly="true"
            :rules="['required']"
            :use-asterisk="false"
            class="input-credit"
          />
        </div>

        <GlobalFormSubmitSlot
          :form-id="formId"
          :submit-button-text="$_tr('form.submit')"
        />
      </template>
    </global-form>

    <section class="form-aside-container">
      <aside class="form-aside">
        <ReplyAsideBlock
          :label="$_tr('aside.user.button')"
          :description="$_tc('aside.user.description', [+defaultCredits])"
          :link="{ name: 'RestaurantOrdersPage' }"
        />

        <ReplyAsideBlock
          v-if="canEditOrders"
          :label="$_tr('aside.admin.button')"
          :description="$_tr('aside.admin.description')"
          :link="{ name: 'RestaurantAdminPage' }"
        />
      </aside>
    </section>
  </FormTemplate>
</template>

<script>
import moment from 'moment'

import Random from '@inside-library/helpers/GenerateID'
import GlobalFormSubmitSlot from '@inside-forms/displays/sub-components/globals/GlobalFormSubmitSlot'

import FormTemplate from '@inside-forms/components/FormTemplate'
import ReplyAsideBlock from '@inside-forms/components/reply/ReplyAsideBlock'

import OrderDish from './sub-components/OrderDish'

import { Title, BaseText } from 'inside-collection/atoms'

import { http } from '@inside-library/helpers/Http'
import { partition } from '@inside-library/helpers/Arrays'

import { days as DAYS } from '../../constants'

export default {
  name: 'RestaurantsOrder',
  $_i18nRootPath: 'customs.RESTAURANTS.ORDER',
  components: {
    Title,
    BaseText,
    FormTemplate,
    OrderDish,
    GlobalFormSubmitSlot,
    ReplyAsideBlock
  },
  props: {
    categoriesList: {
      type: Array
    }
  },
  data() {
    return {
      formId: 'restaurant-order',
      total: 0,
      subTotals: [],
      defaultCredits: null,
      previewCredits: null,
      orderNumber: null,
      title: null,
      selectedDate: null
    }
  },
  computed: {
    dishesCategories() {
      return this.categoriesList.filter(
        category => this.dishes(category).length
      )
    },
    dishes() {
      const date = this.$_formatDate(moment(this.selectedDate), 'dddd')

      return category =>
        this.getCheckedData(category, ['dishes', 'data'], []).filter(
          ({ status, weekdays }) => {
            if (!status) return false

            return weekdays.data.some(
              ({ title }) =>
                title.replace(/^[0-9]\. /, '').toLowerCase() ===
                date.toLowerCase()
            )
          }
        )
    },
    subtitle() {
      const subtitle = this.getStore(
        'getInsideSettings',
        'restaurants.restaurants_subtitle'
      )

      return subtitle ? subtitle.trim() : null
    },
    defaultDate() {
      const currentHour = +moment().format('H')
      const today = moment().format('dddd')
      const [openingDays, closureDays] = this.splittedDays

      if (currentHour >= this.closedAfter || closureDays.includes(today)) {
        if (openingDays.length) {
          const indexOfToday = openingDays.findIndex(day => today === day)
          let nextDay

          if (indexOfToday < 0) {
            do {
              nextDay = moment().add(1, 'd').format('dddd')
            } while (!openingDays.includes(nextDay))
          } else {
            nextDay = openingDays[indexOfToday + 1] || openingDays[0]
          }

          const tempDay = moment().day(nextDay)

          return tempDay
            .add(moment().isSameOrAfter(tempDay) ? 1 : 0, 'w')
            .set('h', 12)
            .toDate()
        }

        return moment().toDate()
      } else {
        return moment().toDate()
      }
    },
    availableDays() {
      const days = this.getStore(
        'getInsideSettings',
        'restaurants.restaurants_available_days'
      )
      try {
        return JSON.parse(days)
      } catch {
        return []
      }
    },
    splittedDays() {
      return partition(DAYS, day => this.availableDays.includes(day))
    },
    closedAfter() {
      return +this.getStore(
        'getInsideSettings',
        'restaurants.restaurants_closed_hour'
      )
    },
    disabledDates() {
      const currentHour = +moment().format('H')

      const closureDays = this.splittedDays[1]
      const disabledDays = closureDays.map(day =>
        moment(day, 'dddd').set('h', 12).day()
      )

      return {
        to:
          currentHour >= this.closedAfter
            ? moment().toDate()
            : moment().toDate(),
        days: disabledDays
      }
    },
    canEditOrders() {
      return this.getCheckedData(this.dishesCategories, [
        0,
        'admin',
        'permission',
        'update'
      ])
    },
    formImage() {
      return {
        'banner-page': this.$store.getters.getInsideSettings(
          'restaurants.restaurants_form_picture'
        )
      }
    }
  },
  watch: {
    total(total) {
      this.previewCredits = (this.defaultCredits - total).toFixed(2)
    }
  },
  created() {
    this.fetchCredits()
  },
  methods: {
    async fetchCredits() {
      try {
        const { data } = await http.get('content/users', {
          fields: ['credits'],
          filters: { 'uuid:eq': this.getUserInfos.uuid }
        })

        this.defaultCredits = this.previewCredits = (
          +data[0].credits || 0
        ).toFixed(2)
      } catch (err) {
        throw new Error(err)
      }
    },
    preventSubmit({ cost }) {
      const cantPay = +cost > +this.defaultCredits

      if (cantPay) {
        this.$_triggerToast({
          type: 'error',
          text: this.$_tr('logs.creditsError')
        })
      }

      return cantPay
    },
    handleDishTotalPriceChange({ name, total }) {
      const itemInSubTotals = this.subTotals.find(item => item.name === name)

      if (itemInSubTotals) {
        itemInSubTotals.total = total.toFixed(2)
      } else {
        this.subTotals.push({ name, total })
      }

      this.total = this.calcTotal()
    },
    calcTotal() {
      const total = this.subTotals.reduce((acc, { total }) => acc + +total, 0)
      return total.toFixed(2)
    },
    groupByDish(data) {
      const grouped = {}

      for (const key in data) {
        const match = key.match(
          /^dish_([a-z0-9-]+)_(category|name|price|quantity)$/
        )
        if (match) {
          const [_, uuid, field] = match

          if (!grouped[uuid]) {
            grouped[uuid] = {}
          }

          grouped[uuid][field] = data[key].value
        }
      }
      return grouped
    },
    formatData(data) {
      const formFields =
        this.$store.getters.getFieldByFormId('restaurant-order')

      const order = Object.values(this.groupByDish(formFields)).filter(
        field => {
          return field
        }
      )

      const filteredData = Object.fromEntries(
        Object.entries(data).filter(([key]) => !key.startsWith('dish_'))
      )

      const orderNumber = Random.ID().substring(1).toUpperCase()

      const title = `order_${orderNumber}`

      return {
        ...filteredData,
        title,
        number: orderNumber,
        order: JSON.stringify(order)
      }
    },
    async handleSuccess() {
      try {
        await this.put(`content/users/${this.getUserInfos.uuid}`, {
          credits: +this.previewCredits
        })

        this.$router.push({ name: 'RestaurantOrdersPage' })
      } catch (err) {
        throw new Error(err)
      }
    },
    openModal() {
      const content = {
        item: {
          body: 'body',
          actionTitle: 'action'
        },
        content: 'action'
      }

      const action = () => Promise.resolve()

      this.triggerModal('action', 'static', content, {
        layout: 'center',
        transition: 'fadeIn',
        action
      })
    }
  }
}
</script>

<style lang="scss">
@use '@inside-library/styles/mixins/partials/common-mixin' as *;
@use '../../styles/variables/mixins' as *;

.restaurants-order-container {
  .layout-container {
    width: 68%;

    @include custom-break-min(1100px) {
      .form-aside-container {
        left: 0;
        width: 24%;
        transform: translateX(-60%);
      }
    }

    @include desktop-to-tablet {
      width: 80%;
    }

    @include tablet {
      width: 100%;
    }
  }

  .header {
    text-align: center;
    flex-direction: column;
    align-items: center;
  }

  .form-aside-container {
    .reply-aside-block .description {
      color: var(--color-light);
    }
  }

  .global-form__fields {
    .date {
      margin-bottom: var(--spacing-l);

      .vdp-datepicker__calendar .cell {
        &.selected {
          background: var(--color-primary);
        }

        &.today:not(.selected) {
          background: none;
        }
      }
    }

    .category {
      + .category {
        margin-top: var(--spacing-l);
      }

      .title {
        font-weight: bold !important;
      }
    }

    .cost-comment {
      display: flex;
      justify-content: space-between;

      @include restaurants-currency;

      .comment {
        width: 70%;
      }

      .cost {
        width: 56px;
      }
    }

    /* Chrome, Safari, Edge, Opera */
    input::-webkit-outer-spin-button,
    input::-webkit-inner-spin-button {
      -webkit-appearance: none;
      margin: 0;
    }

    /* Firefox */
    input[type='number'] {
      -moz-appearance: textfield;
    }
  }

  .global-form__submit {
    display: flex;
    justify-content: flex-end;
    align-items: center;

    .credits {
      display: flex;
      justify-content: flex-end;
      margin-right: var(--spacing-xl);

      .input-credit {
        width: 56px;

        + .input-credit {
          margin-left: var(--spacing-s);
        }
      }
    }
  }
}
</style>
