<script lang="ts" setup>
import { useI18n } from 'vue-i18n';
import { storeToRefs } from 'pinia';
import { QSelect, useQuasar } from 'quasar';
import { getUserId } from 'src/services/keycloak';
import { computed, nextTick, onMounted, reactive, ref, watch } from 'vue';
import {
  baseUrl,
  dialogCheckData,
  dialogWarningClose,
  formatNumberDecimal,
  canAccess,
  isRoleInclude,
} from 'stores/utils';
import { ProductTree, quotationProductTree } from './utils';

// NOTE: Import stores
import { dateFormat, calculateAge, dateFormatJS } from 'src/utils/datetime';
import { useQuotationStore } from 'src/stores/quotations';
import useProductServiceStore from 'stores/product-service';
import { calculateDaysUntilExpire, dialog } from 'src/stores/utils';
import useEmployeeStore from 'stores/employee';
import { useInvoice, useReceipt, usePayment } from 'stores/payment';
import useCustomerStore from 'stores/customer';
import useOptionStore from 'stores/options';
import { useQuotationForm, DEFAULT_DATA } from './form';
import { deleteItem } from 'stores/utils';

// NOTE  Import Types
import { RequestData, RequestDataStatus } from 'src/stores/request-list/types';
import { View } from './types';
import {
  PayCondition,
  ProductRelation,
  ProductServiceList,
  QuotationPayload,
} from 'src/stores/quotations/types';
import { Employee } from 'src/stores/employee/types';
import { Receipt } from 'src/stores/payment/types';
import {
  ProductGroup,
  Product,
  Service,
} from 'src/stores/product-service/types';

// NOTE: Import Components
import TableRequest from './TableRequest.vue';
import SelectInput from 'components/shared/SelectInput.vue';
import SwitchItem from 'components/shared/SwitchItem.vue';
import ProductItem from 'components/05_quotation/ProductItem.vue';
import WorkerItem from 'components/05_quotation/WorkerItem.vue';
import ToggleButton from 'components/button/ToggleButton.vue';
import FormAbout from 'components/05_quotation/FormAbout.vue';
import ImportWorker from './ImportWorker.vue';
import {
  AddButton,
  SaveButton,
  EditButton,
  UndoButton,
  CancelButton,
  MainButton,
} from 'components/button';
import QuotationFormReceipt from './QuotationFormReceipt.vue';
import QuotationFormProductSelect from './QuotationFormProductSelect.vue';
import QuotationFormInfo from './QuotationFormInfo.vue';
import QuotationFormWorkerSelect from './QuotationFormWorkerSelect.vue';
import QuotationFormWorkerAddDialog from './QuotationFormWorkerAddDialog.vue';
import UploadFileSection from 'src/components/upload-file/UploadFileSection.vue';
import DialogViewFile from 'src/components/dialog/DialogViewFile.vue';

import { columnPaySplit } from './constants';
import { precisionRound } from 'src/utils/arithmetic';
import { useConfigStore } from 'src/stores/config';
import { useRequestList } from 'src/stores/request-list';
import QuotationFormMetadata from './QuotationFormMetadata.vue';
import BadgeComponent from 'src/components/BadgeComponent.vue';
import PaymentForm from './PaymentForm.vue';
import { api } from 'src/boot/axios';
import { RouterLink, useRoute } from 'vue-router';
import { initLang, initTheme, Lang } from 'src/utils/ui';
import { convertTemplate } from 'src/utils/string-template';

import { CustomerBranch } from 'src/stores/customer';

type Node = {
  [key: string]: any;
  opened?: boolean;
  checked?: boolean;
  bg?: string;
  fg?: string;
  icon?: string;
  children?: Node[];
};

type ProductGroupId = string;

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;

const employeeStore = useEmployeeStore();
const route = useRoute();
const useReceiptStore = useReceipt();
const configStore = useConfigStore();
const productServiceStore = useProductServiceStore();
const customerStore = useCustomerStore();
const quotationForm = useQuotationForm();
const quotationStore = useQuotationStore();
const invoiceStore = useInvoice();
const paymentStore = usePayment();
const optionStore = useOptionStore();
const requestStore = useRequestList();
const { t, locale } = useI18n();
const $q = useQuasar();
const openQuotation = ref<boolean>(false);
const formMetadata = ref();

const customerBranchOption = ref<CustomerBranch>();

const rowsRequestList = ref<RequestData[]>([]);

const {
  currentFormData: quotationFormData,
  currentFormState: quotationFormState,

  invoicePayload: invoiceFormData,

  newWorkerList,
  fileItemNewWorker,
  quotationFull,
} = storeToRefs(quotationForm);

const { data: config } = storeToRefs(configStore);

const receiptList = ref<Receipt[]>([]);
const refStatusFilter = ref<InstanceType<typeof QSelect>>();
const templateForm = ref<string>('');
const templateFormOption = ref<{ label: string; value: string }[]>([]);

const toggleWorker = ref(true);
const tempTableProduct = ref<ProductServiceList[]>([]);
const tempPaySplitCount = ref(0);
const tempPaySplit = ref<
  { no: number; amount: number; name?: string; invoice?: boolean }[]
>([]);
const currentQuotationId = ref<string | undefined>(undefined);
const date = ref();
const readonly = computed(() => {
  return !(
    quotationFormState.value.mode === 'create' ||
    quotationFormState.value.mode === 'edit'
  );
});

const selectedWorker = ref<
  (Employee & {
    attachment?: {
      name?: string;
      group?: string;
      url?: string;
      file?: File;
      _meta?: Record<string, any>;
    }[];
  })[]
>([]);
const selectedWorkerItem = computed(() => {
  return [
    ...selectedWorker.value.map((e) => ({
      foreignRefNo: e.employeePassport
        ? e.employeePassport[0]?.number || '-'
        : '-',
      employeeName:
        locale.value === Lang.English
          ? `${e.firstNameEN} ${e.lastNameEN}`
          : e.firstName
            ? `${e.firstName} ${e.lastName}`
            : `${e.firstNameEN} ${e.lastNameEN}`,
      birthDate: dateFormatJS({ date: e.dateOfBirth }),
      gender: e.gender,
      age: calculateAge(e.dateOfBirth),
      nationality: optionStore.mapOption(e.nationality),
      documentExpireDate:
        e.employeePassport !== undefined &&
        e.employeePassport[0]?.expireDate !== undefined
          ? dateFormatJS({ date: e.employeePassport[0]?.expireDate })
          : '-',
      imgUrl: e.selectedImage
        ? `${API_BASE_URL}/employee/${e.id}/image/${e.selectedImage}`
        : '',
      status: e.status,
    })),

    ...newWorkerList.value.map((v: any) => ({
      foreignRefNo: v.passportNo,
      employeeName:
        locale.value === Lang.English
          ? `${v.firstNameEN} ${v.lastNameEN}`
          : `${v.firstName} ${v.lastName}`,
      birthDate: dateFormatJS({ date: v.dateOfBirth }),
      gender: v.gender,
      age: calculateAge(v.dateOfBirth),
      nationality: optionStore.mapOption(v.nationality),
      documentExpireDate: '-',
      imgUrl: '',
      status: 'CREATED',
    })),
  ];
});
const firstCodePayment = ref('');
const selectedProductGroup = ref('');
const selectedInstallmentNo = ref<number[]>([]);
const installmentAmount = ref<number>(0);
const selectedInstallment = ref();
const agentPrice = ref(false);
const attachmentData = ref<
  {
    name: string;
    progress: number;
    loaded: number;
    total: number;
    url?: string;
  }[]
>([]);

const getToolbarConfig = computed(() => {
  const toolbar = [['left', 'center', 'justify'], ['toggle'], ['clip']];
  if (readonly.value) {
    return toolbar.filter((item) => !item.includes('toggle'));
  }

  return toolbar;
});

function getPrice(
  list: typeof productServiceList.value,
  filterHook?: (
    item: (typeof productServiceList.value)[number],
    index?: number,
  ) => boolean,
) {
  if (filterHook) list = list.filter(filterHook);

  return list.reduce(
    (a, c) => {
      if (
        selectedInstallmentNo.value.length > 0 &&
        c.installmentNo &&
        !selectedInstallmentNo.value.includes(c.installmentNo)
      ) {
        return a;
      }

      const calcVat =
        c.product[agentPrice.value ? 'agentPriceCalcVat' : 'calcVat'];
      const vatFactor = calcVat ? (config.value?.vat ?? 0.07) : 0;

      const price = precisionRound(
        (c.pricePerUnit * c.amount * (1 + vatFactor) - c.discount) /
          (1 + vatFactor),
      );
      const vat = price * vatFactor;

      a.totalPrice = precisionRound(a.totalPrice + price + c.discount);
      a.totalDiscount = precisionRound(a.totalDiscount + c.discount);
      a.vat = precisionRound(a.vat + vat);
      a.vatExcluded = calcVat
        ? a.vatExcluded
        : precisionRound(a.vatExcluded + price);
      a.finalPrice = precisionRound(a.totalPrice - a.totalDiscount + a.vat);

      return a;
    },
    {
      totalPrice: 0,
      totalDiscount: 0,
      vat: 0,
      vatExcluded: 0,
      finalPrice: 0,
    },
  );
}

