<template>
  <div class="transaction-create">
    <nav class="breadcrumb" aria-label="breadcrumbs" v-if="account">
      <ul>
        <li>
          <router-link :to="{ name: 'account', params: { id: account._id } }">{{ account.name }}</router-link>
        </li>
        <li v-if="tag && tag !== noTag">
          <a href="#" @click.prevent>{{ transactionTagLabel[tag].label }}</a>
        </li>
        <li class="is-active">
          <a href="#" @click.prevent>
            <span v-if="transaction._id">{{ name }}</span>
            <span v-else>Nouvelle dépense</span>
          </a>
        </li>
      </ul>
    </nav>
    <div class="columns">
      <div class="column">
        <div class="field is-horizontal">
          <div class="field-label is-normal">
            <label class="label">Nom</label>
          </div>
          <div class="field-body">
            <div class="field">
              <div class="control">
                <input
                  type="text"
                  class="input"
                  v-model.trim="name"
                  maxlength="30"
                  placeholder="Nom de la dépense"
                />
                <p
                  class="help is-info"
                >{{ $tc('validation.max_char', 30 - name.length, { max: 30 - name.length }) }}</p>
              </div>
            </div>
          </div>
        </div>
        <div class="field is-horizontal">
          <div class="field-label is-normal">
            <label class="label">Montant</label>
          </div>
          <div class="field-body">
            <div class="field">
              <div class="field has-addons">
                <p class="control is-expanded">
                  <input
                    type="number"
                    class="input"
                    v-model.number="amount"
                    placeholder="Montant"
                    inputmode="numeric"
                    pattern="[0-9]*"
                    min="0"
                    max="1000000"
                  />
                </p>
                <p class="control">
                  <span v-if="account.currencies.length > 1" class="select">
                    <select name="currency" id="currency" v-model="currency">
                      <option
                        v-for="(currency, k) in account.currencies"
                        :key="k"
                        :value="currency"
                      >{{ currency.symbol || currency.name }}</option>
                    </select>
                  </span>
                  <a
                    v-else
                    class="button is-static"
                  >{{ account.mainCurrency.symbol || account.mainCurrency.name }}</a>
                </p>
              </div>
              <p class="help is-info">montant max : {{ maxAmount | money(currency) }}</p>
            </div>
          </div>
        </div>
        <div class="field is-horizontal">
          <div class="field-label is-normal">
            <label class="label">Localisation</label>
          </div>
          <div class="field-body">
            <div class="field">
              <div class="control" v-if="transaction.location">
                <input type="text" readonly class="input" v-model="transaction.location.place" />
              </div>
            </div>
          </div>
        </div>
        <div class="field is-horizontal">
          <div class="field-label is-normal">
            <label class="label">Date</label>
          </div>
          <div class="field-body">
            <div class="field">
              <div class="control">
                <input type="date" class="input" v-model="date" placeholder="Date" :max="today" />
              </div>
            </div>
          </div>
        </div>
        <transaction-tag-update v-model="tag" />
      </div>
      <div class="column">
        <div class="field is-horizontal">
          <div class="field-label is-normal">
            <label class="label">Payé par</label>
          </div>
          <div class="field-body">
            <div class="field is-narrow">
              <div class="control">
                <div class="select is-fullwidth">
                  <select name="pay-by" id="pay-by" v-model="payBy">
                    <option
                      v-for="(user, k) in account.users"
                      :key="k"
                      :value="user.alias"
                    >{{ user.alias }}</option>
                  </select>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="field is-horizontal">
          <div class="field-label is-normal">
            <label class="label">Pour</label>
            <button
              class="button is-primary is-small"
              :class="{ 'is-outlined': payForUsers.length !== account.users.length}"
              type="button"
              @click="selectAll"
            >tous</button>
          </div>
          <div class="field-body">
            <div class="field is-narrow">
              <div class="control">
                <div v-for="(split, k) in payFor" :key="k" class="user-item">
                  <transaction-split :split="payFor[k]" />
                  <hr v-if="k !== payFor.length - 1" />
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <fab-button @valid="submitTransaction" :margin="true" :button-style="backgroundColor">
      <awe-icon icon="check" />
    </fab-button>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue, Watch } from 'vue-property-decorator'
import { Getter } from 'vuex-class'
import IAccount from '@/models/IAccount'
import ICurrency from '@/models/ICurrency'
import ITransaction from '@/models/ITransaction'
import IUser from '@/models/IUser'
import ISplit from '@/models/ISplit'
import TransactionType from '@/enums/TransactionType'
import TransactionTag, { TransactionTagLabel } from '@/enums/TransactionTag'
import accountService from '@/services/AccountService'
import exchangeService from '@/services/ExchangeService'
import transactionService from '@/services/TransactionService'
import formatDate from '@/utils/format-date'
import notif from '@/utils/notif'
import { money } from '@/utils/filters'
import { confirmation, alertMessage, findDarkValue } from '@/utils'

