<script setup lang="ts">
import { ref, watch, onMounted, nextTick, reactive } from 'vue';
import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { useRoute, useRouter } from 'vue-router';
import { canAccess } from 'stores/utils';

import type { District, Province, SubDistrict } from 'src/stores/address';
import useCustomerStore from 'stores/customer';
import useEmployeeStore from 'stores/employee';
import useAddressStore from 'src/stores/address';
import useFlowStore from 'stores/flow';
import { dialog } from 'stores/utils';
import { useNavigator } from 'src/stores/navigator';
import { Status } from 'stores/types';
import {
  CustomerStats,
  Customer,
  CustomerBranch,
  CustomerType,
} from 'stores/customer/types';

import { SaveButton } from 'components/button';
import TabCustomer from './TabCustomer.vue';
import FloatingActionButton from 'components/FloatingActionButton.vue';
import StatCardComponent from 'components/StatCardComponent.vue';
import BranchPage from './BranchPage.vue';
import SelectBusinessType from 'src/components/shared/select/SelectBusinessType.vue';
import AdvanceSearch from 'src/components/shared/AdvanceSearch.vue';
import TabEmployee from './TabEmployee.vue';
import SelectInput from 'src/components/shared/SelectInput.vue';

import { columnsCustomer, columnsEmployee } from './constant';
import { useCustomerForm, useEmployeeForm } from './form';
import { storeToRefs } from 'pinia';

const { t, locale } = useI18n();
const $q = useQuasar();
const route = useRoute();
const router = useRouter();
const flowStore = useFlowStore();
const navigatorStore = useNavigator();
const addressStore = useAddressStore();
const customerStore = useCustomerStore();
const employeeStore = useEmployeeStore();
const customerFormStore = useCustomerForm();
const employeeFormStore = useEmployeeForm();

const { state: customerFormState, currentFormData: customerFormData } =
  storeToRefs(customerFormStore);
const { state: employeeFormState, statusEmployeeCreate } =
  storeToRefs(employeeFormStore);

// NOTE: Component ref
const refTabCustomer = ref<InstanceType<typeof TabCustomer>>();
const refTabEmployee = ref<InstanceType<typeof TabEmployee>>();

// NOTE: Page Data
const currentCustomer = ref<Customer>();

// NOTE: Page State
const hideStats = ref(false);
const gridView = ref(false);
const employeeStats = ref(0);
const inputSearch = ref('');
const filterBusinessType = ref('');
const searchDate = ref<string[]>([]);
const currentTab = ref<'employer' | 'employee'>('employer');
const currentStatus = ref<Status | 'All'>('All');
const customerTypeSelected = ref<{
  label: string;
  value: 'all' | 'customerLegalEntity' | 'customerNaturalPerson';
}>({
  label: t('general.all'),
  value: 'all',
});
const statsCustomerType = ref<CustomerStats>({
  CORP: 0,
  PERS: 0,
});
const fieldDisplayCustomer = ref<
  {
    label: string;
    value: string;
  }[]
>(
  columnsCustomer
    .filter((v) => v.name !== 'action')
    .map((v) => ({ label: v.label, value: v.name })),
);
const fieldDisplayEmployee = ref<
  {
    label: string;
    value: string;
  }[]
>(
  columnsEmployee
    .filter((v) => v.name !== 'action')
    .map((v) => ({ label: v.label, value: v.name })),
);
const fieldSelected = ref<string[]>(
  [
    ...columnsEmployee.map((v) => v.name),
    ...columnsCustomer.map((v) => v.name),
  ].filter((v, index, self) => self.indexOf(v) === index),
);
const filterAddress = reactive({
  provinceId: '',
  districtId: '',
  subDistrictId: '',
});
const addressOpt = reactive<{
  provinceOpt: Province[];
  districtOpt: District[];
  subDistrictOpt: SubDistrict[];
}>({
  provinceOpt: [],
  districtOpt: [],
  subDistrictOpt: [],
});
const fieldCustomer = [
  'all',
  'customerLegalEntity',
  'customerNaturalPerson',
] as const;