const summaryPrice = computed(() => getPrice(productServiceList.value));

const payBank = ref('');

const pageState = reactive({
  hideStat: false,
  inputSearch: '',
  statusFilter: 'all',
  fieldSelected: [],
  gridView: false,
  isLoaded: false,
  importWorker: false,

  currentTab: 'all',
  addModal: false,
  quotationModal: false,
  employeeModal: false,
  productServiceModal: false,
  remarkWrite: true,
  imageDialog: false,
  imageDialogTitle: '',
  imageDialogUrl: '',
});

const productList = ref<Partial<Record<ProductGroupId, Product[]>>>({});
const serviceList = ref<Partial<Record<ProductGroupId, Service[]>>>({});
const productGroup = ref<ProductGroup[]>([]);
const selectedGroupSub = ref<'product' | 'service' | null>(null);

const productServiceList = ref<
  Required<QuotationPayload['productServiceList'][number]>[]
>([]);
const productService = computed(() => {
  return selectedInstallmentNo.value.length > 0
    ? productServiceList.value.filter((v) => {
        return (
          v.installmentNo &&
          selectedInstallmentNo.value.includes(v.installmentNo)
        );
      })
    : productServiceList.value;
});

function isIssueInvoice() {
  return quotationFormData.value.paySplit.some(
    (value) =>
      selectedInstallmentNo.value.includes(value.no) &&
      value.invoiceId !== undefined,
  );
}

async function fetchStatus() {
  statusQuotationForm.value = [
    {
      title: 'Issued',
      status: getStatus(quotationFormData.value.quotationStatus, 0, -1),
      active: () => view.value === View.Quotation,
      handler: () => {
        view.value = View.Quotation;
        code.value = '';
        selectedInstallmentNo.value = [];
        selectedInstallment.value = [];
      },
    },
    {
      title: 'Accepted',
      status: getStatus(quotationFormData.value.quotationStatus, 1, 0),
      active: () => view.value === View.Accepted,
      handler: () => ((view.value = View.Accepted), (code.value = '')),
    },
    {
      title: 'Invoice',
      status:
        quotationFormData.value.payCondition === 'Full'
          ? getStatus(quotationFormData.value.quotationStatus, 3, 1)
          : getStatus(quotationFormData.value.quotationStatus, 4, 1),
      active: () =>
        view.value === View.Invoice || view.value === View.InvoicePre,
      handler: () => {
        code.value = '';
        selectedInstallmentNo.value = [];
        selectedInstallment.value = [];

        getInvoice();
      },
    },
    {
      title: 'PaymentInProcess',
      status: getStatus(quotationFormData.value.quotationStatus, 4, 1),
      active: () =>
        view.value === View.Payment || view.value === View.PaymentPre,
      handler: () => {
        code.value = '';
        view.value =
          quotationFormData.value.payCondition === 'Full' ||
          quotationFormData.value.payCondition === 'BillFull'
            ? View.Payment
            : View.PaymentPre;
      },
    },
    {
      title: 'Receipt',
      status: getStatus(quotationFormData.value.quotationStatus, 4, 1),
      active: () => view.value === View.Receipt,
      handler: () => {
        fetchReceipt();
        view.value = View.Receipt;
        code.value = '';
      },
    },
    {
      title: 'ProcessComplete',
      status: getStatus(quotationFormData.value.quotationStatus, 5, 4),
      active: () => view.value === View.Complete,
      handler: async () => {
        view.value = View.Complete;
        await fetchRequest();
      },
    },
  ];
}

async function fetchRequest() {
  const res = await requestStore.getRequestDataList({
    query: quotationFormState.value.inputSearchRequest,
    page: 1,
    pageSize: 999999,
    requestDataStatus:
      quotationFormState.value.statusFilterRequest === 'All'
        ? undefined
        : quotationFormState.value.statusFilterRequest,
    quotationId: quotationFormData.value.id,
  });

  if (res) {
    rowsRequestList.value = res.result;
  }
}

async function fetchQuotation() {
  if (
    (!!currentQuotationId.value || !!quotationFormData.value.id) &&
    quotationFormState.value.mode &&
    quotationFormState.value.mode !== 'create'
  ) {
    const id = currentQuotationId.value || quotationFormData.value.id || '';

    await quotationForm.assignFormData(id, quotationFormState.value.mode);

    tempPaySplitCount.value = quotationFormData.value.paySplitCount || 0;
    tempPaySplit.value = JSON.parse(
      JSON.stringify(quotationFormData.value.paySplit),
    );
  }

  assignWorkerToSelectedWorker();

  await assignToProductServiceList();

  await fetchStatus();
}

async function fetchReceipt() {
  const res = await useReceiptStore.getReceiptList({
    quotationId: quotationFormData.value.id,
    quotationOnly: true,
    debitNoteOnly: false,
  });

  if (res) {
    receiptList.value = res.result;
  }
}

async function closeTab() {
  if (quotationFormState.value.mode === 'edit') {
    quotationForm.resetForm();
    await assignToProductServiceList();
  } else {
    dialogWarningClose(t, {
      message: t('dialog.message.close'),
      action: () => {
        window.close();
      },
      cancel: () => {},
    });
  }
}

function closeAble() {
  return window.opener !== null;
}

async function assignToProductServiceList() {
  const ret = await productServiceStore.fetchProductGroup({
    page: 1,
    pageSize: 9999,
  });

  if (ret) {
    productGroup.value = ret.result;

    productServiceList.value = quotationFormData.value.productServiceList.map(
      (v) => ({
        id: v.id!,
        installmentNo: v.installmentNo || 0,
        workerIndex: v.workerIndex || [0],
        vat: v.vat || 0,
        pricePerUnit: v.pricePerUnit || 0,
        discount: v.discount || 0,
        amount: v.amount || 0,
        product: v.product,
        work: v.work || null,
        service: v.service || null,
      }),
    );
    selectedProductGroup.value =
      quotationFormData.value.productServiceList[0]?.product.productGroup?.id ||
      '';
  }
}

async function submitAccepted() {
  dialog({
    color: 'info',
    icon: 'mdi-account-check',
    title: t('dialog.title.confirmQuotationAccept'),
    actionText: t('general.confirm'),
    persistent: true,
    message: t('dialog.message.quotationAccept'),
    action: async () => {
      if (!quotationFormData.value.id) return;

      const res = await quotationForm.accepted(quotationFormData.value.id);
      if (res) {
        await fetchQuotation();
      }
    },
    cancel: () => {},
  });
}

async function convertInvoiceToSubmit() {
  if (quotationFormData.value.id) {
    invoiceFormData.value = {
      installmentNo: selectedInstallmentNo.value,
      amount:
        quotationFormData.value.payCondition === 'SplitCustom'
          ? installmentAmount.value
          : summaryPrice.value.finalPrice,
      quotationId: quotationFormData.value.id,
    };

    const res = await quotationForm.submitInvoice();
    if (res) {
      await fetchQuotation();
      view.value = View.Payment;
    }
  }
}

async function convertDataToFormSubmit() {
  quotationFormData.value.productServiceList = JSON.parse(
    JSON.stringify(
      productServiceList.value.map((v) => ({
        installmentNo: v.installmentNo,
        workerIndex: v.workerIndex,
        discount: v.discount,
        amount: v.amount,
        product: v.product,
        work: v.work,
        service: v.service,
      })),
    ),
  );

  selectedWorker.value.forEach((v, i) => {
    if (v.attachment !== undefined) {
      v.attachment.forEach((value) => {
        fileItemNewWorker.value.push({
          employeeIndex: i,
          name: value.name,
          group: value.group as 'passport' | 'visa' | 'in-country-notice',
          url: value.url,
          file: value.file,
          _meta: value._meta,
        });
      });
    }
  });

  quotationFormData.value.worker = JSON.parse(
    JSON.stringify([
      ...selectedWorker.value.map((v) => {
        {
          return v.id;
        }
      }),
      ...newWorkerList.value.map((v) => {
        {
          return v.id;
        }
      }),
    ]),
  );

  quotationFormData.value.paySplit = JSON.parse(
    JSON.stringify(
      quotationFormData.value.paySplit.map((p) => ({ ...p, no: undefined })),
    ),
  );

  quotationFormData.value = {
    id: quotationFormData.value.id,
    workerMax: quotationFormData.value.workerMax,
    productServiceList: quotationFormData.value.productServiceList,
    urgent: quotationFormData.value.urgent,
    customerBranchId: quotationFormData.value.customerBranchId,
    registeredBranchId: quotationFormData.value.registeredBranchId,
    worker: quotationFormData.value.worker,
    payBillDate: quotationFormData.value.payBillDate,
    paySplit: quotationFormData.value.paySplit,
    paySplitCount: quotationFormData.value.paySplitCount,
    payCondition: quotationFormData.value.payCondition,
    dueDate: quotationFormData.value.dueDate,
    contactTel: quotationFormData.value.contactTel,
    contactName: quotationFormData.value.contactName,
    workName: quotationFormData.value.workName,
    _count: quotationFormData.value._count,
    status: quotationFormData.value.status,
    discount: quotationFormData.value.discount,
    remark: quotationFormData.value.remark || '',
    agentPrice: agentPrice.value,
    sellerId: quotationFormData.value.sellerId,
  };

  newWorkerList.value = [];
  const res = await quotationForm.submitQuotation();

  if (res === true) {
    quotationFormState.value.mode = 'info';
    localStorage.setItem(
      'new-quotation',
      JSON.stringify({
        quotationId: quotationFormData.value.id,
        customerBranchId: quotationFormData.value.customerBranchId,
        branchId: quotationFormData.value.registeredBranchId,
        agentPrice: agentPrice.value,
        statusDialog: 'info',
      }),
    );
    await fetchQuotation();
  }
}

