<template>
  <q-dialog ref="dialogRef" full-height @hide="onDialogHide">
    <q-card
      class="column no-wrap"
      style="width: 100%; max-width: 95vw; height: 100%"
    >
      <DefaultDialogHeader
        :title="`Permissões: ${group.label}`"
        @close="onDialogCancel"
      />

      <q-card-section class="col column no-wrap q-pa-none" style="min-height: 0">
        <div class="row items-stretch col no-wrap" style="min-height: 0">
          <!-- Menu -->
          <div class="col-12 col-md-6 column no-wrap" style="min-height: 0">
            <div class="text-center text-subtitle1 text-weight-medium q-pa-sm">
              Menu
            </div>
            <q-separator />

            <q-inner-loading :showing="loading" />

            <q-list v-if="!loading" separator class="col scroll">
              <q-item
                v-for="item in menus"
                :key="item.scope"
                clickable
                :active="selectedScope === item.scope"
                active-class="bg-blue-1 text-primary"
                @click="selectedScope = item.scope"
              >
                <q-item-section avatar>
                  <q-icon :name="item.icon" color="dark" />
                </q-item-section>

                <q-item-section>
                  <q-item-label>
                    {{ item.label }}
                    <q-icon
                      v-if="item.children?.length"
                      name="mdi-chevron-right"
                      size="16px"
                      class="q-ml-xs"
                    />
                  </q-item-label>
                  <q-item-label caption>
                    <PermissionLevelBadges :bits="bitsFor(item.scope)" />
                  </q-item-label>
                </q-item-section>

                <q-item-section side>
                  <q-btn
                    flat
                    round
                    dense
                    icon="mdi-pencil-outline"
                    color="dark"
                    @click.stop
                  >
                    <q-tooltip>Editar permissões</q-tooltip>
                    <PermissionLevelMenu
                      :bits="bitsFor(item.scope)"
                      :available-bits="availableBitsFor(item.scope)"
                      @update:bits="(value) => setBits(item.scope, value)"
                    />
                  </q-btn>
                </q-item-section>
              </q-item>
            </q-list>
          </div>

          <q-separator vertical />

          <!-- SubCategorias -->
          <div class="col column no-wrap" style="min-height: 0">
            <div class="text-center text-subtitle1 text-weight-medium q-pa-sm">
              SubCategorias
            </div>
            <q-separator />

            <div
              v-if="!selected"
              class="col column flex-center text-center text-foreground q-pa-md"
            >
              <div>Nenhum menu selecionado!</div>
              <div class="text-caption">
                ← Selecione um menu à esquerda para carregar as subcategorias.
              </div>
            </div>

            <div
              v-else-if="!children.length"
              class="col column flex-center text-center text-foreground q-pa-md"
            >
              <div>Nenhuma subcategoria</div>
              <div class="text-caption">
                O menu "{{ selected.label }}" não possui subcategorias.
              </div>
            </div>

            <q-list v-else separator class="col scroll">
              <q-item v-for="child in children" :key="child.scope">
                <q-item-section avatar>
                  <q-icon :name="child.icon" color="dark" />
                </q-item-section>

                <q-item-section>
                  <q-item-label>{{ child.label }}</q-item-label>
                  <q-item-label caption>
                    <PermissionLevelBadges :bits="bitsFor(child.scope)" />
                  </q-item-label>
                </q-item-section>

                <q-item-section side>
                  <q-btn
                    flat
                    round
                    dense
                    icon="mdi-pencil-outline"
                    color="dark"
                  >
                    <q-tooltip>Editar permissões</q-tooltip>
                    <PermissionLevelMenu
                      :bits="bitsFor(child.scope)"
                      :available-bits="availableBitsFor(child.scope)"
                      @update:bits="(value) => setBits(child.scope, value)"
                    />
                  </q-btn>
                </q-item-section>
              </q-item>
            </q-list>
          </div>
        </div>
      </q-card-section>

      <q-separator />

      <q-card-actions align="right" class="col-auto q-pa-md">
        <q-btn
          label="Cancelar"
          color="primary"
          outline
          @click="onDialogCancel"
        />
        <q-btn
          label="Salvar"
          color="primary"
          :loading="saving"
          :disable="loading"
          @click="onSave"
        />
      </q-card-actions>
    </q-card>
  </q-dialog>
