<template>
  <div class="pt-print">
    <Row :gutter="24">
      <Col
        :span="isPopup ? 24 : 10"
        class="pt-print__col-config"
      >
        <Card
          dis-hover
          :bordered="false"
          class="pt-print__card"
        >
          <div class="pt-print__card-header">
            <div
              v-if="pdfLoading"
              class="pt-print__loading"
            >
              <i class="fa fa-spinner fa-spin" />
              <span class="pt-print__loading-text">{{ $t('PDF_PRINT_CONFIG.LOADING_FILE') }}</span>
            </div>

            <div
              v-if="!fromFile && !pdfLoading"
              class="pt-print__session"
              v-html="sesionName"
            />
          </div>

          <div
            v-if="fromFile"
            class="pt-print__upload"
          >
            <Upload
              multiple
              type="drag"
              action=""
              accept="application/pdf"
              :before-upload="handleUpload"
              :show-upload-list="false"
            >
              <div class="pt-print__upload-content">
                <Icon
                  type="ios-cloud-upload"
                  size="64"
                  class="pt-print__upload-icon"
                />
                <p class="pt-print__upload-text">
                  {{ fileNameUpload || $t('SESSION_PRINT.UPLOAD_FILE') }}
                </p>
                <p
                  v-if="!fileNameUpload"
                  class="pt-print__upload-hint"
                >
                  {{ $t('SESSION_PRINT.UPLOAD_HINT') }}
                </p>
              </div>
            </Upload>
          </div>

          <div class="pt-print__section pt-print__section--session">
            <div class="pt-print__section-header">
              <div class="pt-print__section-header-left">
                <i-switch
                  v-model="sessionPrint.active"
                  size="default"
                />
                <h3 class="pt-print__section-title">
                  {{ $t('SESSION_PRINT.TITLE') }}
                </h3>
              </div>
            </div>

            <div
              v-if="sessionPrint.active"
              class="pt-print__section-content"
            >
              <div class="pt-print__options">
                <div class="pt-print__option">
                  <Checkbox
                    v-model="sessionPrint.isPagging"
                    :disabled="!sessionPrint.active"
                  >
                    <span class="pt-print__option-label">
                      {{ $t("SESSION_PRINT.ACTIVE_PAGGING") }}
                    </span>
                  </Checkbox>
                </div>

                <div class="pt-print__option">
                  <Checkbox
                    v-model="sessionPrint.isTimestamp"
                    :disabled="!sessionPrint.active"
                  >
                    <span class="pt-print__option-label">
                      {{ $t("SESSION_PRINT.IS_TIMESTAMP") }}
                    </span>
                  </Checkbox>
                </div>
              </div>

              <Row
                :gutter="12"
                class="pt-print__fields"
              >
                <Col :span="12">
                  <div class="pt-print__field">
                    <label class="pt-print__field-label">
                      {{ $t('SESSION_PRINT.SESSION_NAME') }}
                    </label>
                    <Input
                      v-model="sessionPrint.content"
                      :disabled="!sessionPrint.active"
                      :placeholder="$t('SESSION_PRINT.ENTER_SESSION_NAME')"
                      size="default"
                    />
                  </div>
                </Col>

                <Col :span="7">
                  <div class="pt-print__field">
                    <label class="pt-print__field-label">
                      {{ $t('PDF_PRINT_CONFIG.POSITION') }}
                    </label>
                    <Select
                      v-model="sessionPrint.position"
                      :disabled="!sessionPrint.active"
                      size="default"
                    >
                      <Option
                        v-for="option in positionOptions"
                        :key="option.value"
                        :value="option.value"
                      >
                        {{ option.emoji }} {{ $t(`PDF_PRINT_CONFIG.${option.label}`) }}
                      </Option>
                    </Select>
                  </div>
                </Col>

                <Col :span="5">
                  <div class="pt-print__field">
                    <label class="pt-print__field-label">
                      {{ $t('PDF_PRINT_CONFIG.FONT_SIZE') }}
                    </label>
                    <InputNumber
                      v-model="sessionPrint.fontSize"
                      :disabled="!sessionPrint.active"
                      :min="8"
                      :max="72"
                      size="default"
                      style="width: 100%"
                    />
                  </div>
                </Col>
              </Row>
            </div>
          </div>

          <div class="pt-print__section pt-print__section--template">
            <div
              v-if="listConfig.length"
              class="pt-print__template"
            >
              <div class="pt-print__section-header pt-print__section-header--simple">
                <h3 class="pt-print__section-title">
                  <i class="fa fa-print" />
                  {{ $t('SESSION_PRINT.LIST_TEMPLATE') }}
                </h3>
              </div>

              <div class="pt-print__template-list">
                <Button
                  v-for="item in listConfig"
                  :key="item._id"
                  :type="item.isDefault ? 'default' : 'primary'"
                  size="small"
                  :loading="btnLoading"
                  :disabled="pdfLoading"
                  class="pt-print__template-btn"
                  @click="printPdfConfig(item.config)"
                >
                  <i
                    :class="item.isDefault ? 'fa fa-file-pdf-o' : 'fa fa-print'"
                  />
                  <span>{{ item.name }}</span>
                </Button>
              </div>

              <div class="pt-print__template-footer">
                <div class="pt-print__template-footer-left">
                  <Checkbox
                    v-model="isSaveFile"
                    :value="isSaveFile"
                    @on-change="onChangSaveFile"
                  >
                    <span class="pt-print__option-label">
                      {{ $t('SESSION_PRINT.IS_SAVE_FILE') }}
                    </span>
                  </Checkbox>
                </div>

                <div class="pt-print__template-footer-right">
                  <router-link
                    to="/printer/config"
                    target="_blank"
                    class="pt-print__template-link"
                  >
                    <i class="fa fa-plus-circle" />
                    {{ $t('PDF_PRINT_CONFIG.CREATE_TEMPLATE') }}
                  </router-link>
                </div>
              </div>
            </div>

            <div
              v-else
              class="pt-print__empty"
            >
              <div class="pt-print__empty-content">
                <i class="fa fa-file-o pt-print__empty-icon" />
                <p class="pt-print__empty-text">
                  {{ $t('SESSION_PRINT.TEMPLATE_EMPTY') }}
                </p>
                <router-link
                  to="/printer/config"
                  target="_blank"
                  class="pt-print__empty-action"
                >
                  <Button
                    type="primary"
                    size="large"
                  >
                    <i class="fa fa-plus" />
                    {{ $t('PDF_PRINT_CONFIG.CREATE_TEMPLATE_FIRST') }}
                  </Button>
                </router-link>
              </div>
            </div>
          </div>
        </Card>
      </Col>

      <Col
        v-if="!isPopup"
        :span="14"
        class="pt-print__col-preview"
      >
        <Card
          dis-hover
          :bordered="false"
          class="pt-print__preview-card"
        >
          <div class="pt-print__preview-header">
            <h3 class="pt-print__preview-title">
              <i class="fa fa-eye" />
              {{ $t('SESSION_PRINT.PREVIEW_TITLE') }}
            </h3>
          </div>

          <div class="pt-print__preview-content">
            <div
              v-if="pdfFileUploadUrl"
              class="pt-print__preview-frame"
            >
              <iframe
                :src="pdfFileUploadUrl"
                class="pt-print__preview-iframe"
                frameborder="0"
              />
            </div>

            <div
              v-else
              class="pt-print__preview-empty"
            >
              <i class="fa fa-file-pdf-o pt-print__preview-empty-icon" />
              <p class="pt-print__preview-empty-text">
                {{ $t('SESSION_PRINT.PREVIEW_EMPTY') }}
              </p>
            </div>
          </div>
        </Card>
      </Col>
    </Row>
  </div>
