<template>
  <Modal ref="modalRef" size="xl">
    <template #title> Add a new item </template>

    <template #default="{ closeModal }">
      <FormAlert :message="error" />
      <Form @submit="onSubmit" v-model="data" :validators="validators">
        <FormAutocompleteField
          v-if="typeof item !== 'string'"
          name="item"
          label="Item"
          required
          :search-fn="searchForItems"
        >
          <template #notfound="{ query }">
            <button @click="startAddingNewItem(query)">Add a new item</button>
          </template>
        </FormAutocompleteField>
        <template v-if="item && typeof item === 'string'">
          <FormField name="displayName" label="Display Name" required />
          <FormSelectField
            :options="itemTypesOptions"
            required
            name="type"
            label="Type"
          />
          <FormField name="barcode" label="Barcode" />
          <FormField name="url" label="URL" />
          <div class="grid space-y-2 sm:grid-cols-3 sm:space-y-0 sm:space-x-2">
            <FormField
              name="weight"
              type="number"
              step="0.001"
              label="Weight (g)"
            />
            <FormField
              name="consumable"
              type="checkbox"
              label="Consumable / Food item"
            />
            <FormField name="public" type="checkbox" label="Public item" />
          </div>
          <FormTextareaField name="notes" label="Notes" />
        </template>

        <FormGroup name="transactionInfo">
          <FormDateField
            name="actionAt"
            label="Action committed at"
            :disabled="!item"
            required
          />

          <div class="grid grid-cols-2 space-x-2 sm:grid-cols-4">
            <FormField
              name="price"
              label="Cost"
              type="number"
              step=".01"
              class="sm:col-span-3"
              :disabled="!item"
            />
            <FormSelectField
              :options="currencies"
              :disabled="!item"
              name="currency"
              label="Currency"
            />
          </div>

          <FormTextareaField
            :disabled="!item"
            name="notes"
            label="Additional notes about the transaction"
          />
        </FormGroup>

        <FormGroup name="additionalInfo">
          <div class="grid space-y-2 sm:grid-cols-3 sm:space-y-0 sm:space-x-2">
            <FormDateField
              name="expiresAt"
              label="Expires at"
              :disabled="!item"
            />
            <FormDateField
              name="acquiredAt"
              label="Acquired at"
              :disabled="!item"
            />
            <FormDateField
              name="consumedAt"
              label="Consumed at"
              :disabled="!item"
            />
          </div>

          <FormTextareaField
            name="notes"
            label="Additional notes about the individual stored item"
            :disabled="!item"
          />
        </FormGroup>

        <div class="flex justify-end space-x-1">
          <Button button-type="submit" @click="submitlock = true"
            >Submit and add another</Button
          >
          <Button button-type="submit">Submit</Button>
        </div>
      </Form>
    </template>
  </Modal>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { useAccessToken } from '../../composables/useAccessToken';
import { BACKEND_URL } from '../../constants';
import { BuildingListItem } from '../../interfaces/building.interfaces';
import {
  StorageItem,
  StorageListItem,
  StoredItem,
} from '../../interfaces/storage.interfaces';
import jfetch from '../../utils/jfetch';
import takeError from '../../utils/take-error';
import { FormSubmit, SelectOption } from '../form/form.types';
import Form from '../form/Form.vue';
import FormAlert from '../form/FormAlert.vue';
import FormField from '../form/FormField.vue';
import FormSelectField from '../form/fields/FormSelectField.vue';
import { IsRequired, MinLength } from '../form/validators';
import Modal from '../Modal.vue';
import { ItemType, ItemTypeName } from '../../enums/item-type.enum';
import { TransactionType } from '../../enums/transaction-type.enum';
import FormGroup from '../form/FormGroup.vue';
import FormDateField from '../form/fields/FormDateField.vue';
import FormAutocompleteField from '../form/fields/FormAutocompleteField.vue';
import { FormValidator } from '../form/validator.types';
import deepUnref from '../../utils/deep-unref';
import FormTextareaField from '../form/fields/FormTextareaField.vue';
import Button from '../Button.vue';

const defaults: any = {
  item: null,
  transactionInfo: {
    type: TransactionType.ACQUIRED,
    actionAt: new Date(),
  },
  additionalInfo: {
    acquiredAt: new Date(),
  },
};

const { authHeader } = useAccessToken();
const modalRef = ref<InstanceType<typeof Modal>>();
const building = ref<BuildingListItem>();
const storage = ref<StorageListItem>();
const item = ref<StorageItem | string | null>(null);
const data: any = ref({
  ...deepUnref(defaults),
});
const error = ref('');
const submitlock = ref(false);

const emit = defineEmits<{
  (e: 'added', storage: StoredItem): void;
}>();

const itemTypesOptions = computed(() => {
  return Object.keys(ItemTypeName).reduce<SelectOption[]>(
    (list, key) => [
      ...list,
      {
        value: key.toString(),
        name: ItemTypeName[key as ItemType],
      },
    ],
    []
  );
});

const validators = ref<FormValidator[]>([
  {
    field: 'displayName',
    validators: [MinLength(3), IsRequired()],
  },
  {
    field: 'type',
    validators: [IsRequired()],
  },
  {
    field: 'transactionInfo.actionAt',
    validators: [IsRequired()],
  },
]);

const currencies = [
  {
    value: 'EUR',
    name: 'EUR',
  },
  {
    value: 'USD',
    name: 'USD',
  },
];

const searchForItems = async (search: string) => {
  if (!search || search.length < 3) return [];

  const query = new URLSearchParams();
  if (search.startsWith('b:') && search.length > 3) {
    query.append('barcode', search.substring(2));
  } else {
    query.append('searchTerm', search);
  }

  const { data: list } = await jfetch(
    `${BACKEND_URL}/storage/item?${query.toString()}`,
    {
      headers: authHeader.value,
    }
  );
  return list;
};

defineExpose({
  openModal: (useBuilding: BuildingListItem, useStorage: StorageListItem) => {
    building.value = useBuilding;
    storage.value = useStorage;
    item.value = null;
    data.value = {
      ...deepUnref(defaults),
    };
    modalRef.value?.openModal();
  },
});

watch(
  () => data.value.item,
  (selected) => {
    if (selected && selected.id) {
      item.value = selected;
      return;
    }
    item.value = null;
  }
);

const startAddingNewItem = (insert: string) => {
  item.value = insert;
  if (insert.startsWith('b:')) {
    data.value['barcode'] = insert.substring(2);
  } else {
    data.value['displayName'] = insert;
  }
};

const onSubmit = async (form: FormSubmit) => {
  error.value = '';
  if (!form.isValid || !storage.value) {
    submitlock.value = false;
    return;
  }

  const body = {
    ...form.formData,
  };
  delete body.item;

  const requestUrl = `${BACKEND_URL}/storage/item/${storage.value.id}${
    item.value && typeof item.value !== 'string' ? `/${item.value.id}` : ''
  }`;

  let createdStoredItem: StoredItem;
  try {
    const { data: response } = await jfetch(requestUrl, {
      method: 'POST',
      headers: authHeader.value,
      body,
    });
    createdStoredItem = response;
  } catch (e) {
    error.value = takeError(e);
    return;
  }

  emit('added', createdStoredItem);
  if (submitlock.value) {
    submitlock.value = false;
    return;
  }
  modalRef.value?.closeModal();
};
</script>