async function getAllProduct(
  groupId: string,
  opts?: { force?: boolean; page?: number; pageSize?: number; query?: string },
) {
  selectedGroupSub.value = 'product';
  if (!opts?.force && productList.value[groupId] !== undefined) return;
  const ret = await productServiceStore.fetchListProduct({
    page: opts?.page ?? 1,
    pageSize: opts?.pageSize ?? 9999,
    query: opts?.query,
    productGroupId: groupId,
    activeOnly: true,
  });
  if (ret) productList.value[groupId] = ret.result;
}

async function getAllService(
  groupId: string,
  opts?: { force?: boolean; page?: number; pageSize?: number; query?: string },
) {
  selectedGroupSub.value = 'service';

  if (!opts?.force && serviceList.value[groupId] !== undefined) return;

  const ret = await productServiceStore.fetchListService({
    page: opts?.page ?? 1,
    pageSize: opts?.pageSize ?? 9999,
    productGroupId: groupId,
    query: opts?.query,

    fullDetail: true,
  });
  if (ret) serviceList.value[groupId] = ret.result;
}

async function triggerSelectEmployeeDialog() {
  pageState.employeeModal = true;
  await nextTick();
}

function triggerProductServiceDialog() {
  covertToNode();
  pageState.productServiceModal = true;
}

function handleChangePayType(type: PayCondition) {
  if (
    type === 'Split' ||
    (type === 'Full' &&
      tempPaySplitCount.value !== undefined &&
      tempPaySplit.value &&
      tempTableProduct.value)
  ) {
    quotationFormData.value.paySplitCount = tempPaySplitCount.value;
    quotationFormData.value.paySplit = JSON.parse(
      JSON.stringify(tempPaySplit.value),
    );
    productServiceList.value = productServiceList.value.map((item, index) => ({
      ...item,
      installmentNo: tempTableProduct.value[index].installmentNo || 0,
    }));
  }

  if (type === 'SplitCustom') {
    quotationFormData.value.paySplitCount = tempPaySplitCount.value || 1;
    if (tempPaySplit.value.length === 0) {
      quotationFormData.value.paySplit = [];
      quotationFormData.value.paySplit.push({ no: Number(1), amount: 0 });
    }
  }
}

function handleUpdateProductTable(
  data: QuotationPayload['productServiceList'][number],
  opt?: {
    newInstallmentNo: number;
  },
) {
  // handleChangePayType(quotationFormData.value.payCondition);
  // calc price
  const calc = (c: QuotationPayload['productServiceList'][number]) => {
    const originalPrice = c.pricePerUnit || 0;
    const finalPriceWithVat = precisionRound(
      originalPrice * (1 + (config.value?.vat || 0.07)),
    );
    const finalPriceNoVat =
      finalPriceWithVat / (1 + (config.value?.vat || 0.07));

    const price = finalPriceNoVat * c.amount;
    const vat = c.product.calcVat
      ? (finalPriceNoVat * c.amount - (c.discount || 0)) *
        (config.value?.vat || 0.07)
      : 0;
    return precisionRound(price + vat);
  };

  // installment
  if (opt && opt.newInstallmentNo) {
    const oldInstallmentNo = JSON.parse(JSON.stringify(data.installmentNo));
    const oldPaySplit = quotationFormData.value.paySplit.find(
      (v) => v.no === oldInstallmentNo,
    );
    const newPaySplit = quotationFormData.value.paySplit.find(
      (v) => v.no === opt.newInstallmentNo,
    );

    if (oldPaySplit) oldPaySplit.amount = oldPaySplit.amount - calc(data);
    if (newPaySplit) newPaySplit.amount = newPaySplit.amount + calc(data);

    return;
  }

  // re calc price
  const currTempPaySplit = tempPaySplit.value.find(
    (v) => v.no === data.installmentNo,
  );
  const currPaySplit = quotationFormData.value.paySplit.find(
    (v) => v.no === data.installmentNo,
  );
  const targetPaySplit = productService.value.filter(
    (v) => v.installmentNo === data.installmentNo,
  );
  let targetPaySplitAmount: number[] = [];

  targetPaySplitAmount = targetPaySplit.map((c) => {
    return calc(c);
  });

  const totalSum = targetPaySplitAmount.reduce((sum, value) => sum + value, 0);
  if (currTempPaySplit && currPaySplit) {
    currTempPaySplit.amount = totalSum;
    currPaySplit.amount = totalSum;
  }
}

function toggleDeleteProduct(index: number) {
  const currProduct = productServiceList.value[index];
  let currPaySplit = quotationFormData.value.paySplit.find(
    (v) => v.no === currProduct.installmentNo,
  );
  let currTempPaySplit = tempPaySplit.value.find(
    (v) => v.no === currProduct.installmentNo,
  );

  // cal curr amount
  if (currPaySplit && currTempPaySplit) {
    const price = agentPrice.value
      ? currProduct.product.agentPrice
      : currProduct.product.price;
    const pricePerUnit = currProduct.product.vatIncluded
      ? price / (1 + (config.value?.vat || 0.07))
      : price;
    const vat =
      (pricePerUnit * currProduct.amount - currProduct.discount) *
      (config.value?.vat || 0.07);
    const finalPrice =
      pricePerUnit * currProduct.amount +
      vat -
      Number(currProduct.discount || 0);

    currTempPaySplit.amount = currPaySplit.amount - finalPrice;
    currPaySplit.amount = currTempPaySplit.amount;
  }

  // product display
  productServiceList.value.splice(index, 1);
  productServiceList.value = [...productServiceList.value];

  // find split count
  tempPaySplitCount.value = Math.max(
    ...productServiceList.value.map((v) => v.installmentNo || 0),
  );
  quotationFormData.value.paySplitCount = tempPaySplitCount.value;

  // make split.length === split count
  tempPaySplit.value.splice(quotationFormData.value.paySplitCount);
  quotationFormData.value.paySplit.splice(
    quotationFormData.value.paySplitCount,
  );
}

async function assignWorkerToSelectedWorker() {
  selectedWorker.value = quotationFormData.value.worker;
}

function convertToTable(nodes: Node[]) {
  const _recursive = (v: Node): Node | Node[] => {
    if (v.checked && v.children) return v.children.flatMap(_recursive);
    if (v.checked) return v;
    return [];
  };
  const list = nodes.flatMap(_recursive).map((v) => v.value);
  if (list.length === 0) return;

  quotationFormData.value.paySplitCount = Math.max(
    ...list.map((v) => v.installmentNo || 0),
  );
  tempPaySplitCount.value = quotationFormData.value.paySplitCount;

  list.forEach((v) => {
    v.amount = Math.max(selectedWorkerItem.value.length, 1);
    if (!v.workerIndex) v.workerIndex = [];
    for (let i = 0; i < selectedWorkerItem.value.length; i++) {
      v.workerIndex.push(i);
    }

    if (!v.installmentNo) {
      v.installmentNo = quotationFormData.value.paySplitCount;
    }
  });

  productServiceList.value = list;
  tempTableProduct.value = JSON.parse(JSON.stringify(list));

  if (nodes.length > 0) {
    quotationFormData.value.paySplit = Array.apply(
      null,
      new Array(quotationFormData.value.paySplitCount),
    ).map((_, i) => ({
      no: i + 1,
      amount: getPrice(list, (v) => {
        return (
          v.installmentNo === i + 1 ||
          (i + 1 === quotationFormData.value.paySplitCount && !v.installmentNo)
        );
      }).finalPrice,
    }));
  } else {
    quotationFormData.value.paySplit = [];
    quotationFormData.value.paySplitCount = 0;
    quotationFormData.value.payCondition = PayCondition.Full;
  }

  tempPaySplit.value = JSON.parse(
    JSON.stringify(quotationFormData.value.paySplit),
  );
  tempPaySplitCount.value = quotationFormData.value.paySplitCount;
  pageState.productServiceModal = false;
}

function convertEmployeeToTable(selected: Employee[]) {
  productServiceList.value.forEach((v) => {
    if (selectedWorker.value.length === 0 && v.amount === 1) v.amount -= 1;

    v.amount = Math.max(
      v.amount + selected.length - selectedWorker.value.length,
      1,
    );

    const oldWorkerId: string[] = [];
    const newWorkerIndex: number[] = [];

    selectedWorker.value.forEach((item, i) => {
      if (v.workerIndex.includes(i)) oldWorkerId.push(item.id);
    });
    selected.forEach((item, i) => {
      if (selectedWorker.value.find((n) => item.id === n.id)) return;
      newWorkerIndex.push(i);
    });

    v.workerIndex = oldWorkerId
      .map((id) => selected.findIndex((item) => item.id === id))
      .filter((idx) => idx !== -1)
      .concat(newWorkerIndex);
  });

  pageState.employeeModal = false;
  quotationFormData.value.workerMax = Math.max(
    quotationFormData.value.workerMax || 1,
    selectedWorker.value.length,
  );
}