const today: Date = new Date()

@Component({
  components: {
    'fab-button': () => import('@/components/FabButton.vue'),
    'transaction-split': () => import('@/components/TransactionSplit.vue'),
    'transaction-tag-update': () =>
      import('@/components/TransactionTagUpdate.vue')
  }
})
export default class TransactionCreate extends Vue {
  @Getter
  public user!: IUser | null
  @Prop({ type: Object, required: true })
  public transaction!: ITransaction
  @Prop({ type: Object, required: true })
  public account!: IAccount
  public name: string = ''
  public amount: number | null = null
  public tag: TransactionTag = TransactionTag.None
  public today: string = formatDate(today)
  public date: string = formatDate(today)
  public location: string = ''
  public currency: ICurrency | null = null
  public payBy: string = ''
  public payFor: ISplit[] = []
  public maxAmount: number = 1000000
  public noTag: string = TransactionTag.None
  public transactionTagLabel: typeof TransactionTagLabel = TransactionTagLabel

  public async created(): Promise<void> {
    this.setData(this.transaction)
  }

  public setData(transaction: ITransaction): void {
    this.name = transaction.name
    this.date = formatDate(transaction.date)
    this.tag = transaction.tag
    this.amount = transaction.amount || null
    this.payBy = transaction.payBy
    this.payFor = transaction.payFor
    if (this.account.users) {
      this.account.users.forEach((user: IUser) => {
        if (!transaction.payFor.find((p: ISplit) => p.alias === user.alias)) {
          this.payFor.push({
            alias: user.alias || '',
            weight: 0
          })
        }
      })
    }
    this.currency = transaction.mainCurrency
  }

  public async submitTransaction(next: any): Promise<void> {
    if (!this.validate()) {
      next()
      return
    }
    if (!this.currency || !this.account) {
      next()
      return
    }
    const currencies: string[] = this.account.currencies.map(
      (c: ICurrency) => c.code
    )
    const date: Date = new Date(this.date)
    const hasId: boolean = !!this.transaction._id
    const amount: number = this.amount
      ? parseFloat(this.amount.toString().replace(',', '.'))
      : 0
    const transaction: ITransaction = {
      _id: this.transaction._id,
      _rev: this.transaction._rev,
      doctype: this.transaction.doctype,
      accountId: this.account._id || '',
      name: this.name,
      date,
      tag: this.tag,
      amount,
      payBy: this.payBy,
      payFor: this.payForUsers,
      userIds: this.account.userIds,
      mainCurrency: this.currency,
      currencies: this.account.currencies,
      transactionType: TransactionType.normal,
      exchange: await exchangeService.get(this.currency.code, date, currencies)
    }
    const response: PouchDB.Core.Response = hasId
      ? await transactionService.save(transaction)
      : await transactionService.add(this.account._id || '', transaction)
    if (response.ok) {
      if (hasId) {
        this.$router.push({
          name: 'transaction',
          params: { id: this.transaction._id || '' }
        })
        confirmation('Dépense mise à jour.')
      } else {
        this.$router.push({
          name: 'account',
          params: { id: this.account._id || '' }
        })
        confirmation('Dépense créée.')
      }
    } else {
      // tslint:disable-next-line:no-console
      console.warn(response)
      alertMessage(`Une erreur s'est produite à la création d'une transaction.`)
    }
    next()
  }

  public selectAll(): void {
    if (!this.account) {
      return
    }
    this.payFor.forEach((p: ISplit) => (p.weight = p.weight || 1))
  }

  public get payForUsers(): ISplit[] {
    return this.payFor.filter((p, index) => p.weight > 0)
  }

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

  @Watch('payBy')
  public onPayByChange(payBy: string, oldPayBy: string) {
    if (
      oldPayBy &&
      this.account &&
      this.payFor.length !== this.account.users.length
    ) {
      const old = this.payFor.find((p: ISplit) => p.alias === oldPayBy)
      if (old) {
        old.weight = 0
      }
    }
    if (payBy) {
      const newPayBy = this.payFor.find((p: ISplit) => p.alias === payBy)
      if (newPayBy) {
        newPayBy.weight = newPayBy.weight || 1
      }
    }
  }

  private validate(): boolean {
    if (
      !this.name ||
      !this.amount ||
      (!this.currency && !this.date && this.payFor.length === 0)
    ) {
      if (this.amount === 0) {
        notif.error('Le montant doit être supérieur à 0.')
      } else {
        notif.error('Tous les champs sont requis.')
      }
      return false
    }
    if (isNaN(this.amount) || this.amount > this.maxAmount) {
      notif.error(
        `Veuillez saisir un montant numérique inférieur à ${money(
          this.maxAmount,
          this.currency
        )}.`
      )
      return false
    }
    if (this.amount < 0) {
      notif.error('Le montant doit être supérieur à 0.')
      return false
    }
    return true
  }
}
</script>

<style scoped>
.help {
  text-align: left;
}
</style>
