import getConfig from 'next/config';
import { saveAs } from 'file-saver';
import { action, observable, extendObservable, computed, makeObservable } from 'mobx';
import { IProfile, IDepartment, IAccountTransaction } from 'typings';
import axios from 'axios';
import { formatDate } from 'utils/helpers';
import Authentication from './authentication';

const { publicRuntimeConfig } = getConfig();

const customerBsUrl = publicRuntimeConfig.CUSTOMER_BS_URL;
const baseUrl = `${customerBsUrl}/api/accounts`;

export interface IProfiles {
  ssn: string;
  name: string;
  isCompany: boolean;
  isRegistered: boolean;
  perPage: number;
  departments: IDepartment[];
  transactions: IAccountTransaction[];
  subscriptions: IProfile[];
  updateDepartments: (departments: IDepartment[]) => void;
  summaryTotalSum: number;
  summaryTotalForeignSum: number;
  allSelected: boolean;
  clearTransactions: () => void;
  addSubscription: (profile: IProfile) => void;
  addTransaction: (t: IAccountTransaction) => void;
  transactionsPdf: (input: PdfInput) => void;
}

type PdfInput = {
  ssn: string;
  from: Date;
  to: Date;
  id: string;
};

type InitalState = {
  profiles?: object;
};
export default class Profiles implements IProfiles {
  private authentication: Authentication;

  constructor({ profiles = {} }: InitalState, authentication: Authentication) {
    makeObservable(this, {
      ssn: observable,
      name: observable,
      isCompany: observable,
      isRegistered: observable,
      perPage: observable,
      departments: observable,
      transactions: observable,
      subscriptions: observable,
      updateDepartments: action,
      summaryTotalSum: computed,
      summaryTotalForeignSum: computed,
      summarySubscriptions: computed,
      selectedSubscriptions: computed,
      allSelected: computed,
      clearTransactions: action,
      addSubscription: action,
      addTransaction: action,
      transactionsPdf: action,
    });

    extendObservable(this, profiles);
    this.authentication = authentication;
  }

  ssn = '';

  name = '';

  isCompany = false;

  isRegistered = true;

  perPage = 30;

  departments: IDepartment[] = [];

  transactions: IAccountTransaction[] = [];

  subscriptions: IProfile[] = [];

  updateDepartments(departments: IDepartment[]) {
    this.departments = departments;
  }

  get summaryTotalSum() {
    return this.summarySubscriptions.reduce((p, s: IProfile) => p + (s.summary.totalSum || 0), 0);
  }

  get summaryTotalForeignSum() {
    return this.summarySubscriptions.reduce(
      (p, s: IProfile) => p + (s.summary.totalForeignSum || 0),
      0,
    );
  }

  get summarySubscriptions() {
    return this.subscriptions.filter((i: IProfile) => i.summary !== null);
  }

  get selectedSubscriptions() {
    return this.subscriptions.filter((i: IProfile) => i.selected).length;
  }

  get allSelected() {
    return this.selectedSubscriptions === this.subscriptions.length;
  }

  clearTransactions() {
    this.transactions = [];
  }

  addSubscription(profile: IProfile) {
    const index = this.subscriptions.findIndex(
      (i: IProfile) => i.subscriptionId === profile.subscriptionId,
    );

    if (index !== -1) {
      // replace
      this.subscriptions[index] = profile;
      return;
    }
    this.subscriptions.push(profile);
  }

  addTransaction(transaction: IAccountTransaction) {
    const index = this.transactions.findIndex(
      (i: IAccountTransaction) => i.transactionId === transaction.transactionId,
    );

    if (index !== -1) {
      // replace
      this.transactions.splice(index, 1);
      return;
    }
    this.transactions.push(transaction);
  }

  async transactionsPdf({ id, from, to, ssn }: PdfInput) {
    const TOKEN = this.authentication.token;

    try {
      const { data } = await axios.get<Iterable<number>>(
        `${baseUrl}/${ssn || this.ssn}/transactions/export`,
        {
          headers: {
            Authorization: `Bearer ${TOKEN}`,
          },
          responseType: 'arraybuffer',
          params: {
            ssn: ssn || this.ssn,
            id,
            from,
            to,
          },
        },
      );

      const excel = from && to && `${formatDate(from, 'd.M.yyyy')} - ${formatDate(to, 'd.M.yyyy')}`;
      const extension = !id ? 'xlsx' : id.length > 1 ? 'zip' : 'pdf';
      const file = new Blob([new Uint8Array(data)], { type: `application/${extension}` });
      const fileName = !id ? `${excel}.${extension}` : `${id}.${extension}`;

      saveAs(file, fileName);
    } catch (e) {
      // TODO: improve error handling
    }
  }
}