async function triggerDelete(name: string) {
  await quotationStore.delAttachment({
    parentId: quotationFormData.value.id || '',
    name,
  });
  await getAttachment();
}

async function getAttachment() {
  const attachment = await quotationStore.listAttachment({
    parentId: quotationFormData.value.id || '',
  });

  if (attachment && attachment.length > 0) {
    attachmentData.value = attachmentData.value.filter((item) =>
      attachment.includes(item.name),
    );

    attachment.forEach((v) => {
      const exists = attachmentData.value.some((item) => item.name === v);

      if (!exists) {
        attachmentData.value.push({
          name: v,
          progress: 1,
          loaded: 0,
          total: 0,
          url: `quotation/${quotationFormData.value.id || ''}/attachment/${v}`,
        });
      }
    });
  } else attachmentData.value = [];
}

async function uploadAttachment(file?: File) {
  if (!file) return;
  if (!quotationFormData.value) return;
  attachmentData.value.push({
    name: file.name,
    progress: 0,
    loaded: 0,
    total: 0,
  });

  const ret = await quotationStore.putAttachment({
    parentId: quotationFormData.value.id || '',
    name: file.name,
    file: file,
    onUploadProgress: (e) => {
      attachmentData.value[attachmentData.value.length - 1] = {
        name: file.name,
        progress: e.progress || 0,
        loaded: e.loaded,
        total: e.total || 0,
        url: `quotation/${quotationFormData.value.id || ''}/attachment/${file.name}`,
      };
    },
  });
  if (ret) await getAttachment();
}

function viewProductFile(data: ProductRelation) {
  const base64 = data.detail.match(/src="([^"]+)"/);

  pageState.imageDialog = true;
  pageState.imageDialogTitle = data.name;
  pageState.imageDialogUrl = base64 ? base64[1] : '';
}

const sessionData = ref<Record<string, any>>();

onMounted(async () => {
  initTheme();
  initLang();

  await configStore.getConfig();

  sessionStorage.setItem(
    'new-quotation',
    localStorage.getItem('new-quotation') ||
      sessionStorage.getItem('new-quotation') ||
      '',
  );

  localStorage.removeItem('new-quotation');
  const payload = sessionStorage.getItem('new-quotation');

  const { data: docTemplate, status } =
    await api.get<string[]>('/doc-template');

  if (status < 400) {
    templateFormOption.value = docTemplate.map((v) => ({
      label: v,
      value: v,
    }));
  }

  if (!!payload) {
    const parsed = JSON.parse(payload);
    date.value = Date.now();
    quotationFormState.value.mode = parsed.statusDialog;
    quotationFormData.value.registeredBranchId = parsed.branchId;
    quotationFormData.value.customerBranchId = parsed.customerBranchId;
    currentQuotationId.value = parsed.quotationId;
    agentPrice.value = parsed.agentPrice;
    quotationFormData.value.sellerId = getUserId();
    await fetchQuotation();
    await assignWorkerToSelectedWorker();
    sessionData.value = parsed;
  }

  await fetchStatus();

  if (quotationFormState.value.mode !== 'create') {
    await getAttachment();
  }

  pageState.isLoaded = true;

  if (route.query['tab'] === 'invoice') {
    getInvoice();
  }
  if (route.query['tab'] === 'receipt') {
    await fetchReceipt();
    view.value = View.Receipt;
    code.value = '';
  }
});

watch(
  () => quotationFormData.value.quotationStatus,
  () => {
    fetchStatus();
  },
);

watch(
  () => quotationFormData.value.customerBranchId,
  async (v) => {
    if (!v) return;
    selectedWorker.value = [];
  },
);

watch(
  () => quotationFormData.value.registeredBranchId,
  async (v) => {
    if (!pageState.isLoaded) return;
    const url = new URL(window.location.href);
    url.searchParams.set('branchId', v);
    history.pushState({}, '', url.toString());
  },
);

const productServiceNodes = ref<ProductTree>([]);

watch(
  () => productServiceList.value,
  () => {
    covertToNode();
  },
);

watch(customerBranchOption, () => {
  if (!customerBranchOption.value) return;

  quotationFormData.value.contactName = customerBranchOption.value.contactName;
  quotationFormData.value.contactTel = customerBranchOption.value.contactTel;
});

// async function searchEmployee(text: string) {
//   let query: string | undefined = text;
//   let pageSize = 50;

//   if (!text) {
//     query = undefined;
//     pageSize = 9999;
//   }

//   const retEmp = await customerStore.fetchBranchEmployee(
//     quotationFormData.value.customerBranchId,
//     {
//       query: query,
//       pageSize: pageSize,
//       passport: true,
//     },
//   );
//   if (retEmp) workerList.value = retEmp.data.result;
// }

function storeDataLocal() {
  quotationFormData.value.productServiceList = productService.value;

  localStorage.setItem(
    'quotation-preview',
    JSON.stringify({
      data: {
        codeInvoice: code.value,
        codePayment: firstCodePayment.value,
        ...quotationFormData.value,
        productServiceList: productService.value,
      },
      meta: {
        source: {
          ...quotationFormState.value.source,
          code:
            quotationFormState.value.mode === 'create'
              ? '-'
              : quotationFormState.value?.source?.code,
          createAt:
            quotationFormState.value.mode === 'create'
              ? Date.now()
              : quotationFormState.value?.source?.createdAt,
          createBy: quotationFormState.value?.source?.createdBy,
          payCondition: quotationFormData.value.payCondition,
          contactName: quotationFormData.value.contactName,
          contactTel: quotationFormData.value.contactTel,
          workName: quotationFormData.value.workName,
          dueDate: quotationFormData.value.dueDate,
        },
        selectedWorker: selectedWorker.value,
        createdBy: quotationFormState.value.createdBy('tha'),
        agentPrice: agentPrice.value,
      },
    }),
  );

  const url = new URL('/quotation/document-view', window.location.origin);

  url.searchParams.append('type', view.value);

  window.open(url, '_blank');
}
const QUOTATION_STATUS = [
  'Issued',
  'Accepted',
  'PaymentPending',
  'PaymentInProcess',
  'PaymentSuccess',
  'ProcessComplete',
  'Canceled',
];

function getStatus(
  status: typeof quotationFormData.value.quotationStatus,
  doneIndex: number,
  doingIndex: number,
) {
  return QUOTATION_STATUS.findIndex((v) => v === status) >= doneIndex
    ? 'done'
    : QUOTATION_STATUS.findIndex((v) => v === status) >= doingIndex
      ? 'doing'
      : 'waiting';
}

const statusQuotationForm = ref<
  {
    title: string;
    status: 'done' | 'doing' | 'waiting';
    handler: () => void;
    active?: () => boolean;
  }[]
>([]);

const view = ref<View>(View.Quotation);

const code = ref<string>('');

async function getInvoiceCode(invoiceId: string) {
  const ret = await invoiceStore.getInvoice(invoiceId);
  if (ret) code.value = ret.code;
}

async function getInvoiceCodeFullPay() {
  const ret = await invoiceStore.getInvoiceList({
    quotationId: quotationFormData.value.id,
  });
  if (ret) code.value = ret.result.at(0)?.code || '';
}

const importWorkerCriteria = ref<{
  passport: string[] | null;
  visa: string[] | null;
}>({
  passport: [],
  visa: [],
});

async function getWorkerFromCriteria(
  payload: typeof importWorkerCriteria.value,
) {
  const ret = await employeeStore.fetchList({
    payload: {
      passport: payload.passport || undefined,
    },
    pageSize: 99999, // must include all possible worker
    page: 1,
    passport: true,
    customerBranchId: quotationFormData.value.customerBranchId,
    activeOnly: true,
  });

  if (!ret) return false; // error, do not close dialog

  const deduplicate = ret.result.filter(
    (a) => !selectedWorker.value.find((b) => a.id === b.id),
  );

  convertEmployeeToTable([...deduplicate, ...selectedWorker.value]);

  return true;
}

async function exampleReceipt(id: string) {
  $q.loading.show();
  const url = await paymentStore.getFlowAccount(id);

  if (url) {
    $q.loading.hide();
    window.open(url.data.link, '_blank');
  }
}

function getInvoice() {
  view.value =
    quotationFormData.value.payCondition === 'Full' ||
    quotationFormData.value.payCondition === 'BillFull'
      ? View.Invoice
      : View.InvoicePre;

  if (
    quotationFormData.value.payCondition === 'Full' ||
    quotationFormData.value.payCondition === 'BillFull'
  ) {
    getInvoiceCodeFullPay();
  } else {
    code.value = '';
  }
}

