import couchService from '@/services/CouchService'
import IAccount from '@/models/IAccount'
import ITransaction from '@/models/ITransaction'
import transactionService from '@/services/TransactionService'
import { slug } from '@/utils'
import IEncryptable from '@/models/IEncryptable'
import IEncrypted from '@/models/IEncrypted'

class AccountService {
  public async get(id: string): Promise<IAccount | null> {
    const account: IAccount = await couchService.get(id)
    if (!account) {
      return null
    }
    return account
  }

  public async getRemote(id: string): Promise<IAccount | null> {
    const account: IAccount = await couchService.getRemote(id)
    if (!account) {
      return null
    }
    return account
  }

  public async add(account: IAccount): Promise<PouchDB.Core.Response> {
    try {
      account.slug = slug(account.name)
      const id = couchService.newId('acc', true)
      account._id = id
      account.doctype = 'account'
      const response = await couchService.save(account)
      return response
    } catch (error) {
      // tslint:disable-next-line:no-console
      console.warn({ error })
      return {
        ok: false,
        id: '',
        rev: ''
      }
    }
  }

  public async active(id: string): Promise<boolean> {
    try {
      const account = await this.get(id)
      if (account) {
        account.archive = false
      }
      const { ok } = await couchService.save(account)
      return ok
    } catch (error) {
      // tslint:disable-next-line:no-console
      console.info('erreur dans la cloture du compte', {
        error
      })
    }
    return false
  }

  public async archive(id: string): Promise<boolean> {
    try {
      const account = await this.get(id)
      if (account) {
        account.archive = true
      }
      const { ok } = await couchService.save(account)
      return ok
    } catch (error) {
      // tslint:disable-next-line:no-console
      console.info('erreur dans la cloture du compte', {
        error
      })
    }
    return false
  }

  public async remove(id: string): Promise<boolean> {
    try {
      const transactions: ITransaction[] = await transactionService.getAllByAccountId(
        id
      )
      transactions.forEach((transaction: ITransaction) => {
        transaction._deleted = true
      })
      await transactionService.multipleSave(transactions)
    } catch (error) {
      // tslint:disable-next-line:no-console
      console.info('erreur dans la suppression des transactions associées', {
        error
      })
    }
    return await couchService.remove(id)
  }

  public async getAll(archived: boolean = false): Promise<IAccount[]> {
    try {
      const response = await couchService.getByPrefix('acc')
      const accounts = response.rows.map((row: any) => row.doc) as IAccount[]
      const result = []
      for (const account of accounts) {
        if ((archived && account.archive) || (!archived && !account.archive)) {
          result.push(account)
        }
      }
      return result
    } catch (error) {
      // tslint:disable-next-line:no-console
      console.warn('get all', { error })
      return []
    }
  }

  public async update(id: string, account: IAccount): Promise<boolean> {
    const response = await couchService.get(id)
    if (response) {
      const result = await couchService.save({
        ...account,
        _id: id,
        doctype: 'account'
      })
      account._rev = result.rev
      return result.ok
    }
    return false
  }

  private toEncrypt(account: IAccount): IEncryptable | IEncrypted {
    if (!account) {
      return {}
    }
    return {
      name: account.name,
      slug: account.slug,
      premium: account.premium
    }
  }
}

export default new AccountService()
