<template>
  <q-dialog :auto-close="false" :model-value="visible" persistent bordered>
    <q-card class="dialog-content" >
      <q-toolbar class="bg-grey-4">
        <q-toolbar-title>{{ dialogTitle }}</q-toolbar-title>
        <q-btn flat round dense icon="close" @click="close" />
      </q-toolbar>

      <q-card-section class="q-mx-md " >
        <q-select
          v-permissions="props.actionPermissions.edit"
          class="q-mt-md"
          :disable="loading||!domain.domainActive"
          filled
          dense
          v-model="canSharedUserFilter"
          use-input
          input-debounce="0"
          :options="canSharedUserFilteredOptions"
          clearable
          :placeholder="canSharedUserFilter ? '' : domain.domainActive ? '権限を付与するユーザーを選択' : '接続先が無効なため、権限を付与できません'"
          @filter="filterFn">

          <template v-slot:selected-item="scope">
            <span v-if="canSharedUserFilter">
              {{ canSharedUserFilter.fullName }} （{{ canSharedUserFilter.email }}）
              <role-label :domain="domain" :user="scope.opt"></role-label>
            </span>
          </template>

          <template v-slot:after>
            <q-btn :disable="!canSharedUserFilter" :loading="addLoading" label="付与" color="primary" @click="shareTo(canSharedUserFilter as IUserDisplayWithShareRole)" />
          </template>

          <template v-slot:option="scope">
            <q-item v-bind="scope.itemProps">
              <q-item-section avatar>{{scope.opt.id}}</q-item-section>
              <q-item-section>{{scope.opt.fullName}}</q-item-section>
              <q-item-section>{{scope.opt.email}}</q-item-section>
              <q-item-section side>
                <div style="width: 6.5em;">
                  <role-label :domain="domain" :user="scope.opt"></role-label>
                </div>
              </q-item-section>
            </q-item>
          </template>
        </q-select>

        <sharing-user-list class="q-mt-md" style="height: 330px" :users="sharedUsers" :loading="loading" :title="userListTitle">
          <template v-slot:body-cell-role="{ row }">
            <q-td auto-width>
              <role-label :domain="domain" :user="row"></role-label>
            </q-td>
          </template>

          <template v-slot:actions="{ row }">
            <q-btn v-permissions="props.actionPermissions.edit" round title="解除" flat color="primary" :disable="isActionDisable && isActionDisable(row)" padding="xs" size="1em" :loading="row.isRemoving" icon="person_off" @click="removeShareTo(row)" />
          </template>
        </sharing-user-list>

      </q-card-section>

      <q-card-actions align="right" class="text-primary">
        <q-btn flat label="確定" @click="checkClose" />
        <q-btn flat label="キャンセル" @click="close" />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script setup lang="ts">
import { ref, watch } from 'vue';
import { IDomainOwnerDisplay } from '../../types/DomainTypes';
import { IUser, IUserDisplay } from '../../types/UserTypes';
import { api } from 'boot/axios';
import { useAuthStore } from 'stores/useAuthStore';
import SharingUserList from 'components/ShareDomain/SharingUserList.vue';
import RoleLabel from 'components/ShareDomain/RoleLabel.vue';
import { Dialog } from 'quasar'

const authStore = useAuthStore();

interface Props {
  modelValue: boolean;
  domain: IDomainOwnerDisplay;
  dialogTitle: string;
  userListTitle: string;
  isActionDisable?: (user: IUserDisplay) => boolean;
  shareApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
  removeSharedApi: (user: IUserDisplay, domain: IDomainOwnerDisplay) => Promise<any>;
  getSharedApi: (domain: IDomainOwnerDisplay) => Promise<any>;
  actionPermissions: { 'list': string, 'edit': string };
}

interface IUserDisplayWithShareRole extends IUserDisplay {
  isRemoving: boolean;
  role: number;
}

const props = defineProps<Props>();

const emit = defineEmits<{
  (e: 'update:modelValue', value: boolean): void;
  (e: 'close'): void;
}>();

const addLoading = ref(false);
const loading = ref(true);
const visible = ref(props.modelValue);

const allUsers = ref<IUserDisplayWithShareRole[]>([]);
const sharedUsers = ref<IUserDisplayWithShareRole[]>([]);
const sharedUsersIdSet = new Set<number>();

