import { api } from 'src/boot/axios';

interface BalanceResponse {
  balance: number;
  credit: number;
  debit: number;
  limit?: number;
}

export interface BalancesResponse extends BalanceResponse {
  userid: string;
}

export interface TransactionsResponse {
  transactions: Array<FG.Transaction>;
  count?: number;
}

import { defineStore } from 'pinia';
import { useMainStore } from 'src/store';
import { AxiosResponse } from 'axios';
import { Notify } from 'quasar';

function fixTransaction(t: FG.Transaction) {
  t.time = new Date(t.time);
}

export const useBalanceStore = defineStore({
  id: 'balance',

  state: () => ({
    balances: [] as BalancesResponse[],
    shortcuts: [] as number[],
    transactions: [] as FG.Transaction[],
    _balances_dirty: 0,
  }),

  getters: {
    balance() {
      const mainStore = useMainStore();
      return this.balances.find((v) => v.userid === mainStore.user?.userid);
    },
  },

  actions: {
    async createShortcut(shortcut: number) {
      const mainStore = useMainStore();
      this.shortcuts.push(shortcut);
      this.shortcuts.sort((a, b) => a - b);
      await api.put(`/users/${mainStore.currentUser.userid}/balance/shortcuts`, this.shortcuts);
    },

    async removeShortcut(shortcut: number) {
      const mainStore = useMainStore();
      this.shortcuts = this.shortcuts.filter((value: number) => value !== shortcut);
      this.shortcuts.sort((a, b) => a - b);
      await api.put(`/users/${mainStore.currentUser.userid}/balance/shortcuts`, this.shortcuts);
    },

    async getShortcuts(force = false) {
      if (force || this.shortcuts.length == 0) {
        const mainStore = useMainStore();
        const { data } = await api.get<number[]>(
          `/users/${mainStore.currentUser.userid}/balance/shortcuts`
        );
        this.shortcuts = data;
      }
    },

    async getBalance(user: FG.User) {
      const { data } = await api.get<BalanceResponse>(`/users/${user.userid}/balance`);
      const idx = this.balances.findIndex((x) => x.userid === user.userid);
      if (idx == -1) this.balances.push(Object.assign(data, { userid: user.userid }));
      else this.balances[idx] = Object.assign(data, { userid: user.userid });
      return data;
    },

    async getBalances(force = false) {
      if (
        force ||
        this.balances.length == 0 ||
        new Date().getTime() - this._balances_dirty > 60000
      ) {
        const { data } = await api.get<BalancesResponse[]>('/balance');
        this.balances = data;
      }
      return this.balances;
    },

    async changeBalance(amount: number, user: FG.User, sender: FG.User | undefined = undefined) {
      const mainStore = useMainStore();
      try {
        const { data } = await api.put<FG.Transaction>(`/users/${user.userid}/balance`, {
          amount,
          user: user.userid,
          sender: sender?.userid,
        });
        fixTransaction(data);
        if (
          user.userid === mainStore.currentUser.userid ||
          sender?.userid === mainStore.currentUser.userid
        )
          this.transactions.push(data);
        const f = this.balances.find((x) => x.userid === user.userid);
        if (f) f.balance += amount;
        if (sender) {
          const f = this.balances.find((x) => x.userid === sender.userid);
          if (f) f.balance += -1 * amount;
        }
        this._balances_dirty = 0;
        return data;
      } catch ({ response }) {
        // Maybe Balance changed
        if (response && (<AxiosResponse>response).status == 409) {
          Notify.create({
            type: 'negative',
            group: false,
            message: 'Das Limit wurde überschritten!',
            timeout: 10000,
            progress: true,
            actions: [{ icon: 'mdi-close', color: 'white' }],
          });
          //void this.getTransactions(true);
          void this.getBalance(sender ? sender : user);
        }
      }
    },

    async getTransactions(
      user: FG.User,
      filter:
        | {
            limit?: number;
            offset?: number;
            from?: Date;
            to?: Date;
            showReversals?: boolean;
            showCancelled?: boolean;
          }
        | undefined = undefined
    ) {
      if (!filter) filter = { limit: 10 };
      const { data } = await api.get<TransactionsResponse>(
        `/users/${user.userid}/balance/transactions`,
        { params: filter }
      );
      data.transactions.forEach((t) => fixTransaction(t));
      if (data.transactions) this.transactions.push(...data.transactions);
      return data;
    },

    async revert(transaction: FG.Transaction) {
      try {
        const { data } = await api.delete<FG.Transaction>(`/balance/${transaction.id}`);
        fixTransaction(data);
        const f = this.transactions.find((x) => x.id === transaction.id);
        if (f) f.reversal_id = data.id;
        this.transactions.push(data);
        console.log(data);
      } catch (error) {
        // ...
      }
      this._balances_dirty = 0;
    },
  },
});