// image
const imageList = ref<{ selectedImage: string; list: string[] }>();
const branch = ref<CustomerBranch[]>();

async function triggerChangeStatus(
  id: string,
  status: string,
  employeeName?: string,
) {
  return await new Promise((resolve, reject) => {
    dialog({
      color: status !== 'INACTIVE' ? 'warning' : 'info',
      icon:
        status !== 'INACTIVE' ? 'mdi-alert' : 'mdi-message-processing-outline',
      title: t('dialog.title.confirmChangeStatus'),
      actionText:
        status !== 'INACTIVE' ? t('general.close') : t('general.open'),
      message:
        status !== 'INACTIVE'
          ? t('dialog.message.confirmChangeStatusOff')
          : t('dialog.message.confirmChangeStatusOn'),
      action: async () => {
        if (currentTab.value === 'employee') {
          await refTabEmployee.value
            ?.toggleStatusEmployee(
              id,
              status === 'INACTIVE' ? false : true,
              employeeName,
            )
            .then(resolve)
            .catch(reject);
        } else {
          await refTabCustomer.value
            ?.toggleStatusCustomer(id, status === 'INACTIVE' ? false : true)
            .then(resolve)
            .catch(reject);
        }
      },
      cancel: () => {},
    });
  });
}

async function createCustomerForm(customerType: 'CORP' | 'PERS') {
  customerFormState.value.dialogModal = true;
  customerFormState.value.dialogType = 'create';
  customerFormData.value.customerType =
    customerType === 'CORP' ? CustomerType.Corporate : CustomerType.Person;
}

function createEmployeeForm() {
  employeeFormStore.resetFormDataEmployee(true);
  employeeFormState.value.dialogType = 'create';
  employeeFormState.value.dialogModal = true;
  employeeFormState.value.isEmployeeEdit = true;
}

async function fetchImageList(
  id: string,
  selectedName: string,
  type: 'customer' | 'employee',
) {
  const res =
    type === 'customer'
      ? await customerStore.fetchImageListById(id)
      : await employeeStore.fetchImageListById(id);
  imageList.value = {
    selectedImage: selectedName,
    list: res.map((n: string) => `${type}/${id}/image/${n}`),
  };

  return res;
}

async function triggerExport() {
  switch (currentTab.value) {
    case 'employer':
      customerStore.customerExport({
        pageSize: 10000,
        startDate: searchDate.value[0],
        endDate: searchDate.value[1],
        businessType: filterBusinessType.value,
        province: filterAddress.provinceId || undefined,
        district: filterAddress.districtId || undefined,
        subDistrict: filterAddress.subDistrictId || undefined,
        customerType:
          customerTypeSelected.value.value === 'customerLegalEntity'
            ? CustomerType.Corporate
            : customerTypeSelected.value.value === 'customerNaturalPerson'
              ? CustomerType.Person
              : undefined,
      });

      break;

    case 'employee':
      employeeStore.employeeExport({
        pageSize: 10000,
        startDate: searchDate.value[0],
        endDate: searchDate.value[1],
      });
      break;
  }
}

async function fetchAddressData(type: 'province' | 'district' | 'subDistrict') {
  let result;

  if (type === 'province') {
    result = await addressStore.fetchProvince();
    if (result) addressOpt.provinceOpt = result;
  }

  if (type === 'district') {
    if (!filterAddress.provinceId) return;
    result = await addressStore.fetchDistrictByProvinceId(
      filterAddress.provinceId,
    );
    if (result) addressOpt.districtOpt = result;
  }

  if (type === 'subDistrict') {
    if (!filterAddress.districtId) return;
    result = await addressStore.fetchSubDistrictByProvinceId(
      filterAddress.districtId,
    );
    if (result) addressOpt.subDistrictOpt = result;
  }

  return result;
}

async function handleSelectAddress(type: 'province' | 'district') {
  if (type === 'province') {
    filterAddress.districtId = filterAddress.subDistrictId = '';
    addressOpt.districtOpt = addressOpt.subDistrictOpt = [];

    await fetchAddressData('district');
  }

  if (type === 'district') {
    filterAddress.subDistrictId = '';
    await fetchAddressData('subDistrict');
  }
}

