<template>
  <div class="has-text-black">
    <div>{{ row.code }} / {{ isVietnamese ? row.name : row.en }} {{ $lang('access-right') }}:</div>
    <div class="mt-2">
      <span class="icon-text mr-6" v-for="v in options" @click="changeOption(v)">
        <a>
          <SvgIcon
            v-bind="{
              name: option === v.code ? 'radio-checked.svg' : 'radio-unchecked.svg',
              type: option === v.code ? 'blue' : 'gray',
              size: 25,
            }"
          />
        </a>
        <b class="fs-18">{{ v[$store.lang === 'en' ? 'en' : 'name'] }}</b>
      </span>
    </div>
    <aside class="menu">
      <ul class="menu-list" v-for="v in topmenu">
        <li>
          <div class="field is-grouped has-background-light has-text-black py-2 px-3">
            <div class="control is-expanded">
              <b>{{ v[$store.lang] }}</b>
            </div>
            <div class="control" v-if="v.submenu.length === 0 && option === 'limit'">
              <span class="ml-6 is-clickable" @click="changeTick(v)">
                <SvgIcon
                  v-bind="{
                    name: v.checked ? 'checked.svg' : 'uncheck.svg',
                    type: v.checked ? 'blue' : 'gray',
                    size: 25,
                  }"
                ></SvgIcon>
              </span>
            </div>
            <div v-if="v.submenu.length > 0 && option === 'limit'">
              <span class="ml-6 is-clickable" @click="changeViewAll(v)" title="Chọn tất cả">
                <SvgIcon
                  v-bind="{
                    name: 'view.svg',
                    type: 'gray',
                    size: 25,
                  }"
                ></SvgIcon>
              </span>
              <span class="ml-6 is-clickable" @click="changeEditAll(v)" title="Chọn tất cả">
                <SvgIcon
                  v-bind="{
                    name: 'edit1.svg',
                    type: 'gray',
                    size: 25,
                  }"
                ></SvgIcon>
              </span>
            </div>
          </div>
          <ul>
            <li class="border-bottom" v-for="x in v.submenu">
              <div class="field is-grouped py-1">
                <div class="control is-expanded">
                  <span class="icon-text">
                    <span>{{ x[$store.lang] }}</span>
                  </span>
                </div>
                <div class="control" v-if="option === 'limit'">
                  <span class="ml-6 is-clickable" @click="changeTick(x, v)" title="Xem thông tin">
                    <SvgIcon
                      v-bind="{
                        name: x.checked ? 'checked.svg' : 'uncheck.svg',
                        type: x.checked ? 'blue' : 'gray',
                        size: 25,
                      }"
                    />
                  </span>
                  <span class="ml-6 is-clickable" @click="changeEdit(x, v)" title="Chỉnh sửa thông tin">
                    <SvgIcon
                      v-bind="{
                        name: x.checked && x.is_edit === true ? 'checked.svg' : 'uncheck.svg',
                        type: x.checked && x.is_edit === true ? 'blue' : 'gray',
                        size: 25,
                      }"
                    ></SvgIcon>
                  </span>
                </div>
              </div>
            </li>
          </ul>
        </li>
      </ul>
    </aside>
  </div>
</template>
<script setup>
const { $getdata, $filter, $find, $insertapi, $deleteapi, $store, $updateapi } = useNuxtApp();

const props = defineProps({
  row: Object,
  api: String,
  setting: String,
});

const isVietnamese = computed(() => $store.lang.toLowerCase() === 'vi');

const options = [
  { code: 'all', name: 'Tất cả tính năng', en: 'All functions' },
  { code: 'limit', name: 'Bị giới hạn', en: 'Limited functions' },
];

const option = ref('limit');
const topmenu = ref([]);
let loanRights = [];

const rows = await $getdata(props.setting, {
  category__in: ['topmenu', 'submenu'],
});

async function getRights(first) {
  loanRights = await $getdata(props.api, { group: props.row.id });
  if (loanRights.length === 0 && first) {
    option.value = 'all';
  }

  const rights = $filter(rows, { category: 'topmenu' });

  rights
    .sort((a, b) => (a.index ?? 0) - (b.index ?? 0))
    .forEach((parent) => {
      const subs = $filter(rows, {
        category: 'submenu',
        classify: parent.code,
      });

      subs
        .sort((a, b) => (a.index ?? 0) - (b.index ?? 0))
        .forEach((sub) => {
          const found = $find(loanRights, { setting: sub.id });
          sub.checked = !!found;
          sub.is_edit = found?.is_edit || null;
          sub.rightId = found?.id || null;
        });

      const foundParent = $find(loanRights, { setting: parent.id });
      parent.rightId = foundParent?.id || null;

      parent.checked = subs.length ? subs.some((s) => s.checked) : !!foundParent;

      parent.submenu = subs;
    });
  topmenu.value = [...rights];
}

async function changeTick(x, v) {
  if (x.checked) {
    x.checked = false;
    const deleteId = x.rightId;
    if (deleteId) {
      await $deleteapi(props.api, deleteId);
      x.rightId = null;
    }

    if (v) {
      const stillChecked = v.submenu.some((s) => s.checked);
      if (!stillChecked) {
        const parentDelete = v.rightId;
        v.checked = false;
        v.rightId = null;

        if (parentDelete) {
          await $deleteapi(props.api, parentDelete);
        }
      }
    }
  }

  // ===== CHECK =====
  else {
    x.checked = true;
    x.is_edit = false;
    const obj = await $insertapi(props.api, { setting: x.id, group: props.row.id, is_edit: false }, undefined, false);

    if (obj) x.rightId = obj.id;

    if (v && !v.checked) {
      v.checked = true;
      v.is_edit = false;
      const parentObj = await $insertapi(
        props.api,
        { setting: v.id, group: props.row.id, is_edit: false },
        undefined,
        false,
      );

      if (parentObj) v.rightId = parentObj.id;
    }
  }

  topmenu.value = [...topmenu.value];
}