function handleWorkName() {
  const validService = productService.value.find(
    (item) => 'service' in item && item.service !== null,
  );

  if (!validService || validService?.service === null) return;

  const workName = validService?.service.name;

  if (
    !!quotationFormData.value.workName &&
    !(quotationFormData.value.workName === workName)
  ) {
    dialogCheckData({
      action: () => {
        quotationFormData.value.workName = workName;
      },
      checkData: () => {
        return {
          oldData: [
            { nameField: 'workName', value: quotationFormData.value.workName },
          ],
          newData: [{ nameField: 'workName', value: workName }],
        };
      },
      cancel: () => {},
    });
  } else {
    quotationFormData.value.workName = workName;
  }
}

watch(
  [
    () => quotationFormState.value.statusFilterRequest,
    () => quotationFormState.value.inputSearchRequest,
  ],
  () => {
    fetchRequest();
  },
);

async function formDownload() {
  if (!quotationFormData.value.id) return;

  const res = await fetch(
    baseUrl +
      '/doc-template/' +
      templateForm.value +
      `?data=quotation&dataId=${quotationFormData.value.id}`,
  );
  const blob = await res.blob();

  const a = document.createElement('a');
  a.download = templateForm.value;
  a.href = window.URL.createObjectURL(blob);
  a.click();
  a.remove();
}

function covertToNode() {
  productServiceNodes.value = quotationProductTree(
    productServiceList.value,
    agentPrice.value,
    config.value?.vat,
  );
}
</script>

