<template>
  <Modal ref="modalRef" size="md">
    <template #title>
      Create a new storage {{ set === true ? 'set' : '' }}
    </template>

    <template #default="{ closeModal }">
      <FormAlert :message="error" />
      <Form @submit="onSubmit" v-model="data" :validators="validators">
        <FormField name="displayName" label="Display Name" />
        <FormSelectField :options="selectOptions" name="type" label="Type" />
        <FormField name="locationDescription" label="Location description">
          <span class="text-sm">Describe the location of this storage</span>
        </FormField>
        <FormColorField name="color" label="Color" />
        <button type="submit">Submit</button>
      </Form>
    </template>
  </Modal>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue';
import { useAccessToken } from '../../composables/useAccessToken';
import { BACKEND_URL } from '../../constants';
import { StorageSetTypeName } from '../../enums/storage-set-type.enum';
import { StorageTypeName } from '../../enums/storage-type.enum';
import { BuildingListItem } from '../../interfaces/building.interfaces';
import { RoomListItem } from '../../interfaces/room.interfaces';
import {
  StorageSetListItem,
  StorageSharedType,
} 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 FormColorField from '../form/fields/FormColorField.vue';

const { authHeader } = useAccessToken();
const defaults = {
  displayName: '',
  type: '',
  locationDescription: '',
  color: '#000000',
};

const modalRef = ref<InstanceType<typeof Modal>>();
const room = ref<RoomListItem>();
const building = ref<BuildingListItem>();
const set = ref<StorageSetListItem | boolean>();
const data = ref({ ...defaults });
const error = ref('');
const selectOptions = computed(() => {
  const source = set.value === true ? StorageSetTypeName : StorageTypeName;
  return Object.keys(source).reduce<SelectOption[]>(
    (list, key) => [
      ...list,
      { value: key.toString(), name: source[key as keyof typeof source] },
    ],
    []
  );
});

const validators = ref([
  {
    field: 'displayName',
    validators: [MinLength(3), IsRequired()],
  },
  {
    field: 'type',
    validators: [IsRequired()],
  },
]);

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

defineExpose({
  openModal: (
    useBuilding: BuildingListItem,
    useRoom: RoomListItem,
    useSet?: StorageSetListItem | boolean
  ) => {
    room.value = useRoom;
    building.value = useBuilding;
    set.value = useSet;
    data.value = { ...defaults };
    modalRef.value?.openModal();
  },
});

const onSubmit = async (value: FormSubmit) => {
  error.value = '';

  if (!value.isValid || !room.value) return;

  const createURL = `${BACKEND_URL}/storage${
    set.value === true ? '/set' : ''
  }/room/${room.value.id}`;

  let createdStorage: StorageSharedType;
  try {
    const response = await jfetch(createURL, {
      method: 'POST',
      body: {
        ...value.formData,
        location: '0,0',
      },
      headers: authHeader.value,
    });

    createdStorage = response.data;
  } catch (e) {
    error.value = takeError(e);
    return;
  }

  // Add created storage to set
  if (set.value && typeof set.value !== 'boolean') {
    await jfetch(
      `${BACKEND_URL}/storage/set/${set.value.id}/${createdStorage.id}`,
      {
        method: 'POST',
        headers: authHeader.value,
      }
    );
  }

  modalRef.value?.closeModal();
  emit('added', createdStorage);
};
</script>
