<template>
  <q-page class="q-pa-md">
    <SettingsTabsHeader />

    <q-card flat bordered class="settings-card">
      <q-card-section class="q-pb-none">
        <div class="text-h6 text-weight-bold">
          {{ pageTitle }}
        </div>

        <div class="text-grey-7 q-mt-xs">
          {{ pageDescription }}
        </div>
      </q-card-section>

      <q-card-section v-if="isCreateMode" class="q-pt-lg">
        <q-banner
          v-if="readonlyBannerMessage"
          class="bg-blue-1 text-primary q-mb-md"
          rounded
        >
          {{ readonlyBannerMessage }}
        </q-banner>

        <div class="row q-col-gutter-lg q-mt-md">
          <q-input
            v-model="draftUserType.description"
            class="col-12 col-md-6"
            :disable="isReadOnly"
            :error="!!serverErrors.description"
            :error-message="serverErrors.description"
            :label="$t('settings.user_types.description')"
          />
        </div>
      </q-card-section>

      <q-card-section v-else class="q-pt-lg">
        <q-banner
          v-if="readonlyBannerMessage"
          class="bg-blue-1 text-primary q-mb-md"
          rounded
        >
          {{ readonlyBannerMessage }}
        </q-banner>

        <div class="row items-center q-col-gutter-md q-mb-md">
          <div class="col-auto">
            <q-chip color="secondary" text-color="primary" icon="mdi-tag">
              {{ selectedUserTypeLabel }}
            </q-chip>
          </div>

          <div class="col-auto">
            <q-chip outline color="primary">
              {{
                $t("settings.user_types.selected_permissions", {
                  count: ticked.length,
                })
              }}
            </q-chip>
          </div>
        </div>
      </q-card-section>

      <q-card-section class="q-pt-none q-pb-lg">
        <div v-if="isCreateMode" class="row items-center q-col-gutter-md q-mb-md">
          <div class="col-auto">
            <q-chip outline color="primary">
              {{
                $t("settings.user_types.selected_permissions", {
                  count: ticked.length,
                })
              }}
            </q-chip>
          </div>
        </div>

        <q-tree
          v-if="treeNodes.length"
          v-model:expanded="expanded"
          class="permission-tree"
          node-key="id"
          tick-strategy="leaf"
          :nodes="treeNodes"
          :ticked="ticked"
          @update:ticked="onTickedUpdate"
        >
          <template #default-header="props">
            <div class="row items-center no-wrap full-width">
              <div class="q-ml-sm">
                <div class="text-body2 text-weight-medium">
                  {{ props.node.label }}
                </div>
              </div>
            </div>
          </template>
        </q-tree>

        <q-inner-loading :showing="loadingTree" color="primary" />
      </q-card-section>

      <q-separator />

      <q-card-actions align="right" class="q-pa-lg">
        <q-btn
          color="primary"
          outline
          padding="10px 24px"
          :label="$t('common.actions.back')"
          @click="router.push({ name: 'SettingsUserTypesPage' })"
        />

        <q-btn
          class="btn-custom-default"
          color="secondary"
          padding="10px 28px"
          :disable="saveDisabled"
          :loading="loading"
          @click="onSubmit"
        >
          <span class="text-primary">{{ $t("common.actions.save") }}</span>
        </q-btn>
      </q-card-actions>
    </q-card>
  </q-page>
</template>

<script setup>
import {
  buildPermissionPayloadFromTicked,
  buildPermissionTreeNodes,
  buildTickedKeys,
  isLockedUserTypePermission,
  normalizeUserTypeOptions
} from "./utils";

import { computed, onMounted, ref } from "vue";
import { createUserType, userTypes } from "src/api/user";
import { getPermissionCatalog, getPermissionsByUserType, updatePermissionsByUserType } from "src/api/permission";
import { useI18n } from "vue-i18n";
import { useRoute, useRouter } from "vue-router";
import { useSubmitHandler } from "src/composables/useSubmitHandler";

import SettingsTabsHeader from "./components/SettingsTabsHeader.vue";

const route  = useRoute();
const router = useRouter();

