<script setup lang="ts">
import { QTableProps } from 'quasar';
import { ref, toRaw, onMounted } from 'vue';
import { dialog } from 'stores/utils';
import { useI18n } from 'vue-i18n';
import TableComponents from 'src/components/TableComponents.vue';
import ShowAttachent from 'src/components/ShowAttachent.vue';
import DialogForm from 'components/DialogForm.vue';

const isEdit = ref(false);
const { t } = useI18n();
const obj = defineModel<
  {
    _meta?: Record<string, any>;
    name?: string;
    group?: string;
    url?: string;
    file?: File;
  }[]
>({
  default: [],
});

const modalDialog = ref<boolean>(false);

const splitAttachment = ref<number>(50);

const currentIndex = ref<number>(-1);

const statusOcr = ref<boolean>(false);

const props = defineProps<{
  showTitle?: boolean;
  ocr?: (
    group: any,
    file: File,
  ) => void | Promise<{
    status: boolean;
    group: string;
    meta: { name: string; value: string }[];
  }>;
  getFileList?: (group: any) => Promise<typeof obj.value>;
  deleteItem?: (obj: any) => void | Promise<boolean>;
  download?: (obj: any) => void;
  save?: (
    group: any,
    meta: any,
    file: File | undefined,
  ) => void | Promise<boolean>;
  autoSave?: boolean;
  readonly?: boolean;
  hideAction?: boolean;
  columns: QTableProps['columns'];
  menu?: { label: string; value: string; _meta?: Record<string, any> }[];
}>();

async function triggerDelete(item: any) {
  dialog({
    color: 'negative',
    icon: 'mdi-alert',
    title: t('dialog.title.confirmDelete'),
    actionText: t('general.delete'),
    message: t('dialog.message.confirmDelete'),
    action: async () => {
      if (
        !props.autoSave ||
        !obj.value[currentIndex.value]?._meta?.hasOwnProperty('id')
      ) {
        obj.value.splice(currentIndex.value, 1);
      } else {
        await props.deleteItem?.(item);
        await fileList();
      }
    },
    cancel: () => {},
  });
}

function browse() {
  inputFile?.click();
}

const inputFile = (() => {
  const _element = document.createElement('input');
  _element.type = 'file';
  _element.accept = 'image/jpeg,image/png';
  _element.addEventListener('change', change);
  return _element;
})();

const selectedMenu = ref<NonNullable<typeof props.menu>[number]>();

async function change(e: Event) {
  const _element = e.target as HTMLInputElement | null;
  const _file = _element?.files?.[0];

  if (_file) {
    if (!obj.value[currentIndex.value] && selectedMenu.value) {
      currentIndex.value = obj.value.length;
      obj.value = [
        ...obj.value,
        {
          _meta: structuredClone(toRaw(selectedMenu.value)._meta || {}),
          group: selectedMenu.value?.value,
          file: _file,
        },
      ];
    }

    const reader = new FileReader();
    reader.readAsDataURL(_file);
    reader.onload = () => {
      if (obj.value[currentIndex.value]) {
        obj.value[currentIndex.value].url = reader.result as string;
      }
    };

    statusOcr.value = true;
    const resOcr = await props.ocr?.(selectedMenu.value?.value, _file);

    if (resOcr?.status) {
      modalDialog.value = true;
      const map = resOcr.meta.reduce<Record<string, string>>((a, c) => {
        a[c.name] = c.value;
        return a;
      }, {});

      if (resOcr.group === 'citizen') {
        obj.value[currentIndex.value]._meta = {
          citizenId: map['citizen_id'],
          firstName: map['firstname'],
          lastName: map['lastname'],
          firstNameEN: map['firstname_en'],
          lastNameEN: map['lastname_en'],
          birthDate: map['birth_date'],
          religion: map['religion'],
          issueDate: map['issue_date'],
          expireDate: map['expire_date'],
        };
      }

      if (resOcr.group === 'passport') {
        obj.value[currentIndex.value]._meta = {
          type: map['doc_type'],
          number: map['doc_number'],
          issueDate: map['issue_date'],
          expireDate: map['expire_date'],
          issuePlace: map['nationality'],
          issueCountry: map['country'],
        };
      }

      if (resOcr.group === 'visa') {
        obj.value[currentIndex.value]._meta = {
          type: map['visa_type'],
          number: map['visa_no'],
          issueDate: map['valid_until'],
          expireDate: map['expire_date'],
          issuePlace: map['issue_place'],
        };
      }

      statusOcr.value = false;
    }
  }
}

async function fileList() {
  if (props.getFileList) {
    const res = await props.getFileList(selectedMenu.value?.value);

    if (res && Array.isArray(res)) {
      obj.value = [...res];
    }
  }
}

defineEmits<{
  (e: 'submit', obj: any): void;
}>();
</script>