async function init() {
  navigatorStore.current.title = 'menu.customer';
  navigatorStore.current.path = [
    {
      text: 'menu.customerCaption',
      i18n: true,
      handler: () => router.push('/customer-management'),
    },
  ];

  gridView.value = $q.screen.lt.md ? true : false;

  if (route.query.tab === 'customer') {
    currentTab.value = 'employer';
    if (route.query.id)
      refTabCustomer.value?.openSpecificCustomer(route.query.id as string);
  } else if (route.query.tab === 'employee') {
    currentTab.value = 'employee';
    if (route.query.id)
      refTabEmployee.value?.openSpecificEmployee(route.query.id as string);
  }

  if (
    route.name === 'CustomerBranchManagement' &&
    typeof route.params.customerId === 'string'
  ) {
    const _data = await customerStore.fetchById(route.params.customerId);

    if (_data) {
      currentCustomer.value = _data;
      navigatorStore.current.path.push({
        text: `${
          _data.customerType === 'CORP'
            ? _data.branch[0].registerName
            : locale.value === 'eng'
              ? _data.branch[0].firstNameEN + ' ' + _data.branch[0].lastNameEN
              : _data.branch[0].firstName + ' ' + _data.branch[0].lastName
        }`,
        i18n: false,
      });
    } else {
      router.push('/customer-management');
    }
  }

  await fetchAddressData('province');

  flowStore.rotate();
}

watch(() => route.name, init);

watch(locale, () => {
  customerTypeSelected.value = {
    label: `${customerTypeSelected.value.label}`,
    value: customerTypeSelected.value?.value,
  };
});

watch(
  () => $q.screen.lt.md,
  () => $q.screen.lt.md && (gridView.value = true),
);

onMounted(async () => await init());
</script>