</template>

<script>
import * as cheerio from 'cheerio';
import { v4 as uuid } from 'uuid';
import { ConfigPdfPrinter } from '@/models/config';
import { saveAsPdf, getUrlBlobPdf } from '@/lib/pdf/api';
import { PdfService } from '@/lib/pdf/service';
import { getShopeePrintPdf } from '@/api/shopee/seller/order/print';
import { CacheOrderPdfBuffer } from '@/plugins/store/cache';
import { usePrinterStore } from '@/vue/pinia/printer';
import { bridgeGetWebcontentTabId } from '@/bridge/options/background';
import { useSessionStorage } from '@vueuse/core';
import { STORAGE_KEYS } from '@/constant/storage';
import { loggerVue } from '@/plugins/logger';
import { getPdfFromUrl } from '@/api/utils/get';

const printerStore = usePrinterStore();

const getIframePdfFromHtml = (html) => {
  const $ = cheerio.load(html);
  const iframe = $('iframe');
  const iframeUrl = iframe.attr('src');
  return iframeUrl;
};

export default {
  name: 'PrinterPDF',
  props: {
    isPopup: {
      type: Boolean,
      default: false,
    },
  },
  data() {
    const listConfig = useSessionStorage(STORAGE_KEYS.SESSION_STORAGE.PRINTER_PDF_LIST_CONFIG, []);

    return {
      btnLoading: false,
      pdfLoading: false,
      shopId: this.$route.query.shopId || '',
      jobId: this.$route.query.jobId || '',
      jobUrl: this.$route.query.jobUrl || '',
      fromTabId: Number(this.$route.query.fromTabId) || 0,
      from: this.$route.query.from || 'file',
      fileNameUpload: '',
      pdfFileUploadUrl: '',
      pdfOrignBuffer: null,
      listConfig,
      isSaveFile: printerStore.saveFilePrint,
      positionOptions: printerStore.listPosition,
      sessionPrint: printerStore.sessionPrint,
    };
  },
  methods: {
    onChangSaveFile() {
      printerStore.saveFilePrint = this.isSaveFile;
    },
    generatePdfBlobUrl(pdfInput) {
      const blob = new Blob([pdfInput], { type: 'application/pdf' });
      return URL.createObjectURL(blob);
    },
    /**
     * @param {File} fileUpload
     */
    async handleUpload(fileUpload) {
      if (!fileUpload) {
        return false;
      }

      this.fileNameUpload = fileUpload.name;
      this.pdfOrignBuffer = await fileUpload.arrayBuffer();
      this.pdfFileUploadUrl = this.generatePdfBlobUrl(this.pdfOrignBuffer);
      this.$Message.success(this.$t('SESSION_PRINT.UPLOAD_FILE_SUCCESS'));
    },
    async pdfFetchFile() {
      this.pdfLoading = true;

      const cacheKey = [this.from, this.jobId, this.jobUrl].join('_');
      const CachePdf = new CacheOrderPdfBuffer(cacheKey);

      const getCachePdf = await CachePdf.get();

      if (!this.jobId) {
        this.jobId = CachePdf.key;
      }

      if (getCachePdf) {
        this.pdfOrignBuffer = new Uint8Array(getCachePdf.buffer).buffer;
      } else {
        try {
          if (this.from === 'shopee' && this.jobId) {
            this.pdfOrignBuffer = await getShopeePrintPdf(this.jobId);

            await CachePdf.set({
              buffer: Array.from(new Uint8Array(this.pdfOrignBuffer)),
            });
          }

          if (this.from === 'tiktok' && this.jobUrl) {
            this.pdfOrignBuffer = await getPdfFromUrl(this.jobUrl);

            await CachePdf.set({
              buffer: Array.from(new Uint8Array(this.pdfOrignBuffer)),
            });
          }

          if (this.from === 'url' && this.jobUrl) {
            this.pdfOrignBuffer = await getPdfFromUrl(this.jobUrl);

            await CachePdf.set({
              buffer: Array.from(new Uint8Array(this.pdfOrignBuffer)),
            });
          }

          if (this.from === 'lazada' && this.jobUrl) {
            const tabId = this.fromTabId;

            const html = await bridgeGetWebcontentTabId(tabId);

            const iframeUrl = getIframePdfFromHtml(html);
            const pdfUrl = `https://sellercenter.lazada.vn/${iframeUrl}`;

            this.pdfOrignBuffer = await getPdfFromUrl(pdfUrl);

            await CachePdf.set({
              buffer: Array.from(new Uint8Array(this.pdfOrignBuffer)),
            });
          }
        } catch (error) {
          loggerVue.error({
            msg: 'PDF_GET_BUFFER_ERROR',
            from: this.from,
            error,
          });
        }
      }

      if (this.pdfOrignBuffer && !this.pdfFileUploadUrl) {
        this.pdfFileUploadUrl = this.generatePdfBlobUrl(this.pdfOrignBuffer);
      }

      this.pdfLoading = false;
    },
    async printPdfConfig(printConfig) {
      this.btnLoading = true;

      if (!this.pdfOrignBuffer) {
        this.$Message.error(this.$t('SESSION_PRINT.UPLOAD_FILE_NOT_FOUND'));
        this.btnLoading = false;
        return false;
      }

      let pdfBuffer = this.pdfOrignBuffer;

      const pdfService = new PdfService(pdfBuffer);
      try {
        if (printConfig) {
          pdfBuffer = await pdfService.addConfigContent(printConfig);
        }

        if (this.sessionPrint.active) {
          pdfService.setPdfBytes(pdfBuffer);
          pdfBuffer = await pdfService.addFooterContent(this.sessionPrint);
        }

        await this.openPdf(pdfBuffer);
        this.$Message.success(this.$t('SESSION_PRINT.PRINT_SUCCESS'));
      } catch (error) {
        loggerVue.error({
          msg: 'PRINT_PDF_ERROR',
          error,
        });
        this.$Message.error(this.$t('SESSION_PRINT.PRINT_ERROR'));
      }
      this.btnLoading = false;
    },

    async openPdf(pdfBuffer) {
      if (this.isSaveFile) {
        const pdfFileName = `print_${new Date().getTime()}_${this.jobId || uuid()}.pdf`;
        return saveAsPdf(pdfBuffer, pdfFileName);
      }

      const pdfUrl = getUrlBlobPdf(pdfBuffer);

      const windowLoadPdf = window.open(pdfUrl, '_blank');

      windowLoadPdf.onload = () => {
        windowLoadPdf.print();
      };
    },

    async loadConfigs() {
      const listConfig = await ConfigPdfPrinter.findAll();

      if (!listConfig.length) {
        this.listConfig = [];
        return;
      }

      this.listConfig = [
        {
          _id: 'default',
          isDefault: true,
          name: this.$t('PDF_PRINT_CONFIG.DEFAULT_NAME'),
          config: null,
        },
        ...listConfig.filter((item) => {
          return {
            ...item,
            isDefault: false,
          };
        }),
      ];
    },
    async loadPdfFromFile() {
      const urlBlob = '';
      const response = await fetch(urlBlob);
      const blob = await response.blob();
      const url = URL.createObjectURL(blob);

      return this.openExternalUrl(url, false);
    },
  },
  async created() {
    this.loadConfigs();
    ConfigPdfPrinter.pullRemote();

    if (['shopee', 'tiktok', 'lazada', 'url'].includes(this.from)) {
      this.pdfFetchFile();
    } else {
      this.from = 'file';
    }
  },
  computed: {
    fromFile() {
      return this.from === 'file';
    },
    sesionName() {
      return [
        `<span>[${this.from.toUpperCase()}] ${this.$t('SESSION_PRINT.SESSION_NAME')}</span>:`,
        this.jobId,
      ].join(' ');
    },
  },
};
</script>