<template>
  <div v-if="!!showTitle" class="col-11 q-pb-sm text-weight-bold text-body1">
    <q-icon
      flat
      size="xs"
      class="q-pa-sm rounded q-mr-xs"
      color="info"
      name="mdi-account-outline"
      style="background-color: var(--surface-3)"
    />
    {{ $t('general.upload', { msg: $t('general.attachment') }) }}
  </div>

  <div
    class="relative-position full-width row no-wrap wrapper"
    style="height: 250px"
  >
    <div class="col-3 full-height column no-wrap">
      <div class="q-pa-sm text-center bordered" style="height: 50px">
        <q-btn-dropdown
          :disable="readonly"
          icon="mdi-upload"
          color="info"
          :label="$t('general.uploadFile')"
        >
          <q-list v-for="(v, i) in menu" :key="v.value">
            <q-item
              clickable
              v-close-popup
              @click="
                () => {
                  isEdit = true;
                  selectedMenu = menu?.[i];
                  currentIndex = obj.length;

                  browse();
                }
              "
            >
              <q-item-section>
                <q-item-label>{{ $t(v.label) }}</q-item-label>
              </q-item-section>
            </q-item>
          </q-list>
        </q-btn-dropdown>
      </div>

      <div class="bordered-l bordered-b q-pa-sm col full-height scroll">
        <template v-if="menu != undefined">
          <q-item
            clickable
            v-for="v in menu"
            :key="v.value"
            dense
            type="button"
            class="no-padding items-center rounded full-width"
            active-class="menu-active"
            :active="selectedMenu?.value === v.value"
            @click="
              async () => {
                selectedMenu = v;
                if (autoSave) {
                  fileList();
                }
              }
            "
          >
            <span class="q-px-md ellipsis q-pa-sm" style="font-size: 16px">
              {{ $t(v.label) }}
            </span>
          </q-item>
        </template>
      </div>
    </div>

    <div
      v-if="obj"
      class="bordered col surface-2 column items-center no-wrap scroll"
    >
      <slot name="content">
        <template v-if="columns !== undefined">
          <div class="full-width q-pa-md">
            <TableComponents
              buttomDownload
              @download="
                (index) => {
                  download?.(obj[index]);
                }
              "
              @delete="
                async (index) => {
                  currentIndex = index;
                  await triggerDelete(obj[index]);
                }
              "
              @view="
                (index) => {
                  isEdit = false;
                  currentIndex = index;
                  modalDialog = true;
                }
              "
              @edit="
                (index) => {
                  isEdit = true;
                  currentIndex = index;
                  modalDialog = true;
                }
              "
              :rows="
                obj
                  .filter((v) => {
                    if (!autoSave && v.group !== selectedMenu?.value) {
                      return false;
                    }
                    return true;
                  })
                  .map((v, index) => {
                    return {
                      id: v._meta?.id,
                      branchNo: index + 1,
                      attachmentName: v.file?.name || v.name,
                      uploadDate: '',
                    };
                  })
              "
              :columns="columns"
            ></TableComponents>
          </div>
        </template>
      </slot>
    </div>
    <q-inner-loading
      :showing="statusOcr"
      label="Please wait..."
      label-class="text-teal"
      label-style="font-size: 1.1em"
    />
  </div>
  <DialogForm
    edit
    hideDelete
    :is-edit="isEdit"
    style="position: absolute"
    height="100vh"
    weight="90%"
    v-model:modal="modalDialog"
    title="ดูตัวอย่าง"
    hideCloseEvent
    v-if="obj.length > 0"
    :undo="
      () => {
        isEdit = false;
      }
    "
    :edit-data="
      () => {
        isEdit = !isEdit;
      }
    "
    :close="
      () => {
        if (!autoSave || !obj[currentIndex]?._meta?.hasOwnProperty('id')) {
          obj.splice(currentIndex, 1);
        }
        modalDialog = false;
      }
    "
    :submit="
      async () => {
        modalDialog = false;
        if (autoSave === true) {
          const statusSave = await save?.(
            obj[currentIndex].group,
            obj[currentIndex]._meta,
            obj[currentIndex].file,
          );

          if (statusSave) {
            fileList();
          }
        }
      }
    "
  >
    <q-splitter class="full-height" v-model="splitAttachment">
      <template v-slot:before>
        <div class="full-height">
          <ShowAttachent
            v-if="obj[currentIndex]"
            :url="obj[currentIndex].url || ''"
            :file="obj[currentIndex].file"
          />
        </div>
      </template>
      <template v-slot:after>
        <div class="q-pa-md">
          <slot
            v-if="obj[currentIndex]"
            name="form"
            :mode="obj[currentIndex].group"
            :meta="obj[currentIndex]._meta"
            :isEdit="isEdit"
          />
        </div>
      </template>
    </q-splitter>
  </DialogForm>
</template>

<style lang="scss">
.wrapper > * {
  height: 300px;
}

.menu-active {
  background-color: hsla(var(--info-bg) / 0.1);
  color: hsl(var(--info-bg));
}
</style>
