<template>
  <section class="hero is-fullheight account-item" v-if="account">
    <account-encrypted v-if="isEncrypted" />
    <div class="account-item-container">
      <h2 class="title is-2">
        {{ account.name }}
        <router-link
          v-if="isAdmin"
          class="tag"
          :to="{ name: 'account-setting', params: { id } }"
        >
          <awe-icon icon="cog" />
        </router-link>
      </h2>
      <div class="columns is-centered" v-if="showShare">
        <div class="column is-one-third">
          <account-share :account="account" />
        </div>
      </div>
      <article
        class="message is-warning"
        v-if="transactionWithoutExchange.length"
      >
        <div class="message-header">
          <p>Attention</p>
        </div>
        <div class="message-body">
          Certaines dépenses ne sont pas comptées car en attente de récupérer
          les taux pratiqués à leur date respectives.
          <ul>
            <li v-for="(transaction, k) in transactionWithoutExchange" :key="k">
              -
              <router-link
                :to="{ name: 'transaction', params: { id: transaction._id } }"
                >{{ transaction.name }}</router-link
              >
            </li>
          </ul>
          <online-view @online="retrieveExchange">
            <button
              @click="retrieveExchange"
              class="button is-success is-large is-rounded"
              :class="{ 'is-loading': retrievingExchange }"
            >
              Récupérer les devises
            </button>
          </online-view>
        </div>
      </article>
      <div class="tabs is-toggle is-fullwidth" v-if="transactions.length">
        <ul>
          <li :class="{ 'is-active': activeTab === 'transaction' }">
            <a href="#" @click.prevent="toggleTab('transaction')">
              <awe-icon icon="dollar-sign" />
            </a>
          </li>
          <li :class="{ 'is-active': activeTab === 'tag' }" v-if="tagCount > 1">
            <a href="#" @click.prevent="toggleTab('tag')">
              <awe-icon icon="tag" />
            </a>
          </li>
          <li
            :class="{ 'is-active': activeTab === 'balance' }"
            v-if="isMultiUser"
          >
            <a href="#" @click.prevent="toggleTab('balance')">
              <awe-icon icon="balance-scale" />
            </a>
          </li>
          <li
            :class="{ 'is-active': activeTab === 'refund' }"
            v-if="isMultiUser"
          >
            <a href="#" @click.prevent="toggleTab('refund')">
              <awe-icon icon="exchange-alt" />
            </a>
          </li>
        </ul>
      </div>
      <transition-group
        :name="transitionName"
        tag="div"
        mode="out-in"
        v-if="transactions.length"
      >
        <div
          key="transaction"
          class="transaction-panel tab-content columns is-centered"
          v-if="activeTab === 'transaction'"
        >
          <div class="column">
            <account-transaction-list
              :account="account"
              :transactions="transactions"
            />
          </div>
        </div>
        <div
          key="tag"
          class="tag-panel tab-content columns is-centered"
          v-if="activeTab === 'tag'"
        >
          <div class="column">
            <tag-list
              :transactions="transactionWithoutRefund"
              :account="account"
            />
          </div>
        </div>
        <div
          key="balance"
          class="balance-panel tab-content columns is-centered"
          v-if="activeTab === 'balance'"
        >
          <div class="column">
            <chart-balance
              :stats="userStats"
              :currency="account.mainCurrency"
            />
          </div>
        </div>
        <div
          key="refund"
          class="refund-panel tab-content columns is-centered"
          v-if="activeTab === 'refund'"
        >
          <div class="column">
            <div
              v-if="userRefunds.length"
              class="columns is-centered is-multiline"
            >
              <div
                class="column is-one-fifth"
                v-for="(refund, k) in userRefunds"
                :key="`${refund.from.alias}-${refund.to.alias}`"
              >
                <refund-transaction
                  :refund="userRefunds[k]"
                  :account="account"
                />
              </div>
            </div>
            <div v-else class="equilibrium">Le compte est à l'équilibre !</div>
          </div>
        </div>
      </transition-group>
    </div>
    <fab-button
      v-if="!account.archive"
      :to="{ name: 'transaction-new', params: { id: account._id } }"
      :button-style="backgroundColor"
      :margin="true"
    >
      <awe-icon icon="money-bill-wave" />
      <span slot="fulltext">dépense</span>
    </fab-button>
  </section>
</template>

<script lang="ts">
import { Component, Watch } from 'vue-property-decorator'
import { Action, Getter } from 'vuex-class'
import BaseAccount from '@/base-components/BaseAccount'
import bus, { SYNC } from '@/utils/bus-event'
import notif from '@/utils/notif'
import TransactionType from '@/enums/TransactionType'
import accountService from '@/services/AccountService'
import chartService from '@/services/ChartService'
import balanceService from '@/services/BalanceService'
import transactionService from '@/services/TransactionService'
import exchangeService from '@/services/ExchangeService'
import IAccount from '@/models/IAccount'
import IBalance from '@/models/IBalance'
import ICurrency from '@/models/ICurrency'
import IRefund from '@/models/IRefund'
import IStat from '@/models/IStat'
import ITransaction from '@/models/ITransaction'
import IUser from '@/models/IUser'
import { primary, main, findContrastColor, findDarkValue } from '@/utils'