<style lang="scss" scoped>
@import '@/vue/styles/tokens.scss';

.pt-print {
  padding: 16px;
  background: $c-surface-soft;

  &__col-config,
  &__col-preview {
    height: 100%;
  }

  &__card,
  &__preview-card {
    border-radius: $radius-card;
    box-shadow: $shadow-card;
    overflow: hidden;

    :deep(.ivu-card-body) {
      padding: 0;
    }
  }

  &__card-header {
    padding: 20px 24px;
    border-bottom: 1px solid $c-border;
    background: $c-surface;
  }

  &__loading {
    display: flex;
    align-items: center;
    gap: 12px;
    color: $c-link;
    font-size: 16px;

    i {
      font-size: 20px;
    }
  }

  &__loading-text {
    font-weight: 500;
  }

  &__session {
    font-size: 15px;
    color: $c-text-strong;
    font-weight: 500;

    :deep(span) {
      color: $c-link;
    }
  }

  &__upload {
    padding: 24px;
    background: $c-surface;
    border-bottom: 1px solid $c-border;

    :deep(.ivu-upload-drag) {
      border: 2px dashed $c-border-strong;
      border-radius: $radius-item;
      background: $c-surface-soft;
      transition: border-color $motion-base, background-color $motion-base;

      &:hover {
        border-color: $c-link;
        background: $c-surface-alt;
      }
    }
  }

  &__upload-content {
    padding: 40px 20px;
    text-align: center;
  }

  &__upload-icon {
    color: $c-link;
    margin-bottom: 16px;
  }

  &__upload-text {
    font-size: 16px;
    color: $c-text-strong;
    font-weight: 500;
    margin-bottom: 8px;
  }

  &__upload-hint {
    font-size: 13px;
    color: $c-text-muted;
    margin-top: 8px;
  }

  &__section {
    padding: 16px;
    background: $c-surface;
    border-bottom: 1px solid $c-border;

    &:last-child {
      border-bottom: none;
    }
  }

  &__section-header {
    margin-bottom: 12px;

    &--simple .pt-print__section-title {
      display: flex;
      align-items: center;
      gap: 6px;

      i {
        color: $c-link;
      }
    }
  }

  &__section-header-left {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  &__section-title {
    font-size: 14px;
    font-weight: 600;
    color: $c-text-strong;
    margin: 0;
  }

  &__section-content {
    margin-top: 12px;
  }

  &__options {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    margin-bottom: 12px;
  }

  &__option {
    :deep(.ivu-checkbox-wrapper) {
      font-size: 13px;
    }
  }

  &__option-label {
    color: $c-text;
    font-size: 13px;
  }

  &__fields {
    margin-top: 12px;
  }

  &__field {
    :deep(.ivu-input),
    :deep(.ivu-select),
    :deep(.ivu-input-number) {
      border-radius: $radius-sm;
    }
  }

  &__field-label {
    display: block;
    margin-bottom: 8px;
    font-size: 13px;
    font-weight: 500;
    color: $c-text;
  }

  &__template-list {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 6px;
    margin-bottom: 20px;
  }

  &__template-btn {
    font-size: 12px;

    i {
      margin-right: 4px;
    }

    &.ivu-btn {
      width: 100%;
      height: 32px;
      border-radius: $radius-sm;
    }
  }

  &__template-footer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding-top: 16px;
    border-top: 1px solid $c-border;

    .pt-print__option-label {
      font-size: 14px;
    }
  }

  &__template-link {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    color: $c-link;
    font-size: 14px;
    font-weight: 500;
    text-decoration: none;
    transition: color $motion-fast;

    &:hover {
      color: $c-link-hover;
    }

    i {
      font-size: 14px;
    }
  }

  &__empty-content {
    text-align: center;
    padding: 60px 20px;
  }

  &__empty-icon {
    display: block;
    font-size: 64px;
    color: $c-text-placeholder;
    margin-bottom: 16px;
  }

  &__empty-text {
    font-size: 15px;
    color: $c-text-muted;
    margin-bottom: 24px;
  }

  &__empty-action {
    display: inline-block;

    :deep(.ivu-btn) {
      border-radius: $radius-sm;
      height: 44px;
      padding: 0 32px;

      i {
        margin-right: 6px;
      }
    }
  }

  &__preview-card {
    height: calc(100vh - 32px);
    display: flex;
    flex-direction: column;

    :deep(.ivu-card-body) {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }
  }

  &__preview-header {
    padding: 20px 24px;
    border-bottom: 1px solid $c-border;
    background: $c-surface;
  }

  &__preview-title {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 16px;
    font-weight: 600;
    color: $c-text-strong;
    margin: 0;

    i {
      color: $c-link;
    }
  }

  &__preview-content {
    flex: 1;
    background: $c-surface-alt;
    display: flex;
    flex-direction: column;
    overflow: hidden;
  }

  &__preview-frame {
    flex: 1;
    padding: 16px;
    overflow: hidden;
  }

  &__preview-iframe {
    width: 100%;
    height: 100%;
    border-radius: $radius-item;
    box-shadow: $shadow-card;
    background: $c-surface;
  }

  &__preview-empty {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 40px;
  }

  &__preview-empty-icon {
    font-size: 80px;
    color: $c-text-placeholder;
    margin-bottom: 16px;
  }

  &__preview-empty-text {
    font-size: 15px;
    color: $c-text-muted;
  }
}

@media (max-width: 1200px) {
  .pt-print__template-list {
    grid-template-columns: repeat(3, 1fr);
  }
}

@media (max-width: 768px) {
  .pt-print {
    padding: 8px;
  }

  .pt-print__template-list {
    grid-template-columns: repeat(2, 1fr);
  }

  .pt-print__template-footer {
    flex-direction: column;
    gap: 12px;
    align-items: flex-start;
  }
}
</style>
