<script setup>
import { q, m, useLight, useAsyncData, useQuasar } from "#imports";
import { ref, reactive, computed } from "vue";
import { LDatabaseCreateTableDialog, LDialogDatabaseFieldAdd } from "#components";
import { Dialog } from "quasar";
const $q = useQuasar();
const light = useLight();
const { data, refresh } = await useAsyncData("database", async () => {
  return await q({
    system: {
      database: {
        table: true,
        type: true,
        version: true,
        tableStatus: true
      }
    }
  }).then((res) => res.system.database);
});
const SYSTEM_TABLES = ["Config", "EventLog", "MailLog", "Permission", "Role", "SystemValue", "Translate", "User", "UserLog", "UserRole", "MyFavorite", "CustomField", "Revision"];
const custom_tables = computed(() => {
  return (data.value?.tableStatus ?? []).filter((table) => !SYSTEM_TABLES.includes(table.Name));
});
const systables = computed(() => {
  return (data.value?.tableStatus ?? []).filter((table) => SYSTEM_TABLES.includes(table.Name));
});
const selected = reactive({});
const add = async (table) => {
  $q.dialog({
    component: LDialogDatabaseFieldAdd
  }).onOk(async (data2) => {
    try {
      await m("lightDatabaseAddField", {
        table,
        field: data2.name,
        type: data2.type,
        length: data2.length,
        default: data2.default,
        nullable: data2.nullable,
        autoincrement: data2.autoincrement
      });
      light.notify({
        type: "positive",
        message: "Field added successfully"
      });
      refresh();
    } catch (e) {
      light.notify({
        type: "negative",
        message: e.message
      });
    }
  });
};
const edit = async (table) => {
  const field = selected[table]?.[0];
  if (!field) return;
  $q.dialog({
    component: LDialogDatabaseFieldAdd,
    componentProps: { field }
  }).onOk(async (data2) => {
    try {
      await m("lightDatabaseEditField", {
        table,
        field: data2.name,
        type: data2.type,
        length: data2.length,
        default: data2.default,
        nullable: data2.nullable,
        autoincrement: data2.autoincrement
      });
      light.notify({ type: "positive", message: "Field updated successfully" });
      refresh();
    } catch (e) {
      light.notify({ type: "negative", message: e.message });
    }
  });
};
if (data.value?.table) {
  for (let table of data.value.table) {
    selected[table.name] = [];
  }
}
const removeField = async (table) => {
  light.dialog({
    title: "Remove field",
    message: "Are you sure you want to remove the selected fields?",
    ok: "Yes",
    cancel: "No"
  }).onOk(async () => {
    try {
      await m("lightDatabaseRemoveFields", {
        table,
        fields: selected[table].map((field) => field.name)
      });
      light.notify({
        type: "positive",
        message: "Fields removed successfully"
      });
      selected[table] = [];
      refresh();
    } catch (e) {
      light.notify({
        type: "negative",
        message: e.message
      });
    }
  });
};
const createTable = () => {
  Dialog.create({
    component: LDatabaseCreateTableDialog
  }).onOk(async (data2) => {
    try {
      await m("lightDatabaseCreateTable", {
        name: data2.name,
        fields: data2.fields
      });
      light.notify({
        type: "positive",
        message: "Table created successfully"
      });
    } catch (e) {
      light.notify({
        type: "negative",
        message: e.message
      });
    }
    refresh();
  });
};
const selectedTable = ref([]);
const removeTable = async () => {
  light.dialog({
    title: "Remove table",
    message: "Are you sure you want to remove the selected tables?",
    ok: "Yes",
    cancel: "No"
  }).onOk(async () => {
    const tables = selectedTable.value.map((table) => table.Name);
    try {
      for (let table of tables) {
        await m("lightDatabaseRemoveTable", {
          table
        });
      }
    } catch (e) {
      light.notify({
        type: "negative",
        message: e.message
      });
      return;
    }
    light.notify({
      type: "positive",
      message: "Tables removed successfully"
    });
    selectedTable.value = [];
    refresh();
  });
};
const truncatTable = async () => {
  light.dialog({
    title: "Truncate table",
    message: "Are you sure you want to truncate the selected tables?",
    ok: "Yes",
    cancel: "No"
  }).onOk(async () => {
    const tables = selectedTable.value.map((table) => table.Name);
    try {
      for (let table of tables) {
        await m("lightDatabaseTruncateTable", {
          table
        });
      }
    } catch (e) {
      light.notify({
        type: "negative",
        message: e.message
      });
      return;
    }
    light.notify({
      type: "positive",
      message: "Tables truncated successfully"
    });
    selectedTable.value = [];
    refresh();
  });
};
</script>

<template>
    <l-page title="Database">

        <l-card>
            <l-list>
                <l-item label="Type">{{ data.type }}</l-item>
                <l-item label="Version">{{ data.version }}</l-item>
            </l-list>
        </l-card>

        <l-card>
            <q-expansion-item label="Custom Tables" dense header-class="text-weight-medium">
                <q-table :rows="custom_tables" hide-pagination flat separator="cell" dense :rows-per-page-options="[0]"
                    v-model:selected="selectedTable" selection="multiple" row-key="Name" class="q-ma-sm">
                    <template #top>
                        <div class="row items-center q-gutter-sm">
                            <q-btn icon="sym_o_add" @click="createTable" flat size="sm" label="Add Table"
                                color="primary" />
                            <q-btn icon="sym_o_delete" @click="removeTable" :disable="selectedTable.length == 0"
                                label="Remove" flat size="sm" color="negative" />
                            <q-btn icon="sym_o_scan_delete" @click="truncatTable" :disable="selectedTable.length == 0"
                                label="Truncate" flat size="sm" color="warning" />
                        </div>
                    </template>
                </q-table>
            </q-expansion-item>

            <q-separator />

            <q-expansion-item label="System Tables" dense header-class="text-weight-medium">
                <q-table :rows="systables" hide-pagination flat separator="cell" dense :rows-per-page-options="[0]"
                    row-key="Name" class="q-ma-sm" />
            </q-expansion-item>
        </l-card>

        <l-card title="Tables">
            <q-expansion-item v-for="table in data.table" :key="table.name" :label="table.name" dense
                header-class="text-weight-medium">
                <q-table row-key="name" :rows="table.columns" :rows-per-page-options="[0]" hide-pagination flat
                    separator="cell" dense selection="multiple" v-model:selected="selected[table.name]" class="q-ma-sm">
                    <template #top>
                        <div class="row items-center q-gutter-sm">
                            <q-btn icon="sym_o_add" @click="add(table.name)" flat size="sm" label="Add Field"
                                color="primary" />
                            <q-btn icon="sym_o_edit" @click="edit(table.name)"
                                :disable="selected[table.name]?.length !== 1" label="Edit Field" flat size="sm"
                                color="secondary" />
                            <q-btn icon="sym_o_delete" @click="removeField(table.name)"
                                :disable="selected[table.name]?.length == 0" label="Remove Field" flat size="sm"
                                color="negative" />
                        </div>
                    </template>
                </q-table>
            </q-expansion-item>
        </l-card>

    </l-page>
</template>