@Component({
  components: {
    'account-share': () => import('@/components/AccountShare.vue'),
    'account-encrypted': () => import('@/components/AccountEncrypted.vue'),
    'account-transaction-list': () =>
      import('@/components/AccountTransactionList.vue'),
    'tag-list': () => import('@/components/TagList.vue'),
    'chart-balance': () => import('@/components/ChartBalance.vue'),
    'online-view': () => import('@/components/OnlineView.vue'),
    'refund-transaction': () => import('@/components/RefundTransaction.vue'),
    'fab-button': () => import('@/components/FabButton.vue')
  }
})
export default class AccountItem extends BaseAccount {
  @Action
  public setTitle!: any
  public retrieveTransactions: boolean = false
  public transactions: ITransaction[] = []
  public activeTab: string = 'transaction'
  public retrievingExchange: boolean = false
  public transitionName: string = ''

  public async getData(docIds?: string[]): Promise<void> {
    if (docIds && !docIds.find((i: string) => i === this.id)) {
      return
    }
    try {
      if (this.id) {
        this.account = await accountService.get(this.id)
        if (!this.account) {
          notif.error(`le compte ${this.id} n'existe pas`)
          this.$router.push({ name: 'home' })
          return
        }
        this.transactions = await transactionService.getAllByAccountId(this.id)
        this.retrieveTransactions = true
        if (document && document.documentElement) {
          if (this.account.color) {
            document.documentElement.style.setProperty(
              '--primary-color',
              this.account.color
            )
            document.documentElement.style.setProperty(
              '--primary-font-color',
              findDarkValue(this.account.color) || main
            )
          } else {
            document.documentElement.style.setProperty(
              '--primary-color',
              primary
            )
            document.documentElement.style.setProperty(
              '--primary-font-color',
              main
            )
          }
        }
        this.setTitle(this.account.name)
      }
    } catch (error) {
      // tslint:disable-next-line
      console.error({ error })
      this.$router.push({ name: 'home' })
      return
    }
  }

  public toggleTab(tab: string): void {
    this.activeTab = tab
  }

  public async retrieveExchange(): Promise<void> {
    if (!this.transactionWithoutExchange.length) {
      return
    }
    this.retrievingExchange = true
    try {
      const transactions: ITransaction[] = [...this.transactionWithoutExchange]
      for (const transaction of transactions) {
        transaction.exchange = await exchangeService.get(
          transaction.mainCurrency.code,
          transaction.date
        )
      }
      await transactionService.multipleSave(transactions)
      notif.success('Dépenses mises à jour.')
    } catch (error) {
      // tslint:disable-next-line
      console.warn({ error })
    }
    this.retrievingExchange = false
  }

  public totalCostByUserAlias(alias: string): number {
    if (!this.account) {
      return 0
    }
    const transactions: ITransaction[] = this.transactionWithExchange
    return transactionService.getTotalCost(
      transactions,
      this.account.mainCurrency.code,
      alias
    )
  }

  public get totalUserCost(): Array<{ alias: string; total: number }> {
    if (!this.account) {
      return []
    }
    return this.account.users
      .map((user: IUser) => ({
        alias: user.alias || '',
        total: this.totalCostByUserAlias(user.alias || '')
      }))
      .filter((user) => user.total > 0)
  }

  public get showShare(): boolean {
    return !!(
      this.account &&
      this.account.users.length > 1 &&
      this.retrieveTransactions &&
      !this.transactions.length
    )
  }

  public get transactionWithoutRefund(): ITransaction[] {
    if (!this.transactions) {
      return []
    }
    return this.transactions.filter(
      (transaction: ITransaction) =>
        transaction.transactionType === TransactionType.normal
    )
  }

  public get tagCount(): number {
    const tags = new Set(
      this.transactionWithoutRefund.map(
        (transaction: ITransaction) => transaction.tag
      )
    )
    return tags.size
  }

  public get transactionWithExchange(): ITransaction[] {
    if (!this.transactions) {
      return []
    }
    return this.transactions.filter(
      (transaction: ITransaction) => !!transaction.exchange
    )
  }

  public get transactionWithoutExchange(): ITransaction[] {
    if (!this.transactions) {
      return []
    }
    return this.transactions.filter(
      (transaction: ITransaction) => !transaction.exchange
    )
  }

