<template>
  <modals-modal ref="modal" v-model="show" name="ereader-device-edit" :width="800" :height="'unset'" :processing="processing">
    <template #outer>
      <div class="absolute top-0 left-0 p-5 w-2/3 overflow-hidden">
        <p class="text-3xl text-white truncate">{{ title }}</p>
      </div>
    </template>
    <form @submit.prevent="submitForm">
      <div class="w-full text-sm rounded-lg bg-bg shadow-lg border border-black-300">
        <div class="w-full px-3 py-5 md:p-12">
          <div class="flex items-center -mx-1 mb-4">
            <div class="w-full md:w-1/2 px-1">
              <ui-text-input-with-label ref="ereaderNameInput" v-model="newDevice.name" :disabled="processing" :label="$strings.LabelName" />
            </div>
            <div class="w-full md:w-1/2 px-1">
              <ui-text-input-with-label ref="ereaderEmailInput" v-model="newDevice.email" :disabled="processing" :label="$strings.LabelEmail" />
            </div>
          </div>
          <div class="flex items-center -mx-1 mb-4">
            <div class="w-full md:w-1/2 px-1">
              <ui-dropdown v-model="newDevice.availabilityOption" :label="$strings.LabelDeviceIsAvailableTo" :items="userAvailabilityOptions" @input="availabilityOptionChanged" />
            </div>
            <div class="w-full md:w-1/2 px-1">
              <ui-multi-select-dropdown v-if="newDevice.availabilityOption === 'specificUsers'" v-model="newDevice.users" :label="$strings.HeaderUsers" :items="userOptions" />
            </div>
          </div>

          <div class="flex items-center pt-4">
            <div class="flex-grow" />
            <ui-btn color="success" type="submit">{{ $strings.ButtonSubmit }}</ui-btn>
          </div>
        </div>
      </div>
    </form>
  </modals-modal>
</template>

<script>
export default {
  props: {
    value: Boolean,
    existingDevices: {
      type: Array,
      default: () => []
    },
    ereaderDevice: {
      type: Object,
      default: () => null
    },
    users: {
      type: Array,
      default: () => []
    },
    loadUsers: Function
  },
  data() {
    return {
      processing: false,
      newDevice: {
        name: '',
        email: '',
        availabilityOption: 'adminAndUp',
        users: []
      }
    }
  },
  watch: {
    show: {
      handler(newVal) {
        if (newVal) {
          this.init()
        }
      }
    }
  },
  computed: {
    show: {
      get() {
        return this.value
      },
      set(val) {
        this.$emit('input', val)
      }
    },
    title() {
      return !this.ereaderDevice ? 'Create Device' : 'Update Device'
    },
    userAvailabilityOptions() {
      return [
        {
          text: this.$strings.LabelAdminUsersOnly,
          value: 'adminOrUp'
        },
        {
          text: this.$strings.LabelAllUsersExcludingGuests,
          value: 'userOrUp'
        },
        {
          text: this.$strings.LabelAllUsersIncludingGuests,
          value: 'guestOrUp'
        },
        {
          text: this.$strings.LabelSelectUsers,
          value: 'specificUsers'
        }
      ]
    },
    userOptions() {
      return this.users.map((u) => ({ text: u.username, value: u.id }))
    }
  },
  methods: {
    availabilityOptionChanged(option) {
      if (option === 'specificUsers' && !this.users.length) {
        this.callLoadUsers()
      }
    },
    async callLoadUsers() {
      this.processing = true
      await this.loadUsers()
      this.processing = false
    },
    submitForm() {
      this.$refs.ereaderNameInput.blur()
      this.$refs.ereaderEmailInput.blur()

      if (!this.newDevice.name?.trim() || !this.newDevice.email?.trim()) {
        this.$toast.error(this.$strings.ToastNameEmailRequired)
        return
      }

      if (this.newDevice.availabilityOption === 'specificUsers' && !this.newDevice.users.length) {
        this.$toast.error(this.$strings.ToastSelectAtLeastOneUser)
        return
      }
      if (this.newDevice.availabilityOption !== 'specificUsers') {
        this.newDevice.users = []
      }

      this.newDevice.name = this.newDevice.name.trim()
      this.newDevice.email = this.newDevice.email.trim()

      if (!this.ereaderDevice) {
        if (this.existingDevices.some((d) => d.name === this.newDevice.name)) {
          this.$toast.error(this.$strings.ToastDeviceNameAlreadyExists)
          return
        }

        this.submitCreate()
      } else {
        if (this.ereaderDevice.name !== this.newDevice.name && this.existingDevices.some((d) => d.name === this.newDevice.name)) {
          this.$toast.error(this.$strings.ToastDeviceNameAlreadyExists)
          return
        }

        this.submitUpdate()
      }
    },
    submitUpdate() {
      this.processing = true

      const existingDevicesWithoutThisOne = this.existingDevices.filter((d) => d.name !== this.ereaderDevice.name)

      const payload = {
        ereaderDevices: [
          ...existingDevicesWithoutThisOne,
          {
            ...this.newDevice
          }
        ]
      }

      this.$axios
        .$post(`/api/emails/ereader-devices`, payload)
        .then((data) => {
          this.$emit('update', data.ereaderDevices)
          this.show = false
        })
        .catch((error) => {
          console.error('Failed to update device', error)
          this.$toast.error(this.$strings.ToastDeviceUpdateFailed)
        })
        .finally(() => {
          this.processing = false
        })
    },
    submitCreate() {
      this.processing = true

      const payload = {
        ereaderDevices: [
          ...this.existingDevices,
          {
            ...this.newDevice
          }
        ]
      }

      this.$axios
        .$post('/api/emails/ereader-devices', payload)
        .then((data) => {
          this.$emit('update', data.ereaderDevices || [])
          this.show = false
        })
        .catch((error) => {
          console.error('Failed to add device', error)
          this.$toast.error(this.$strings.ToastDeviceAddFailed)
        })
        .finally(() => {
          this.processing = false
        })
    },
    init() {
      if (this.ereaderDevice) {
        this.newDevice.name = this.ereaderDevice.name
        this.newDevice.email = this.ereaderDevice.email
        this.newDevice.availabilityOption = this.ereaderDevice.availabilityOption || 'adminOrUp'
        this.newDevice.users = this.ereaderDevice.users || []
      } else {
        this.newDevice.name = ''
        this.newDevice.email = ''
        this.newDevice.availabilityOption = 'adminOrUp'
        this.newDevice.users = []
      }
    }
  },
  mounted() {}
}
</script>