const { t } = useI18n();

const catalog         = ref([]);
const expanded        = ref([]);
const treeNodes       = ref([]);
const ticked          = ref([]);
const originalTicked  = ref([]);
const loadingTree     = ref(false);
const userTypeOptions = ref([]);

const draftUserType = ref({
  description: "",
});

const currentUserTypeId = computed(() => Number(route.params.userTypeId || 0));

const currentUserType = computed(() =>
  userTypeOptions.value.find((option) => option.id === currentUserTypeId.value) || null,
);

const hasChanges = computed(() => {
  return JSON.stringify([...ticked.value].sort()) !==
    JSON.stringify([...originalTicked.value].sort());
});

const isCreateMode = computed(() => !route.params.userTypeId);


const isProtectedUserType = computed(() =>
  !isCreateMode.value && isLockedUserTypePermission(currentUserType.value),
);

const isReadOnly = computed(() => isProtectedUserType.value);

const pageTitle = computed(() => {
  if (isCreateMode.value) {
    return t("settings.user_types.create_title");
  }

  return t("settings.user_types.edit_title", {
    userType: selectedUserTypeLabel.value,
  });
});

const pageDescription = computed(() => {
  if (isCreateMode.value) {
    return t("settings.user_types.create_description");
  }

  return t("settings.user_types.edit_description");
});

const readonlyBannerMessage = computed(() => {
  if (isProtectedUserType.value) {
    return t("settings.user_types.readonly_banner");
  }

  return "";
});

const saveDisabled = computed(() => {
  if (isCreateMode.value) {
    return isReadOnly.value || !draftUserType.value.description.trim();
  }

  return isReadOnly.value || !hasChanges.value;
});

const selectedUserTypeLabel = computed(() => {
  return currentUserType.value?.label || "";
});


const { execute, loading, serverErrors } = useSubmitHandler((response) => {
  if (isCreateMode.value) {
    router.push({
      name: "SettingsUserTypeEditPage", params: { userTypeId: response.id },
    });

    return;
  }

  originalTicked.value = [...ticked.value];
});

const fetchPermissionTree = async () => {
  loadingTree.value = true;

  try {
    const [catalogResponse, assignedResponse] = await Promise.all([
      getPermissionCatalog(),
      isCreateMode.value
        ? Promise.resolve([])
        : getPermissionsByUserType(currentUserTypeId.value),
    ]);

    catalog.value   = catalogResponse;
    treeNodes.value = buildPermissionTreeNodes(
      catalogResponse,
      assignedResponse,
      t,
      isReadOnly.value,
    );
    ticked.value    = buildTickedKeys(catalogResponse, assignedResponse);
    expanded.value  = [];

    originalTicked.value = [...ticked.value];
  } finally {
    loadingTree.value = false;
  }
};

const fetchUserTypeOptions = async () => {
  const response = await userTypes();

  userTypeOptions.value = normalizeUserTypeOptions(response, t);
};

const onSubmit = async () => {
  if (isCreateMode.value) {
    await execute(async () => {
      const createdUserType = await createUserType({
        description: draftUserType.value.description.trim().toLowerCase(),
      });

      const permissions = buildPermissionPayloadFromTicked(ticked.value);

      if (permissions.length) {
        await updatePermissionsByUserType(createdUserType.id, permissions);
      }

      return createdUserType;
    });

    return;
  }

  const permissions = buildPermissionPayloadFromTicked(ticked.value);

  await execute(async () => {
    return await updatePermissionsByUserType(currentUserTypeId.value, permissions);
  });
};

const onTickedUpdate = (nextTicked) => {
  if (isReadOnly.value) {
    return;
  }

  ticked.value = [...nextTicked];
};

onMounted(async () => {
  await fetchUserTypeOptions();
  await fetchPermissionTree();
});
</script>

<style scoped lang="scss">
.settings-card {
  border-radius: 18px;
}

.permission-tree {
  border:        1px solid rgba(14, 52, 91, 0.12);
  border-radius: 16px;
  padding:       16px;
  min-height:    420px;
}

</style>