  public get userStats(): IStat[] {
    const totalCost: number = this.totalCost
    if (!this.account || totalCost === 0) {
      return []
    }
    const account: IAccount = this.account
    const transactions: ITransaction[] = this.transactionWithExchange
    const mainCurrency: ICurrency = account.mainCurrency
    return this.account.users.map((user: IUser) => {
      const userCost: number = transactionService.getTotalCost(
        transactions,
        account.mainCurrency.code,
        user.alias
      )
      const percent: number = Math.round((userCost / totalCost) * 100)
      return {
        label: user.alias || '',
        value: userCost,
        percent,
        balance: balanceService.getBalanceByUser(
          user,
          mainCurrency,
          transactions
        )
      }
    })
  }

  public get myTotalCost(): number {
    if (!this.account) {
      return 0
    }
    const transactions: ITransaction[] = this.transactionWithExchange
    return transactionService.getTotalCost(
      transactions,
      this.account.mainCurrency.code,
      this.userAlias
    )
  }

  public get totalCost(): number {
    if (!this.account) {
      return 0
    }
    const transactions: ITransaction[] = this.transactionWithExchange
    return transactionService.getTotalCost(
      transactions,
      this.account.mainCurrency.code
    )
  }

  public get userBalance(): IBalance[] {
    if (!this.account || !this.account.users) {
      return []
    }
    const mainCurrency: ICurrency = this.account.mainCurrency
    const transactions: ITransaction[] = this.transactionWithExchange
    return this.account.users.map((user: IUser) =>
      balanceService.getBalanceByUser(user, mainCurrency, transactions)
    )
  }

  public get userRefunds(): IRefund[] {
    if (!this.account) {
      return []
    }
    return balanceService.getRefund(this.userBalance)
  }

  public get isAdmin(): boolean {
    if (!this.account || !this.account.admin || !this.user) {
      return true
    }
    return this.account.admin.slugEmail === this.user.slugEmail
  }

  public get userAlias(): string {
    if (!this.account || !this.user) {
      return ''
    }
    const mainUser = this.user
    const user = this.account.users.find(
      (u: IUser) => u.slugEmail === mainUser.slugEmail
    )
    return (user && user.alias) || ''
  }

  public get isEncrypted(): boolean {
    return !!(this.account && this.account.name.length > 30)
  }

  public get backgroundColor(): any | null {
    if (!this.account || !this.account.color) {
      return null
    }
    return {
      backgroundColor: this.account.color,
      color: findContrastColor(this.account.color) || 'black'
    }
  }

  public get isMultiUser(): boolean {
    return !!this.account && this.account.users.length > 1
  }

  @Watch('activeTab')
  public onActiveTabChange(newTab: string, oldTab: string): void {
    const tabs: string[] = ['transaction', 'tag', 'balance', 'refund']
    this.transitionName =
      tabs.indexOf(newTab) > tabs.indexOf(oldTab) ? 'slide-left' : 'slide-right'
  }
}
</script>

<style lang="scss">
@import '../../styles/variables';
.account-item {
  font-size: 14pt;

  h2.title,
  a {
    color: var(--primary-font-color);
  }

  table tr.is-selected {
    background-color: var(--primary-color);
    color: var(--primary-font-color);
  }

  .tabs.is-toggle {
    max-width: 400pt;
    margin: auto;
    li.is-active {
      a {
        background-color: var(--primary-color);
        border-color: var(--primary-color);
        color: var(--primary-font-color);
      }
    }
  }
  .tabs.is-toggle {
    a {
      height: 35pt;
      width: 35pt;
      border-radius: 50%;
      margin: auto;
      border-width: 2px;
      font-size: 14pt;
    }
    li:first-child,
    li:last-child {
      a {
        border-radius: 50%;
      }
    }
  }
  &.hero {
    &.is-fullheight {
      min-height: calc(100vh - 52px);
    }
  }
  .equilibrium {
    font-size: 25pt;
    color: var(--primary-font-color);
  }
  table.table {
    margin: auto;
  }
  th,
  .pay-by {
    text-align: center;
  }
  .numeric {
    text-align: right;
  }
  .table-container {
    overflow-x: auto;
  }
  .total-panel {
    font-size: 16pt;
  }
}
.no-transaction {
  font-size: 16pt;
}
.tab-content {
  position: absolute;
  width: calc(100% - 30px);
  margin: auto;
  transition: opacity 0.5s cubic-bezier(0.55, 0, 0.1, 1),
    transform 0.5s cubic-bezier(0.55, 0, 0.1, 1);
  &.columns {
    &:last-child {
      margin-bottom: 60px;
    }
  }
}
.slide-left-enter,
.slide-right-leave-active {
  opacity: 0;
  transform: translate(15px, 0);
}
.slide-left-leave-active,
.slide-right-enter {
  opacity: 0;
  transform: translate(-15px, 0);
}
.table {
  th,
  td {
    vertical-align: middle;
  }
}
.account-item-container {
  flex: 1;
}
</style>