<template>
  <ImportWorker
    v-model:open="pageState.importWorker"
    v-model:data="importWorkerCriteria"
    :import-worker="getWorkerFromCriteria"
  />

  <div class="column surface-0 fullscreen">
    <div class="color-bar" :class="{ dark: $q.dark.isActive }">
      <div class="orange-segment"></div>
      <div class="yellow-segment"></div>
      <div class="gray-segment"></div>
    </div>

    <header
      class="row q-px-md q-py-sm items-center justify-between relative-position"
    >
      <section class="banner" :class="{ dark: $q.dark.isActive }"></section>
      <div style="flex: 1" class="row items-center">
        <RouterLink to="/quotation">
          <q-img src="/icons/favicon-512x512.png" width="3rem" />
        </RouterLink>
        <span class="column text-h6 text-bold q-ml-md">
          {{ $t('quotation.title') }}
          {{ code || quotationFormState.source?.code || '' }}
          <span class="text-caption text-regular app-text-muted">
            {{
              $t('quotation.processOn', {
                msg:
                  quotationFormState.mode === 'create'
                    ? `${dateFormat(date, true)} ${dateFormat(date, true, true)}`
                    : `${dateFormat(quotationFull?.createdAt, true)} ${dateFormat(quotationFull?.createdAt, true, true)}`,
              })
            }}
          </span>
        </span>
      </div>

      <div
        v-if="quotationFormState.mode !== 'create'"
        class="column col-sm-2 col-12 q-ml-auto"
        style="gap: 10px"
      >
        <div
          class="row"
          :class="{
            'justify-end': $q.screen.gt.xs,
            'q-pl-xl q-mt-sm': $q.screen.lt.sm,
          }"
        >
          <BadgeComponent
            :title-i18n="$t('general.laborIdentified')"
            :class="{
              'q-ml-md': $q.screen.lt.sm,
            }"
          />
        </div>

        <div
          class="row items-center justify-between surface-1 rounded q-pa-xs"
          style="height: 40px; border-radius: 40px"
          v-if="quotationFormData.quotationStatus === 'Issued'"
        >
          <div class="full-height full-width row">
            <div
              class="col-6 flex flex-center"
              style="
                color: white;
                background: linear-gradient(to right, #035aa1 0%, #14ab35 100%);
                border-radius: 20px;
                gap: 10px;
              "
            >
              <q-icon name="mdi-calendar-range" />
              {{ $t('quotation.receiptDialog.remain') }}
            </div>
            <div class="col-6 flex flex-center">
              <span
                v-if="calculateDaysUntilExpire(quotationFormData.dueDate) <= 0"
              >
                {{
                  $t(
                    `general.${
                      calculateDaysUntilExpire(quotationFormData.dueDate) > 0
                        ? 'beDue'
                        : calculateDaysUntilExpire(
                              quotationFormData.dueDate,
                            ) === 0
                          ? 'due'
                          : 'overDue'
                    }`,
                  )
                }}
              </span>

              <span v-else>
                {{ calculateDaysUntilExpire(quotationFormData.dueDate) }}
                {{ $t('general.day') }}
              </span>
            </div>
          </div>
        </div>
      </div>
    </header>

    <article
      class="col full-width q-pa-md"
      style="flex-grow: 1; overflow-y: auto"
    >
      <section class="col-sm col-12">
        <div class="col q-gutter-y-md">
          <div
            class="surface-1 q-pa-sm row no-wrap full-width scroll rounded"
            style="gap: 10px"
          >
            <button
              v-for="value in statusQuotationForm"
              :id="`btn-status-${value.title}`"
              :key="value.title"
              class="q-pa-sm bordered status-color row items-center"
              :class="{
                [`status-color-${value.status}`]: true,
                'quotation-status-active': value.active?.(),
              }"
              @click="value.status !== 'waiting' && value.handler()"
              style="min-width: 120px; cursor: pointer; text-wrap: nowrap"
            >
              <div class="q-px-sm">
                <q-icon
                  class="icon-color quotation-status"
                  style="border-radius: 50%"
                  :name="`${value.status === 'done' ? 'mdi-check-circle' : 'mdi-checkbox-blank-circle-outline'}`"
                />
              </div>
              <div class="col text-left">
                {{ $t(`quotation.status.${value.title}`) }}
              </div>
            </button>
          </div>

          <q-expansion-item
            for="item-up"
            id="item-up"
            dense
            class="overflow-hidden"
            switch-toggle-side
            default-opened
            style="border-radius: var(--radius-2)"
            expand-icon="mdi-chevron-down-circle"
            header-class="surface-1"
          >
            <template v-slot:header>
              <section class="row items-center full-width">
                <div class="row items-center q-pr-md q-py-sm">
                  <span
                    class="text-weight-medium q-mr-md"
                    style="font-size: 18px"
                  >
                    {{ $t('general.document') }}
                  </span>
                </div>

                <q-checkbox
                  v-model="quotationFormData.urgent"
                  class="q-ml-auto"
                  size="xs"
                  :label="$t('general.urgent')"
                  :disable="readonly"
                />
              </section>
            </template>

            <div class="surface-1 q-pa-md full-width">
              <q-form
                ref="formMetadata"
                @submit="
                  () => {
                    convertDataToFormSubmit();
                  }
                "
              >
                <QuotationFormMetadata
                  class="q-mb-md"
                  :readonly
                  :actor="quotationFormState.createdBy?.($i18n.locale) || ''"
                  :quotation-no="(quotationFull && quotationFull.code) || ''"
                  :quotation-status="
                    quotationFormState.source?.quotationStatus === 'Expired'
                  "
                  :created-at="quotationFormState.createdAt"
                  v-model:urgent="quotationFormData.urgent"
                  v-model:work-name="quotationFormData.workName"
                  v-model:contactor="quotationFormData.contactName"
                  v-model:telephone="quotationFormData.contactTel"
                  v-model:due-date="quotationFormData.dueDate"
                  v-model:seller-id="quotationFormData.sellerId"
                >
                  <template #issue-info>
                    <FormAbout
                      hide-add
                      class="col-12 col-md-8"
                      input-only
                      v-model:branch-id="quotationFormData.registeredBranchId"
                      v-model:customer-branch-id="
                        quotationFormData.customerBranchId
                      "
                      v-model:customer-branch-option="customerBranchOption"
                      :readonly="readonly"
                    />
                  </template>
                </QuotationFormMetadata>
              </q-form>
            </div>
          </q-expansion-item>

          <template
            v-if="
              view === View.Quotation ||
              view === View.Accepted ||
              view === View.Invoice
            "
          >
            <q-expansion-item
              for="item-up"
              id="item-up"
              dense
              class="overflow-hidden"
              switch-toggle-side
              default-opened
              style="border-radius: var(--radius-2)"
              expand-icon="mdi-chevron-down-circle"
              header-class="surface-1"
            >
              <template v-slot:header>
                <section class="row items-center full-width">
                  <div class="row items-center q-pr-md q-py-sm">
                    <span
                      class="text-weight-medium q-mr-md"
                      style="font-size: 18px"
                    >
                      {{ $t('quotation.employeeList') }}
                    </span>
                    <template v-if="!readonly">
                      <ToggleButton class="q-mr-sm" v-model="toggleWorker" />
                      {{
                        toggleWorker
                          ? $t('general.specify')
                          : $t('general.noSpecify')
                      }}
                    </template>
                  </div>
                  <nav v-if="canAccess('quotation', 'edit')" class="q-ml-auto">
                    <AddButton
                      id="btn-add-worker"
                      for="btn-add-worker"
                      v-if="
                        !readonly &&
                        (!quotationFormState.source ||
                          quotationFormState.source?.quotationStatus ===
                            'Issued' ||
                          quotationFormState.source?.quotationStatus ===
                            'Expired')
                      "
                      icon-only
                      @click.stop="triggerSelectEmployeeDialog"
                    />
                    <AddButton
                      id="btn-add-worker"
                      for="btn-add-worker"
                      v-if="
                        !!quotationFormState.source &&
                        quotationFormState.source.quotationStatus !==
                          'Issued' &&
                        quotationFormState.source?.quotationStatus !== 'Expired'
                      "
                      @click.stop="openQuotation = !openQuotation"
                      icon-only
                      class="q-ml-auto"
                    />
                  </nav>
                </section>
              </template>

              <div class="surface-1 q-pa-md full-width">
                <WorkerItem
                  @update:employee-amount="
                    (v) =>
                      (quotationFormData.workerMax = Math.max(
                        v,
                        selectedWorker.length,
                      ))
                  "
                  :employee-amount="
                    quotationFormData.workerMax || selectedWorker.length
                  "
                  :readonly="readonly"
                  :rows="selectedWorkerItem"
                  @delete="(i) => deleteItem(selectedWorker, i)"
                />
              </div>
            </q-expansion-item>

            <q-expansion-item
              for="item-up"
              id="item-up"
              dense
              class="overflow-hidden"
              switch-toggle-side
              default-opened
              style="border-radius: var(--radius-2)"
              expand-icon="mdi-chevron-down-circle"
              header-class="surface-1"
            >
              <template v-slot:header>
                <section class="row items-center full-width">
                  <div class="row items-center q-pr-md q-py-sm">
                    <span class="text-weight-medium" style="font-size: 18px">
                      {{ $t('quotation.productList') }}
                    </span>
                  </div>
                  <nav class="q-ml-auto">
                    <AddButton
                      v-if="!readonly"
                      icon-only
                      class="q-ml-auto"
                      id="trigger-product-service-dialog"
                      @click.stop="triggerProductServiceDialog"
                    />
                  </nav>
                </section>
              </template>
              <div class="surface-1 q-pa-md full-width">
                <ProductItem
                  :installment-input="
                    quotationFormData.payCondition === 'SplitCustom'
                  "
                  :max-installment="quotationFormData.paySplitCount"
                  :readonly="readonly"
                  :agent-price="agentPrice"
                  :employee-rows="selectedWorkerItem"
                  @delete="toggleDeleteProduct"
                  :rows="productService"
                  @update:rows="
                    (v) => {
                      view === View.Quotation && (productServiceList = v);
                    }
                  "
                  @update-table="handleUpdateProductTable"
                  @view-file="viewProductFile"
                />
              </div>
            </q-expansion-item>

            <q-expansion-item
              for="item-up"
              id="item-up"
              dense
              class="overflow-hidden"
              switch-toggle-side
              default-opened
              style="border-radius: var(--radius-2)"
              expand-icon="mdi-chevron-down-circle"
              header-class="surface-1"
            >
              <template v-slot:header>
                <section class="row items-center full-width">
                  <div class="row items-center q-pr-md q-py-sm">
                    <span
                      class="text-weight-medium q-mr-md"
                      style="font-size: 18px"
                    >
                      {{ $t('general.payment') }}
                    </span>
                  </div>
                </section>
              </template>

              <div class="surface-1 q-pa-md full-width">
                <template v-if="true">
                  <QuotationFormInfo
                    :view="view"
                    :installment-amount="installmentAmount"
                    :installment-no="selectedInstallmentNo"
                    v-model:pay-type="quotationFormData.payCondition"
                    v-model:pay-bank="payBank"
                    v-model:pay-split-count="quotationFormData.paySplitCount"
                    v-model:pay-split="quotationFormData.paySplit"
                    :readonly
                    v-model:final-discount="quotationFormData.discount"
                    v-model:pay-bill-date="quotationFormData.payBillDate"
                    v-model:summary-price="summaryPrice"
                    class="q-mb-md"
                    @change-pay-type="handleChangePayType"
                  />
                </template>
              </div>
            </q-expansion-item>

            <q-expansion-item
              v-if="quotationFormState.mode !== 'create'"
              for="item-up"
              id="item-up"
              dense
              class="overflow-hidden"
              switch-toggle-side
              default-opened
              style="border-radius: var(--radius-2)"
              expand-icon="mdi-chevron-down-circle"
              header-class="surface-1"
            >
              <template v-slot:header>
                <section class="row items-center full-width">
                  <div class="row items-center q-pr-md q-py-sm">
                    <span
                      class="text-weight-medium q-mr-md"
                      style="font-size: 18px"
                    >
                      {{ $t('quotation.additionalFile') }}
                    </span>
                  </div>
                </section>
              </template>

              <div class="surface-1 q-pa-md full-width">
                <UploadFileSection
                  :readonly="
                    {
                      quotation: quotationFormState.mode !== 'edit',
                      invoice:
                        isRoleInclude(['sale', 'head_of_sale']) ||
                        !canAccess('quotation', 'edit'),
                      accepted: true,
                    }[view]
                  "
                  v-model:file-data="attachmentData"
                  :label="
                    $t('general.upload', { msg: $t('general.attachment') })
                  "
                  :transform-url="
                    async (url: string) => {
                      const result = await api.get<string>(url);
                      return result.data;
                    }
                  "
                  @update:file="(f) => uploadAttachment(f)"
                  @close="(v) => triggerDelete(v)"
                />
              </div>
            </q-expansion-item>
            <q-expansion-item
              v-if="false"
              for="item-up"
              id="item-up"
              dense
              class="overflow-hidden"
              switch-toggle-side
              default-opened
              style="border-radius: var(--radius-2)"
              expand-icon="mdi-chevron-down-circle"
              header-class="surface-1"
            >
              <template v-slot:header>
                <section class="row items-center full-width">
                  <div class="row items-center q-pr-md q-py-sm">
                    <span
                      class="text-weight-medium q-mr-md"
                      style="font-size: 18px"
                    >
                      {{ $t('quotation.letterOfAcceptance') }}
                    </span>
                  </div>
                </section>
              </template>

              <div class="surface-1 q-pa-md flex" style="gap: var(--size-2)">
                <SelectInput
                  style="max-width: 250px"
                  class=""
                  incremental
                  v-model="templateForm"
                  id="quotation-branch"
                  :option="templateFormOption"
                  :label="$t('quotation.templateForm')"
                />
                <!-- <MainButton
                  outlined
                  icon="mdi-play-box-outline"
                  color="207 96% 32%"
                  @click="() => {}"
                >
                  {{ $t('general.view', { msg: $t('general.example') }) }}
                </MainButton> -->
                <MainButton
                  solid
                  icon="mdi-pencil-outline"
                  color="207 96% 32%"
                  @click="formDownload"
                >
                  {{ $t('general.designForm') }}
                </MainButton>
              </div>
            </q-expansion-item>

            <q-expansion-item
              for="item-up"
              id="item-up"
              dense
              class="overflow-hidden"
              switch-toggle-side
              default-opened
              style="border-radius: var(--radius-2)"
              expand-icon="mdi-chevron-down-circle"
              header-class="surface-1"
            >
              <template v-slot:header>
                <section class="row items-ceenhancement nter full-width">
                  <div class="row items-center q-pr-md q-py-sm">
                    <span
                      class="text-weight-medium q-mr-md"
                      style="font-size: 18px"
                    >
                      {{ $t('general.remark') }}
                    </span>
                  </div>
                </section>
              </template>

              <div class="surface-1 q-pa-md full-width">
                <q-editor
                  dense
                  :hint="$t('general.enterToAdd')"
                  :readonly="readonly || !pageState.remarkWrite"
                  :model-value="
                    !pageState.remarkWrite || readonly
                      ? convertTemplate(quotationFormData.remark || '', {
                          'quotation-payment': {
                            paymentType: quotationFormData.payCondition,
                            amount: getPrice(productServiceList).finalPrice,
                            installments: quotationFormData.paySplit,
                          },
                          'quotation-labor': {
                            name: selectedWorker.map(
                              (v, i) =>
                                `${i + 1}. ` +
                                `${v.employeePassport.length !== 0 ? v.employeePassport[0].number + '_' : ''}  ${v.namePrefix}.${v.firstNameEN ? `${v.firstNameEN} ${v.lastNameEN}` : `${v.firstName} ${v.lastName}`}  `.toUpperCase(),
                            ),
                          },
                        })
                      : quotationFormData.remark || ''
                  "
                  min-height="5rem"
                  class="full-width"
                  :content-class="{
                    'q-my-sm rounded': true,
                    bordered: !readonly && pageState.remarkWrite,
                  }"
                  toolbar-bg="input-border"
                  style="cursor: auto; color: var(--foreground)"
                  :flat="!readonly"
                  :style="`width: ${$q.screen.gt.xs ? '100%' : '63vw'}`"
                  :toolbar="getToolbarConfig"
                  :toolbar-toggle-color="readonly ? 'disabled' : 'primary'"
                  :toolbar-color="
                    readonly ? 'disabled' : $q.dark.isActive ? 'white' : ''
                  "
                  :definitions="{
                    clip: {
                      icon: 'mdi-paperclip',
                      tip: 'Upload',
                      disable: readonly,
                      handler: () => console.log('upload'),
                    },
                  }"
                  @update:model-value="
                    (v) => {
                      quotationFormData.remark = v;
                    }
                  "
                >
                  <template v-if="!readonly" v-slot:toggle>
                    <div class="text-caption row no-wrap">
                      <MainButton
                        :disabled="readonly"
                        :solid="!pageState.remarkWrite"
                        icon="mdi-eye-outline"
                        color="0 0% 40%"
                        @click="pageState.remarkWrite = false"
                        style="padding: 0 var(--size-2)"
                        :style="{
                          color: pageState.remarkWrite
                            ? 'hsl(0 0% 40%)'
                            : undefined,
                        }"
                      >
                        {{ $t('general.view', { msg: $t('general.example') }) }}
                      </MainButton>
                      <MainButton
                        :disabled="readonly"
                        :solid="pageState.remarkWrite"
                        icon="mdi-pencil-outline"
                        color="0 0% 40%"
                        @click="pageState.remarkWrite = true"
                        style="padding: 0 var(--size-2)"
                        :style="{
                          color: !pageState.remarkWrite
                            ? 'hsl(0 0% 40%)'
                            : undefined,
                        }"
                      >
                        {{ $t('general.edit') }}
                      </MainButton>
                    </div>
                  </template>
                </q-editor>

                <p class="app-text-muted text-caption">
                  {{ $t('general.hintRemark') }}
                  <code>#[quotation-labor]</code>
                  {{ $t('general.quotationLabor') }}
                  {{ $t('general.or') }}
                  <code>#[quotation-payment]</code>
                  {{ $t('general.quotationPayment') }}
                </p>
              </div>
            </q-expansion-item>
          </template>

          <template v-else>
            <PaymentForm
              v-if="
                view !== View.InvoicePre &&
                view !== View.Receipt &&
                view !== View.Complete
              "
              :readonly="
                isRoleInclude(['sale', 'head_of_sale']) ||
                !canAccess('quotation', 'edit')
              "
              :data="quotationFormState.source"
              v-model:first-code-payment="firstCodePayment"
              @fetch-status="
                () => {
                  fetchQuotation();
                }
              "
            />

            <div
              v-if="view === View.Complete"
              class="surface-1 q-pa-md full-width q-gutter-y-md rounded"
            >
              <div class="row justify-between items-center">
                <q-input
                  for="input-search"
                  outlined
                  dense
                  :label="$t('general.search')"
                  class="col-12 col-md-3"
                  :bg-color="$q.dark.isActive ? 'dark' : 'white'"
                  v-model="quotationFormState.inputSearchRequest"
                  debounce="200"
                >
                  <template #prepend>
                    <q-icon name="mdi-magnify" />
                  </template>
                  <template v-if="$q.screen.lt.md" v-slot:append>
                    <span class="row">
                      <q-separator vertical />
                      <q-btn
                        icon="mdi-filter-variant"
                        unelevated
                        class="q-ml-sm"
                        padding="4px"
                        size="sm"
                        rounded
                        @click="refStatusFilter?.showPopup"
                      />
                    </span>
                  </template>
                </q-input>

                <q-select
                  v-show="$q.screen.gt.sm"
                  ref="refStatusFilter"
                  v-model="quotationFormState.statusFilterRequest"
                  outlined
                  dense
                  option-value="value"
                  option-label="label"
                  map-options
                  emit-value
                  :for="'field-select-status'"
                  :hide-dropdown-icon="$q.screen.lt.sm"
                  :options="[
                    {
                      label: $t('general.all'),
                      value: 'All',
                    },
                    {
                      label: $t('requestList.status.Pending'),
                      value: RequestDataStatus.Pending,
                    },
                    {
                      label: $t('requestList.status.InProgress'),
                      value: RequestDataStatus.InProgress,
                    },
                    {
                      label: $t('requestList.status.Completed'),
                      value: RequestDataStatus.Completed,
                    },
                  ]"
                ></q-select>
              </div>

              <TableRequest
                v-if="view === View.Complete"
                :rows="rowsRequestList"
              />
            </div>

            <q-expansion-item
              v-if="view === View.InvoicePre"
              for="item-up"
              id="item-up"
              dense
              class="overflow-hidden"
              switch-toggle-side
              default-opened
              style="border-radius: var(--radius-2)"
              expand-icon="mdi-chevron-down-circle"
              header-class="surface-1"
            >
              <div class="surface-1 q-pa-md full-width">
                <SwitchItem :value="view">
                  <template #[View.InvoicePre]>
                    <q-table
                      flat
                      bordered
                      :columns="columnPaySplit"
                      :rows="quotationFormData.paySplit"
                      selection="multiple"
                      v-model:selected="selectedInstallment"
                      @update:selected="
                        (v) => {
                          selectedInstallment = v.filter(
                            (value) => !value.invoiceId,
                          );

                          selectedInstallmentNo = selectedInstallment.map(
                            (value: any) => value.no,
                          );

                          installmentAmount = selectedInstallment.reduce(
                            (total: number, value: any) => total + value.amount,
                            0,
                          );
                        }
                      "
                      row-key="no"
                      :no-data-label="$t('general.noDataTable')"
                      :rows-per-page-options="[0]"
                      hide-pagination
                      :selected-rows-label="
                        (n) =>
                          $t('general.selected', {
                            number: n,
                            msg: $t('productService.product.product'),
                          })
                      "
                    >
                      <template v-slot:header="props">
                        <q-tr
                          :props="props"
                          :style="`background-color:hsla(var(--info-bg) / 0.07)`"
                        >
                          <q-th auto-width>
                            <q-checkbox
                              v-if="
                                !quotationFormData.paySplit.every(
                                  (p) => p.invoiceId,
                                )
                              "
                              v-model="props.selected"
                            />
                          </q-th>
                          <q-th
                            v-for="col in props.cols"
                            :key="col.name"
                            :props="props"
                          >
                            {{ $t(col.label) }}
                          </q-th>
                        </q-tr>
                      </template>
                      <template v-slot:body="props">
                        <q-tr
                          :class="{ 'cursor-pointer': props.row.invoiceId }"
                          :props="props"
                          @click="
                            async () => {
                              if (props.row.invoiceId) {
                                await getInvoiceCode(props.row.invoiceId);

                                selectedInstallmentNo =
                                  quotationFormState.source?.paySplit
                                    .filter(
                                      (v) =>
                                        v.invoiceId === props.row.invoiceId,
                                    )
                                    .map((v) => v.no) || [];

                                installmentAmount = props.row.amount;
                                view = View.Invoice;
                              }
                            }
                          "
                        >
                          <q-td auto-width>
                            <q-checkbox
                              v-model="props.selected"
                              v-if="!props.row.invoiceId"
                            />
                          </q-td>
                          <q-td
                            v-for="col in props.cols"
                            :key="col.name"
                            :props="props"
                          >
                            <template v-if="col.name === 'installmentNo'">
                              {{ col.value }}
                            </template>

                            <template v-if="col.name === 'amount'">
                              {{ formatNumberDecimal(col.value, 2) }}
                            </template>

                            <template v-if="col.name === 'status'">
                              <BadgeComponent
                                :title="
                                  !!col.value
                                    ? 'สร้างใบแจ้งหนี้เเล้ว'
                                    : 'ยังไม่สร้างใบแจ้งหนี้'
                                "
                                :hsla-color="!!col.value ? '' : '--red-7-hsl'"
                              />
                            </template>
                          </q-td>
                        </q-tr>
                      </template>
                    </q-table>
                  </template>
                </SwitchItem>
              </div>
            </q-expansion-item>
          </template>

          <template
            v-if="
              (view === View.Quotation || view === View.Accepted) &&
              quotationFormData.id
            "
          >
            <q-expansion-item
              for="item-up"
              id="item-up"
              dense
              class="overflow-hidden"
              switch-toggle-side
              default-opened
              style="border-radius: var(--radius-2)"
              expand-icon="mdi-chevron-down-circle"
              header-class="surface-1"
            >
              <template v-slot:header>
                <section class="row items-center full-width">
                  <div class="row items-center q-pr-md q-py-sm">
                    <span
                      class="text-weight-medium q-mr-md"
                      style="font-size: 18px"
                    >
                      {{ $t('general.form') }}
                    </span>
                  </div>
                </section>
              </template>

              <div class="surface-1 q-pa-md row" style="gap: var(--size-2)">
                <SelectInput
                  class="q-mr-xl col-md-3 col-12"
                  v-model="templateForm"
                  id="quotation-branch"
                  :option="templateFormOption"
                  :label="$t('quotation.templateForm')"
                />
                <!-- <MainButton
                  outlined
                  icon="mdi-play-box-outline"
                  color="207 96% 32%"
                  @click="storeDataLocal"
                >
                  {{ $t('general.view', { msg: $t('general.example') }) }}
                </MainButton> -->
                <MainButton
                  solid
                  icon="mdi-pencil-outline"
                  color="207 96% 32%"
                  @click="formDownload"
                >
                  {{ $t('general.designForm') }}
                </MainButton>
              </div>
            </q-expansion-item>
          </template>

          <template v-if="view === View.Receipt">
            <QuotationFormReceipt
              v-for="(v, i) in receiptList"
              :key="i"
              :amount="v.amount"
              :date="v.date"
              :pay-type="quotationFormData.payCondition"
              :index="i"
              :pay-split-count="quotationFormData.paySplitCount || 0"
              @view="
                () => {
                  if (quotationFormData.payCondition !== 'Full') {
                    selectedInstallmentNo = [v.invoice.installments[0].no];
                    installmentAmount = v.invoice.amount;
                  }

                  view = View.Quotation;
                }
              "
              @example="
                () => {
                  exampleReceipt(v.id);
                }
              "
            />
          </template>
        </div>
      </section>
    </article>

    <footer class="surface-1 q-pa-md full-width">
      <div class="row full-width justify-end">
        <MainButton
          class="q-mr-auto"
          v-if="
            view !== View.InvoicePre &&
            view !== View.PaymentPre &&
            view !== View.Receipt
          "
          outlined
          icon="mdi-play-box-outline"
          color="207 96% 32%"
          id="btn-view-example"
          @click="storeDataLocal"
        >
          {{ $t('general.view', { msg: $t('general.example') }) }}
        </MainButton>

        <CancelButton
          outlined
          id="btn-close"
          @click="closeTab()"
          :label="$t('dialog.action.close')"
          v-if="quotationFormState.mode === 'info' && closeAble()"
        />

        <div
          class="q-ml-sm"
          v-if="
            view === View.Accepted &&
            canAccess('quotation', 'edit') &&
            quotationFormData.quotationStatus === 'Issued'
          "
        >
          <MainButton
            solid
            icon="mdi-account-multiple-check-outline"
            color="207 96% 32%"
            id="btn-submit-accepted"
            @click="
              () => {
                submitAccepted();
              }
            "
          >
            {{ $t('quotation.customerAcceptance') }}
          </MainButton>
        </div>

        <template
          v-if="
            view === View.InvoicePre &&
            !quotationFormData.paySplit.every((p) => p.invoiceId)
          "
        >
          <MainButton
            solid
            :disabled="selectedInstallment.length === 0"
            icon="mdi-account-multiple-check-outline"
            class="q-ml-sm"
            color="207 96% 32%"
            id="btn-select-invoice"
            @click="
              () => {
                view = View.Invoice;
              }
            "
          >
            {{ $t('quotation.selectInvoice') }}
          </MainButton>
        </template>

        <div
          class="q-ml-sm"
          v-if="
            view === View.Invoice &&
            canAccess('quotation', 'edit') &&
            ((quotationFormData.quotationStatus !== 'PaymentPending' &&
              quotationFormData.payCondition !== 'Full') ||
              quotationFormData.quotationStatus === 'Accepted') &&
            !isIssueInvoice()
          "
        >
          <MainButton
            solid
            icon="mdi-account-multiple-check-outline"
            color="207 96% 32%"
            id="btn-approve-invoice"
            @click="
              () => {
                convertInvoiceToSubmit();
              }
            "
          >
            {{ $t('quotation.approveInvoice') }}
          </MainButton>
        </div>

        <div
          class="row q-ml-sm"
          style="gap: var(--size-2)"
          v-if="
            (view === View.Quotation &&
              canAccess('quotation', 'edit') &&
              (quotationFormData.quotationStatus === 'Issued' ||
                quotationFormData.quotationStatus === 'Expired')) ||
            !quotationFormData.quotationStatus
          "
        >
          <UndoButton
            outlined
            @click="closeTab()"
            id="btn-undo"
            v-if="quotationFormState.mode === 'edit'"
          />
          <SaveButton
            type="submit"
            id="btn-save"
            v-if="
              quotationFormState.mode === 'create' ||
              quotationFormState.mode === 'edit'
            "
            solid
            @click="() => formMetadata.submit()"
          />
          <EditButton
            v-else
            class="no-print"
            id="btn-edit"
            @click="quotationFormState.mode = 'edit'"
            solid
          />
        </div>
      </div>
    </footer>

    <!-- SEC: Dialog -->
    <!-- add employee quotation -->

    <QuotationFormWorkerSelect
      :preselect-worker="selectedWorker"
      :customerBranchId="quotationFormData.customerBranchId"
      v-model:open="pageState.employeeModal"
      v-model:new-worker-list="newWorkerList"
      @success="
        (v) => {
          selectedWorker = v.worker;
        }
      "
    />

    <!-- add product service -->

    <QuotationFormProductSelect
      v-model="pageState.productServiceModal"
      v-model:nodes="productServiceNodes"
      v-model:product-group="productGroup"
      v-model:product-list="productList"
      v-model:service-list="serviceList"
      v-model:selected-product-group="selectedProductGroup"
      :agent-price="agentPrice"
      @submit="
        (node) => {
          convertToTable(node);
          handleWorkName();
        }
      "
      @select-group="
        async (id) => {
          await getAllService(id);
          await getAllProduct(id);
        }
      "
      @search="
        (id, text, mode) => {
          if (mode === 'service') {
            getAllService(id, { force: true, query: text, pageSize: 50 });
          }
          if (mode === 'product') {
            getAllProduct(id, { force: true, query: text, pageSize: 50 });
          }
        }
      "
    ></QuotationFormProductSelect>
  </div>

  <!-- add Worker -->
  <QuotationFormWorkerAddDialog
    v-if="quotationFormState.source"
    :disabled-worker-id="selectedWorker.map((v) => v.id)"
    :product-service-list="quotationFormState.source.productServiceList"
    :quotation-id="quotationFormState.source.id"
    :customer-branch-id="quotationFormState.source.customerBranchId"
    v-model:open="openQuotation"
    @success="
      openQuotation = !openQuotation;
      fetchQuotation();
    "
  />

  <DialogViewFile
    :title="pageState.imageDialogTitle"
    :url="pageState.imageDialogUrl"
    v-model="pageState.imageDialog"
  />