const canSharedUsers = ref<IUserDisplayWithShareRole[]>([]);
const canSharedUserFilter = ref<IUserDisplayWithShareRole>();
const canSharedUserFilteredOptions = ref<IUserDisplayWithShareRole[]>([]);

const filterFn = (val:string, update: (cb: () => void) => void) => {
  update(() => {
    if (val === '') {
      canSharedUserFilteredOptions.value = canSharedUsers.value;
      return;
    }
    const needle = val.toLowerCase();
    canSharedUserFilteredOptions.value = canSharedUsers.value.filter(v =>
      v.email.toLowerCase().indexOf(needle) > -1 || v.fullNameSearch.toLowerCase().indexOf(needle) > -1);
  })
}

watch(
  () => props.modelValue,
  async (newValue) => {
    visible.value = newValue;
    sharedUsers.value = [];
    canSharedUserFilter.value = undefined
    loading.value = false;
    addLoading.value = false;
    if (newValue) {
      if (Object.keys(allUsers.value).length == 0) {
        await getUsers();
      }
      await loadShared();
    }
  }
);

watch(
  () => visible.value,
  (newValue) => {
    emit('update:modelValue', newValue);
  }
);

const checkClose = () => {
  if (!canSharedUserFilter.value) {
    close();
    return;
  }
  Dialog.create({
    title: '注意',
    message: '選択済だがまだ付与未完了のユーザーがあります。<br>必要な操作を選んでください。',
    html: true,
    persistent: true,
    ok: {
      color: 'primary',
      label: '付与'
    },
    cancel: '直接閉じる',
  }).onCancel(() => {
    close();
  }).onOk(() => {
    shareTo(canSharedUserFilter.value as IUserDisplayWithShareRole);
  });
};

const close = () => {
  emit('close');
};

const shareTo = async (user: IUserDisplayWithShareRole) => {
  addLoading.value = true;
  loading.value = true;
  await props.shareApi(user, props.domain);
  await loadShared();
  canSharedUserFilter.value = undefined;
  loading.value = false;
  addLoading.value = false;
}

const removeShareTo = async (user: IUserDisplayWithShareRole) => {
  loading.value = true;
  user.isRemoving = true;
  await props.removeSharedApi(user, props.domain);
  if (isCurrentDomain()) {
    await authStore.loadCurrentDomain();
  }
  await loadShared();
  loading.value = false;
};

const isCurrentDomain = () => {
  return props.domain.id === authStore.currentDomain.id;
}

const loadShared = async () => {
  loading.value = true;
  sharedUsersIdSet.clear();

  const { data } = await props.getSharedApi(props.domain);

  sharedUsers.value = data.data.reduce((arr: IUserDisplayWithShareRole[], item: IUser) => {
    const val = itemToDisplay(item);
    if(!sharedUsersIdSet.has(val.id)) {
      sharedUsersIdSet.add(val.id);
      // for sort
      if (isOwner(val.id)) {
        val.role = 2;
      } else if (isManager(val.id)) {
        val.role = 1;
      } else {
        val.role = 0;
      }
      arr.push(val);
    }
    return arr;
  }, []).sort((a: IUserDisplayWithShareRole, b: IUserDisplayWithShareRole) => b.role - a.role);

  canSharedUsers.value = allUsers.value.filter((item) => !sharedUsersIdSet.has(item.id));
  canSharedUserFilteredOptions.value = canSharedUsers.value;

  loading.value = false;
}

function isOwner(userId: number) {
  return userId === props.domain?.owner?.id
}

function isManager(userId: number) {
  return false // TODO
}

const getUsers = async () => {
  loading.value = true;
  const result = await api.get('api/v1/users');
  allUsers.value = result.data.data.map(itemToDisplay);
  loading.value = false;
}

const itemToDisplay = (item: IUser) => {
  return {
    id: item.id,
    firstName: item.first_name,
    lastName: item.last_name,
    fullNameSearch: (item.last_name + item.first_name).toLowerCase(),
    fullName: item.last_name + ' ' + item.first_name,
    email: item.email,
    isSuperuser: item.is_superuser,
    isActive: item.is_active,
    role: 0,
  } as IUserDisplayWithShareRole
}

</script>

<style lang="scss">
.dialog-content {
  width: 700px !important;
  max-width: 80vw !important;
  max-height: 80vh;
  .q-select {
    min-width: 0 !important;
  }
}

</style>