async function changeOption(v) {
  option.value = v.code;
  loanRights = await $getdata(props.api, { group: props.row.id });

  if (v.code === 'all') {
    if (loanRights?.length > 0) {
      await Promise.all(loanRights.map((item) => $deleteapi(props.api, item.id)));
    }

    topmenu.value.forEach((p) => {
      p.checked = false;
      p.rightId = null;
      p.submenu?.forEach((s) => {
        s.checked = false;
        s.rightId = null;
      });
    });

    topmenu.value = [...topmenu.value];
  } else {
    await getRights();
  }
}

async function changeEdit(x, v) {
  if (x.checked) {
    const deleteId = x.rightId;

    if (deleteId) {
      await $updateapi(props.api, {
        id: x.rightId,
        setting: x.id,
        group: props.row.id,
        is_edit: !x.is_edit,
      });
    }
    x.is_edit = !x.is_edit;
    x.rightId = null;
  }

  // ===== CHECK =====
  else {
    x.checked = true;
    x.is_edit = true;
    const obj = await $insertapi(props.api, { setting: x.id, group: props.row.id, is_edit: true }, undefined, false);

    if (obj) x.rightId = obj.id;

    if (v && !v.checked) {
      v.checked = true;

      const parentObj = await $insertapi(
        props.api,
        { setting: v.id, group: props.row.id, is_edit: false },
        undefined,
        false,
      );

      if (parentObj) v.rightId = parentObj.id;
    }
  }

  topmenu.value = [...topmenu.value];
}

async function changeViewAll(v) {
  try {
    const hasSubmenu = v?.submenu?.length > 0;

    const isAllChecked = hasSubmenu ? v.submenu.every((s) => s.checked === true) : v.checked;

    // ================= UNCHECK ALL =================
    if (isAllChecked) {
      v.checked = false;
      v.is_edit = false;

      // Chỉ delete parent nếu có quyền
      if (v.rightId) {
        await $deleteapi(props.api, v.rightId);
        v.rightId = null;
      }

      if (hasSubmenu) {
        const needDelete = v.submenu.filter((item) => item.rightId);

        await Promise.all(needDelete.map((item) => $deleteapi(props.api, item.rightId)));

        // Update state local
        v.submenu.forEach((item) => {
          item.rightId = null;
          item.checked = false;
          item.is_edit = false;
        });
      }
    }

    // ================= CHECK ALL =================
    else {
      v.checked = true;
      v.is_edit = false;

      // Chỉ insert parent nếu chưa có
      if (!v.rightId) {
        const parentObj = await $insertapi(
          props.api,
          { setting: v.id, group: props.row.id, is_edit: false },
          undefined,
          false,
        );

        if (parentObj) v.rightId = parentObj.id;
      }

      if (hasSubmenu) {
        const needInsert = v.submenu.filter((item) => !item.rightId);

        await Promise.all(
          needInsert.map(async (item) => {
            const obj = await $insertapi(
              props.api,
              { setting: item.id, group: props.row.id, is_edit: false },
              undefined,
              false,
            );

            if (obj) item.rightId = obj.id;
          }),
        );

        // Update state local
        v.submenu.forEach((item) => {
          item.checked = true;
          item.is_edit = false;
        });
      }
    }

    // Force reactive
    topmenu.value = [...topmenu.value];
  } catch (err) {
    console.error('changeViewAll error:', err);
  }
}

async function changeEditAll(v) {
  try {
    if (!v?.submenu?.length) return;

    const isAllEdit = v.submenu.every((item) => item.is_edit === true);
    const newEditState = !isAllEdit;

    // Parent luôn phải được check
    v.checked = true;
    v.is_edit = false;

    // Chỉ insert parent nếu chưa có quyền
    if (!v.rightId) {
      const parentObj = await $insertapi(
        props.api,
        { setting: v.id, group: props.row.id, is_edit: false },
        undefined,
        false,
      );

      if (parentObj) v.rightId = parentObj.id;
    }

    // ===== CHỈ LẤY NHỮNG ITEM CẦN THAO TÁC =====
    const needUpdate = v.submenu.filter((item) => item.rightId && item.is_edit !== newEditState);

    const needInsert = v.submenu.filter((item) => !item.rightId);

    // Update những item cần đổi is_edit
    await Promise.all(
      needUpdate.map((item) =>
        $updateapi(props.api, {
          id: item.rightId,
          setting: item.id,
          group: props.row.id,
          is_edit: newEditState,
        }),
      ),
    );

    // Insert những item chưa có quyền
    await Promise.all(
      needInsert.map(async (item) => {
        const obj = await $insertapi(
          props.api,
          {
            setting: item.id,
            group: props.row.id,
            is_edit: newEditState,
          },
          undefined,
          false,
        );

        if (obj) item.rightId = obj.id;
      }),
    );

    // ===== UPDATE STATE LOCAL =====
    v.submenu.forEach((item) => {
      item.checked = true;
      item.is_edit = newEditState;
    });

    // Force reactive
    topmenu.value = [...topmenu.value];
  } catch (err) {
    console.error('changeEditAll error:', err);
  }
}

await getRights(true);
</script>