</template>

<style scoped>
.worker-list > :deep(*:not(:last-child)) {
  margin-bottom: var(--size-2);
}

.icon-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1/1;
  font-size: 1.5rem;
  padding: var(--size-1);
  border-radius: var(--radius-2);
}

.bg-color-orange {
  --_color: var(--yellow-7-hsl);
  color: white;
  background: hsla(var(--_color));
}

.dark .bg-color-orange {
  --_color: var(--orange-6-hsl);
}

.bg-color-orange-light {
  --_color: var(--yellow-7-hsl);
  background: hsla(var(--_color) / 0.2);
}
.dark .bg-color-orange {
  --_color: var(--orange-6-hsl / 0.2);
}

.color-bar {
  width: 100%;
  height: 1vh;
  background: linear-gradient(
    90deg,
    rgba(245, 159, 0, 1) 0%,
    rgba(255, 255, 255, 1) 77%,
    rgba(204, 204, 204, 1) 100%
  );
  display: flex;
  overflow: hidden;
}

.color-bar.dark {
  opacity: 0.7;
}

.orange-segment {
  background-color: var(--yellow-7);
  flex-grow: 4;
}

.yellow-segment {
  background-color: hsla(var(--yellow-7-hsl) / 0.2);
  flex-grow: 0.5;
}