<template>
  <FloatingActionButton
    style="z-index: 999"
    :hide-icon="currentTab === 'employee'"
    v-if="$route.name === 'CustomerManagement' && canAccess('customer', 'edit')"
    @click="
      () => {
        if (currentTab === 'employee') {
          createEmployeeForm();
        }
      }
    "
  >
    <q-fab-action
      v-if="currentTab === 'employer'"
      id="add-customer-legal-entity"
      style="color: white; background-color: hsla(var(--violet-11-hsl))"
      @click="createCustomerForm('CORP')"
      padding="xs"
      icon="mdi-office-building-outline"
      :label="$t('general.add') + ' ' + $t('customer.employerLegalEntity')"
      external-label
      label-position="left"
    />
    <q-fab-action
      v-if="currentTab === 'employer'"
      id="add-customer-natural-person"
      :label="$t('general.add') + ' ' + $t('customer.employerNaturalPerson')"
      external-label
      label-position="left"
      @click="createCustomerForm('PERS')"
      style="color: white; background-color: hsla(var(--teal-10-hsl))"
      padding="xs"
      icon="mdi-account-plus-outline"
    />
  </FloatingActionButton>

  <div class="column full-height no-wrap">
    <!-- หน้า table -->
    <div
      v-show="$route.name === 'CustomerManagement'"
      class="column full-height"
    >
      <div class="text-body-2 text-weight-medium q-mb-xs flex items-center">
        {{ $t('general.dataSum') }}
        <q-badge
          rounded
          class="q-ml-sm"
          style="
            background-color: hsla(var(--info-bg) / 0.15);
            color: hsl(var(--info-bg));
          "
        >
          {{
            currentTab === 'employer'
              ? statsCustomerType.PERS + statsCustomerType.CORP
              : employeeStats
          }}
        </q-badge>
        <q-btn
          class="q-ml-sm"
          icon="mdi-pin-outline"
          color="primary"
          size="sm"
          flat
          dense
          rounded
          @click="hideStats = !hideStats"
          :style="hideStats ? 'rotate: 90deg' : ''"
          style="transition: 0.1s ease-in-out"
        />
      </div>

      <!-- stat -->
      <div class="row full-width">
        <transition name="slide">
          <div v-if="!hideStats" class="col-12 q-mb-md">
            <div class="scroll">
              <StatCardComponent
                v-if="statsCustomerType"
                label-i18n
                :branch="
                  currentTab === 'employer'
                    ? [
                        {
                          count: statsCustomerType.CORP ?? 0,
                          label: 'customer.employerLegalEntity',
                          icon: 'mdi-office-building-outline',
                          color: 'purple',
                        },
                        {
                          count: statsCustomerType.PERS ?? 0,
                          label: 'customer.employerNaturalPerson',
                          icon: 'mdi-account-outline',
                          color: 'green',
                        },
                      ]
                    : [
                        {
                          label: 'customer.employee',
                          count: employeeStats,
                          icon: 'mdi-account-outline',
                          color: 'pink',
                        },
                      ]
                "
                :dark="$q.dark.isActive"
              />
            </div>
          </div>
        </transition>
      </div>

      <!-- main -->
      <div
        class="surface-2 bordered rounded col column full-width overflow-hidden"
      >
        <!-- tabs -->
        <div class="column">
          <div
            class="row q-px-md q-py-sm justify-between full-width surface-3 bordered-b"
          >
            <q-input
              for="input-search"
              outlined
              dense
              :label="$t('general.search')"
              class="col col-md-3 q-mr-sm"
              :bg-color="$q.dark.isActive ? 'dark' : 'white'"
              v-model="inputSearch"
              debounce="200"
            >
              <template #prepend>
                <q-icon name="mdi-magnify" />
              </template>
              <template v-slot:append>
                <q-separator vertical inset class="q-mr-xs" />
                <AdvanceSearch
                  v-model="searchDate"
                  :active="
                    ($q.screen.lt.md && currentStatus !== 'All') ||
                    !!filterBusinessType ||
                    !!filterAddress.provinceId
                  "
                >
                  <div
                    v-if="$q.screen.lt.md"
                    class="q-mt-sm text-weight-medium"
                  >
                    {{ $t('general.status') }}
                  </div>
                  <q-select
                    v-if="$q.screen.lt.md"
                    id="select-status"
                    for="select-status"
                    v-model="currentStatus"
                    outlined
                    dense
                    autocomplete="off"
                    option-value="value"
                    option-label="label"
                    map-options
                    emit-value
                    :options="[
                      { label: $t('general.all'), value: 'All' },
                      { label: $t('status.ACTIVE'), value: 'ACTIVE' },
                      { label: $t('status.INACTIVE'), value: 'INACTIVE' },
                    ]"
                  />
                  <template v-if="currentTab === 'employer'">
                    <div class="q-mt-sm text-weight-medium">
                      {{ $t('customer.form.businessType') }}
                    </div>
                    <SelectBusinessType
                      v-model:value="filterBusinessType"
                      clearable
                    />
                    <div class="q-mt-sm text-weight-medium">
                      {{ $t('customer.form.address') }}
                    </div>
                    <SelectInput
                      clearable
                      v-model="filterAddress.provinceId"
                      option-value="id"
                      :label="$t('form.province')"
                      :option="addressOpt.provinceOpt"
                      :option-label="locale === 'eng' ? 'nameEN' : 'name'"
                      @update:model-value="handleSelectAddress('province')"
                    />
                    <SelectInput
                      clearable
                      class="q-mt-sm"
                      option-value="id"
                      v-model="filterAddress.districtId"
                      :option="addressOpt.districtOpt"
                      :label="$t('form.district')"
                      :option-label="locale === 'eng' ? 'nameEN' : 'name'"
                      @update:model-value="handleSelectAddress('district')"
                    />
                    <SelectInput
                      clearable
                      class="q-mt-sm"
                      option-value="id"
                      v-model="filterAddress.subDistrictId"
                      :option="addressOpt.subDistrictOpt"
                      :label="$t('form.subDistrict')"
                      :option-label="locale === 'eng' ? 'nameEN' : 'name'"
                    />
                  </template>
                </AdvanceSearch>
              </template>
            </q-input>

            <SaveButton
              icon-only
              class="q-mr-auto"
              :icon="'material-symbols:download'"
              @click.stop="triggerExport()"
            />

            <div class="row col-md-5" style="white-space: nowrap">
              <q-select
                v-if="$q.screen.gt.sm"
                id="select-status"
                for="select-status"
                v-model="currentStatus"
                outlined
                dense
                autocomplete="off"
                option-value="value"
                option-label="label"
                :class="{ 'offset-md-5': gridView }"
                class="col"
                map-options
                emit-value
                :hide-dropdown-icon="$q.screen.lt.sm"
                :options="[
                  { label: $t('general.all'), value: 'All' },
                  { label: $t('status.ACTIVE'), value: 'ACTIVE' },
                  { label: $t('status.INACTIVE'), value: 'INACTIVE' },
                ]"
              />
              <q-select
                v-if="!gridView"
                id="select-field"
                for="select-field"
                class="q-ml-sm col"
                :options="
                  currentTab === 'employer'
                    ? gridView
                      ? fieldDisplayCustomer.filter((v) => {
                          return (
                            v.value !== 'orderNumber' &&
                            v.value !== 'titleName' &&
                            v.value !== 'address' &&
                            v.value !== 'contactName'
                          );
                        })
                      : fieldDisplayCustomer
                    : fieldDisplayEmployee
                "
                :display-value="$t('general.displayField')"
                :hide-dropdown-icon="$q.screen.lt.sm"
                v-model="fieldSelected"
                :option-label="(l) => $t(l.label)"
                option-value="value"
                autocomplete="off"
                map-options
                emit-value
                outlined
                multiple
                dense
              />

              <q-btn-toggle
                id="btn-mode"
                v-model="gridView"
                dense
                class="no-shadow bordered rounded surface-1 q-ml-sm"
                :toggle-color="$q.dark.isActive ? 'grey-9' : 'grey-2'"
                size="xs"
                :options="[
                  { value: true, slot: 'folder' },
                  { value: false, slot: 'list' },
                ]"
              >
                <template v-slot:folder>
                  <q-icon
                    id="icon-mode-grid"
                    name="mdi-view-grid-outline"
                    size="16px"
                    class="q-px-sm q-py-xs rounded"
                    :style="{
                      color: $q.dark.isActive
                        ? gridView
                          ? '#C9D3DB '
                          : '#787B7C'
                        : gridView
                          ? '#787B7C'
                          : '#C9D3DB',
                    }"
                  />
                </template>
                <template v-slot:list>
                  <q-icon
                    id="icon-mode-list"
                    name="mdi-format-list-bulleted"
                    class="q-px-sm q-py-xs rounded"
                    size="16px"
                    :style="{
                      color: $q.dark.isActive
                        ? gridView === false
                          ? '#C9D3DB'
                          : '#787B7C'
                        : gridView === false
                          ? '#787B7C'
                          : '#C9D3DB',
                    }"
                  />
                </template>
              </q-btn-toggle>
            </div>
          </div>

          <div class="surface-2 bordered-b q-px-md">
            <q-tabs
              dense
              v-model="currentTab"
              align="left"
              class="full-height"
              active-color="info"
            >
              <q-tab
                name="employer"
                class="text-capitalize"
                id="tab-employer"
                @click="
                  () => {
                    inputSearch = '';
                    currentStatus = 'All';
                    flowStore.rotate();
                  }
                "
              >
                <div
                  class="row"
                  :class="
                    currentTab === 'employer' ? 'text-bold' : 'app-text-muted'
                  "
                >
                  {{ $t('customer.employer') }}
                </div>
              </q-tab>
              <q-tab
                name="employee"
                id="tab-employee"
                class="text-capitalize"
                @click="
                  () => {
                    inputSearch = '';
                    currentStatus = 'All';
                    flowStore.rotate();
                  }
                "
              >
                <div
                  class="row"
                  :class="
                    currentTab === 'employee' ? 'text-bold' : 'app-text-muted'
                  "
                >
                  {{ $t('customer.employee') }}
                </div>
              </q-tab>
            </q-tabs>
          </div>

          <div
            v-if="$q.screen.lt.md && currentTab === 'employer'"
            class="q-px-md row q-gutter-x-sm items-center"
          >
            <nav
              class="col rounded q-pa-sm text-center app-text-muted text-caption"
              :class="{
                'active-tab-sm': customerTypeSelected.value === v,
                'bordered surface-1': customerTypeSelected.value !== v,
              }"
              v-for="v in fieldCustomer"
              :key="v"
              @click="customerTypeSelected = { label: v, value: v }"
              id="`btn-sm-${v}`"
            >
              {{
                $t(
                  {
                    all: 'general.all',
                    customerLegalEntity: 'customer.employerLegalEntity',
                    customerNaturalPerson: 'customer.employerNaturalPerson',
                  }[v],
                )
              }}
            </nav>
          </div>
        </div>

        <!-- body -->
        <TabCustomer
          v-if="currentTab === 'employer'"
          ref="refTabCustomer"
          v-model:customer-type-selected="customerTypeSelected"
          v-model:stats-customer-type="statsCustomerType"
          v-model:img-list="imageList"
          :filter-address="filterAddress"
          :filter-business-type="filterBusinessType"
          :gridView
          :searchDate
          :currentTab
          :inputSearch
          :currentStatus
          :fieldSelected
          :fetchImageList
          :triggerChangeStatus
        />

        <TabEmployee
          v-if="currentTab === 'employee'"
          ref="refTabEmployee"
          v-model:employee-stats="employeeStats"
          v-model:img-list="imageList"
          :gridView
          :searchDate
          :currentTab
          :inputSearch
          :currentStatus
          :fieldSelected
          :fetchImageList
          :triggerChangeStatus
        />
      </div>
    </div>

    <!-- หน้า id ลูกค้า -->
    <div
      class="col column rounded bordered"
      style="overflow: hidden"
      v-if="$route.name === 'CustomerBranchManagement'"
    >
      <BranchPage
        v-model:status-employee-create="statusEmployeeCreate"
        v-model:status-employee-edit="employeeFormState.drawerModal"
        v-if="currentCustomer"
        :customer-type="currentCustomer.customerType"
        :current-customer-name="
          currentCustomer.customerType === 'PERS'
            ? locale === 'eng'
              ? `${currentCustomer.branch[0]?.firstNameEN} ${currentCustomer.branch[0]?.lastNameEN}`
              : `${currentCustomer.branch[0]?.firstName} ${currentCustomer.branch[0]?.lastName}`
            : locale === 'eng'
              ? currentCustomer.branch[0]?.registerNameEN
              : currentCustomer.branch[0]?.registerName
        "
        :current-citizen-id="currentCustomer.branch[0]?.citizenId"
        :count-employee="currentCustomer._count.employee"
        :selected-image="currentCustomer.selectedImage"
        :gender="currentCustomer.branch[0]?.gender"
        v-model:customer-id="currentCustomer.id"
        v-model:mode-view="gridView"
        @back="$router.push('/customer-management')"
        @add-employee="
          async (currentBranch) => {
            createEmployeeForm();
            await nextTick();
            employeeFormState.currentBranchId = currentBranch.id;
          }
        "
        v-model:branch="branch"
        v-model:current-customer-url-image="currentCustomer.imageUrl"
      />
    </div>
  </div>
</template>

<style scoped>
.slide-enter-active {
  transition: all 0.1s ease-out;
}

.slide-leave-active {
  transition: all 0.1s cubic-bezier(1, 0.5, 0.8, 1);
}

.slide-enter-from,
.slide-leave-to {
  transform: translateY(-20px);
  opacity: 0;
}

.status-active {
  --_branch-status-color: var(--green-6-hsl);
}

.status-inactive {
  --_branch-status-color: var(--stone-5-hsl);
  --_branch-badge-bg: var(--stone-5-hsl);
  filter: grayscale(0.5);
  opacity: 0.5;
}

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