</template>

<script setup>
import { computed, onMounted, ref } from "vue";
import { Notify, useDialogPluginComponent } from "quasar";
import DefaultDialogHeader from "src/components/defaults/DefaultDialogHeader.vue";
import PermissionLevelBadges from "src/pages/permissions/components/PermissionLevelBadges.vue";
import PermissionLevelMenu from "src/pages/permissions/components/PermissionLevelMenu.vue";
import {
  getUserTypePermissions,
  updateUserTypePermissions,
} from "src/api/user_type";
import {
  FRANCHISOR_PERMISSION_MENUS,
  applyComputedLevels,
} from "src/pages/permissions/permission_menus";

const { group } = defineProps({
  group: {
    type: Object,
    required: true,
  },
});

defineEmits([...useDialogPluginComponent.emits]);

const { dialogRef, onDialogHide, onDialogOK, onDialogCancel } =
  useDialogPluginComponent();

const loading = ref(false);
const saving = ref(false);
const selectedScope = ref(null);

// permission_id e bits atuais do grupo, indexados pelo scope do menu.
const permissionIdByScope = ref({});
const bitsByScope = ref({});
const availableBitsByScope = ref({});

const menus = computed(() =>
  FRANCHISOR_PERMISSION_MENUS.filter(
    (menu) => permissionIdByScope.value[menu.scope] !== undefined,
  ),
);

const selected = computed(
  () => menus.value.find((menu) => menu.scope === selectedScope.value) ?? null,
);

const children = computed(() =>
  (selected.value?.children ?? []).filter(
    (child) => permissionIdByScope.value[child.scope] !== undefined,
  ),
);

const bitsFor = (scope) => bitsByScope.value[scope] ?? 0;
const availableBitsFor = (scope) => availableBitsByScope.value[scope] ?? 0;

const setBits = (scope, value) => {
  bitsByScope.value[scope] = value;
};

const scopesInMenu = () =>
  FRANCHISOR_PERMISSION_MENUS.flatMap((menu) => [
    menu.scope,
    ...(menu.children ?? []).map((child) => child.scope),
  ]);

const fetchPermissions = async () => {
  loading.value = true;
  try {
    const payload = await getUserTypePermissions(group.id);
    const byScope = Object.fromEntries(
      payload.permissions.map((p) => [p.scope, p]),
    );

    permissionIdByScope.value = {};
    bitsByScope.value = {};
    availableBitsByScope.value = {};

    for (const scope of scopesInMenu()) {
      const permission = byScope[scope];
      if (!permission) continue;

      permissionIdByScope.value[scope] = permission.id;
      availableBitsByScope.value[scope] = permission.available_bits;
      // Normaliza dados anteriores à regra (ex.: Visualizar gravado sem Menu).
      bitsByScope.value[scope] = applyComputedLevels(permission.bits);
    }
  } catch {
    Notify.create({
      message: "Não foi possível carregar as permissões do grupo.",
      type: "negative",
    });
  } finally {
    loading.value = false;
  }
};

const onSave = async () => {
  saving.value = true;
  try {
    await updateUserTypePermissions(
      group.id,
      Object.entries(permissionIdByScope.value).map(([scope, id]) => ({
        permission_id: id,
        bits: bitsByScope.value[scope] ?? 0,
      })),
    );
    Notify.create({ message: "Permissões atualizadas.", type: "positive" });
    onDialogOK();
  } catch {
    Notify.create({
      message: "Não foi possível salvar as permissões.",
      type: "negative",
    });
  } finally {
    saving.value = false;
  }
};

onMounted(fetchPermissions);
</script>
