// TODO types, interfaces

import { PrintStampApi, PrintApi, NormalizeApi, StampApi } from '@openapi/printer';
import { saveBlob } from '@utils/files';
import { configCreator, axiosBlobOptions } from './config';
import { AxiosResponse } from 'axios';

class PrinterService {
  public fetchConvertedFileAsyncWithStamp({
    input = 'HTML',
    output = 'PDF',
    template,
    parameters,
  }: any): Promise<void> {
    return new Promise((resolve, reject) => {
      configCreator().then((config) => {
        new PrintStampApi(config)
          .processSync1(input, output, template, parameters, axiosBlobOptions)
          .then((response: AxiosResponse) => {
            saveBlob({
              blob: response.data,
            });
            resolve();
          })
          .catch((e: Error) => {
            console.error(
              `[services/printer/fetchConvertedFileWithStamp] - ${e.toString()}`
            );
            reject(e);
          });
      });
    });
  }

  public fetchConvertedFileSyncWithStamp({
    input = 'HTML',
    output = 'PDF',
    fileName,
    template,
    parameters,
  }: any): Promise<void> {
    return new Promise((resolve, reject) => {
      configCreator().then((config) => {
        new PrintStampApi(config)
          .processSync2(input, output, template, parameters, axiosBlobOptions)
          .then((response: AxiosResponse) => {
            saveBlob({
              blob: response.data,
              fileName
            });
            resolve();
          })
          .catch((e: Error) => {
            console.error(
              `[services/printer/fetchConvertedFileSyncWithStamp] - ${e.toString()}`
            );
            reject(e);
          });
      });
    });
  }

  public async printTemplate({
    input = 'DOCX',
    output = 'DOCX',
    fileName,
    template,
    data,
  }: {
    input?: 'HTML' | 'PDF' | 'DOCX';
    output?: 'HTML' | 'PDF' | 'DOCX';
    fileName: string;
    template: File | Blob;
    data: unknown;
  }): Promise<File> {
    try {
      // Грязный хак
      const parameters: any = JSON.stringify(data);

      const [, name] = fileName.match(/(.*)\.[a-z0-9]+$/i) || [];
      const config = await configCreator();
      const { data: blob, headers } = await new PrintApi(config).processSync3(
        input,
        output,
        template,
        parameters,
        axiosBlobOptions
      );
      const type = headers['content-type'];
      return new File([blob], `${name}.${output.toLowerCase()}`, { type });
    } catch (e) {
      console.error(
        `[services/printer/getConvertedFileSyncWithStamp] - ${String(e)}`
      );
      throw e;
    }
  }

  public async signDocument({
    input = 'DOCX',
    fileName,
    document,
    certificate,
    data,
  }: {
    input?: 'HTML' | 'PDF' | 'DOCX';
    fileName: string;
    document: File | Blob;
    certificate: string;
    data: unknown;
  }): Promise<File> {
    try {
      // Грязный хак
      const parameters: any = JSON.stringify(data);

      const [, name] = fileName.match(/(.*)\.[a-z0-9]+$/i) || [];
      const config = await configCreator();
      const { data: blob, headers } = await new StampApi(config).processSync4(
        input,
        'PDF',
        certificate,
        document,
        parameters,
        axiosBlobOptions
      );
      const type = headers['content-type'];
      return new File([blob], `${name}.pdf`, { type });
    } catch (e) {
      console.error(
        `[services/printer/getConvertedFileSyncWithStamp] - ${String(e)}`
      );
      throw e;
    }
  }