.gray-segment {
  background-color: #ccc;
  flex-grow: 1;
}

.orange-segment,
.yellow-segment,
.gray-segment {
  transform: skewX(-60deg);
}

:deep(i.q-icon.mdi.mdi-chevron-down-circle.q-expansion-item__toggle-icon) {
  color: hsl(var(--text-mute));
}

:deep(
  i.q-icon.mdi.mdi-chevron-down-circle.q-expansion-item__toggle-icon.q-expansion-item__toggle-icon--rotated
) {
  color: var(--brand-1);
}

:deep(.q-editor__toolbar-group):nth-child(2) {
  margin-left: auto !important;
}

:deep(.q-editor__toolbar.row.no-wrap.scroll-x) {
  background-color: var(--surface-2) !important;
}

:deep(.q-editor__toolbar) {
  border-color: var(--surface-3) !important;
}

:deep(
  .q-item.q-item-type.row.no-wrap.q-item--dense.q-item--clickable.q-link.cursor-pointer.q-focusable.q-hoverable.surface-1
    .q-focus-helper
) {
  visibility: hidden;
}

.status-color {
  --_color: var(--gray-0);
  border-color: hsla(var(--_color));
  background: hsla(var(--_color) / 0.05);
  border-radius: 4px;

  .icon-color {
    color: hsla(var(--_color));
  }

  &.status-color-done {
    --_color: var(--green-5-hsl);
    color: var(--foreground);
  }
  &.status-color-doing {
    --_color: var(--blue-5-hsl);
    color: var(--foreground);
  }
  &.status-color-waiting {
    --_color: var(--gray-4-hsl);
    color: var(--foreground);
  }
}

.quotation-status-active {
  opacity: 1;
  font-weight: 600;
  transition: 1s box-shadow ease-in-out;
  animation: status 1s infinite;
}

@keyframes status {
  0% {
    box-shadow: 0x 0px 0px hsla(var(--_color) / 0.5);
  }
  50% {
    box-shadow: 0px 0px 1px 4px hsla(var(--_color) / 0.2);
  }
  100% {
    box-shadow: 0px 0px 4px 7px hsla(var(--_color) / 0);
  }
}

.banner {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: url('/images/building-banner.png');
  background-repeat: no-repeat;
  background-size: cover;
  z-index: -1;

  &.dark {
    filter: invert(100%);
  }
}
</style>