  public async getConvertedFileSyncWithStamp({
    input = 'DOCX',
    output = 'PDF',
    fileName,
    template,
    certificate,
    data,
  }: {
    input?: 'HTML' | 'PDF' | 'DOCX';
    output?: 'HTML' | 'PDF' | 'DOCX';
    fileName: string;
    template: File | Blob;
    certificate: string;
    data: unknown;
  }): Promise<File> {
    try {
      // Грязный хак
      const parameters: any = JSON.stringify(data);

      const [, name] = fileName.match(/(.*)\.[a-z0-9]+$/i) || [];
      const config = await configCreator();
      const { data: document } = await new PrintApi(config).processSync3(
        input,
        output,
        template,
        parameters,
        axiosBlobOptions
      );
      const { data: blob, headers } = await new StampApi(config).processSync4(
        output,
        output,
        certificate,
        document,
        parameters,
        axiosBlobOptions
      );
      const type = headers['content-type'];
      return new File([blob], `${name}.${output.toLowerCase()}`, { type });
    } catch (e) {
      console.error(
        `[services/printer/getConvertedFileSyncWithStamp] - ${String(e)}`
      );
      throw e;
    }
  }

  public async getConvertedFileSyncWithStamp2({
    input = 'DOCX',
    output = 'PDF',
    fileName,
    template,
    parameters,
  }: {
    input?: 'HTML' | 'PDF' | 'DOCX';
    output?: 'HTML' | 'PDF' | 'DOCX';
    fileName: string;
    template: File | Blob;
    parameters: string;
  }): Promise<File> {
    const [, name] = fileName.match(/(.*)\.[a-z0-9]+$/i) || [];
    try {
      const config = await configCreator();
      const { data: blob, headers } = await new PrintStampApi(config).processSync2(
        input,
        output,
        template,
        parameters,
        axiosBlobOptions
      );
      const type = headers['content-type'];
      return new File([blob], `${name}.${output.toLowerCase()}`, { type });
    } catch (e) {
      console.error(
        `[services/printer/getConvertedFileSyncWithStamp] - ${String(e)}`
      );
      throw e;
    }
  }

  public fetchFileSyncWithStamp({
    input = 'PDF',
    output = 'PDF',
    fileName,
    document,
    certificate,
    parameters,
    download = true,
  }: any): Promise<Blob> {
    return new Promise((resolve, reject) => {
      configCreator().then((config) => {
        new StampApi(config)
          .processSync4(input, output, certificate, document, parameters, axiosBlobOptions)
          .then((response: AxiosResponse) => {
            if (download) {
              saveBlob({
                blob: response.data,
                fileName
              });
            }
            resolve(response.data);
          })
          .catch((e: Error) => {
            console.error(
              `[services/printer/fetchFileSyncWithStamp] - ${e.toString()}`
            );
            reject(e);
          });
      });
    });
  }

  public fetchConvertedFileSync({
    input = 'HTML',
    output = 'PDF',
    template,
    parameters,
    fileName = 'print.pdf',
    blobType = 'application/pdf',
    preventDownload = false,
  }: any): Promise<Blob | string> {
    return new Promise((resolve, reject) => {
      configCreator().then((config) => {
        new PrintApi(config)
          .processSync3(input, output, template, parameters, axiosBlobOptions)
          .then((response: AxiosResponse<Blob>) => {
            if (!preventDownload) {
              saveBlob({
                blob: response.data,
                fileName,
                blobType,
              });
            }
            resolve(response.data);
          })
          .catch((e: Error) => {
            console.error(
              `[services/printer/fetchConvertedFileSync] - ${e.toString()}`
            );
            reject(e);
          });
      });
    });
  }

  public normalizeFile({ template, parameters }: any): Promise<Blob | string> {
    return new Promise((resolve, reject) => {
      configCreator().then((config) => {
        new NormalizeApi(config)
          .processSync(template, parameters, axiosBlobOptions)
          .then((response: AxiosResponse<Blob>) => {
            const blob = new Blob([response.data], {
              type:
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            });
            resolve(blob);
          })
          .catch((e: Error) => {
            console.error(`[services/printer/normalizeFile] - ${e.toString()}`);
            reject(e);
          });
      });
    });
  }
}

export default new PrinterService();
