import { Client } from 'cozy-client'
import { Konnector } from 'doctypes'
import triggersMutations from 'cozy-harvest-lib/dist/connections/triggers'
import FluidConfigService from 'services/fluidConfigService'
import { AccountService } from 'services/accountService'
import { FluidType } from 'enum/fluid.enum'

export default class KonnectorStatusService {
  private _client: Client

  constructor(_client: Client) {
    this._client = _client
  }

  getKonnectorsStatus() {
    return 'konnector status'
  }

  // TODO - move to triggerservices
  async getTriggerbyKonnector(konnector: Konnector) {
    const query = this._client
      .find('io.cozy.triggers')
      .where({ 'message.konnector': konnector.slug })
      .sortBy([{ 'cozyMetadata.updatedAt': 'desc' }])
      .limitBy(1)

    return await this._client.query(query)
  }

  async getTriggerbyKonnectorSlug(konnectorSlug: string) {
    const query = this._client
      .find('io.cozy.triggers')
      .where({ 'message.konnector': konnectorSlug })
      .sortBy([{ 'cozyMetadata.updatedAt': 'desc' }])
      .limitBy(1)

    return await this._client.query(query)
  }

  async getAllTriggers() {
    const query = this._client.find('io.cozy.triggers')
    const result = await this._client.query(query)
    return result.data
  }

  async getAllJobs() {
    const query = this._client.find('io.cozy.jobs')
    return await this._client.query(query)
  }

  async getAllKonnectors() {
    const query = this._client.find('io.cozy.konnectors')
    const result = await this._client.query(query)
    return result.data
  }

  static async getSingleTrigger(client: Client, id: string) {
    try {
      const trigger = await triggersMutations(client).fetchTrigger(id)
      return trigger
    } catch (error) {
      throw error
    }
  }

  /**
   * Return a FluidType array containing each konnector fluid with a trigger
   * @param void
   * @return {Promise<FluidType[]>} configured FluidTypes array
   */
  async getKonnectorTiggerStatus(): Promise<FluidType[]> {
    try {
      const fluidConfig = new FluidConfigService().getFluidConfig()
      const [elecData, gasData, waterData] = await Promise.all([
        this.getTriggerbyKonnectorSlug(
          fluidConfig[FluidType.ELECTRICITY].konnectorConfig.slug
        ),
        this.getTriggerbyKonnectorSlug(
          fluidConfig[FluidType.GAS].konnectorConfig.slug
        ),
        this.getTriggerbyKonnectorSlug(
          fluidConfig[FluidType.WATER].konnectorConfig.slug
        ),
      ])
      const data: FluidType[] = []
      if (elecData && elecData.data && elecData.data[0]) {
        data.push(fluidConfig[FluidType.ELECTRICITY].fluidTypeId)
      }
      if (gasData && gasData.data && gasData.data[0]) {
        data.push(fluidConfig[FluidType.GAS].fluidTypeId)
      }
      if (waterData && waterData.data && waterData.data[0]) {
        data.push(fluidConfig[FluidType.WATER].fluidTypeId)
      }
      return data
    } catch (error) {
      throw error
    }
  }

  /**
   * Return a FluidType array containing each konnector fluid with a account
   * @param void
   * @return {Promise<FluidType[]>} configured FluidTypes array
   */
  async getKonnectorAccountStatus(): Promise<FluidType[]> {
    try {
      const fluidConfig = new FluidConfigService().getFluidConfig()
      const [elecData, gasData, waterData] = await Promise.all([
        AccountService.getAccountByType(
          this._client,
          fluidConfig[FluidType.ELECTRICITY].konnectorConfig.slug
        ),
        AccountService.getAccountByType(
          this._client,
          fluidConfig[FluidType.GAS].konnectorConfig.slug
        ),
        AccountService.getAccountByType(
          this._client,
          fluidConfig[FluidType.WATER].konnectorConfig.slug
        ),
      ])
      const data: FluidType[] = []
      if (elecData) {
        data.push(fluidConfig[FluidType.ELECTRICITY].fluidTypeId)
      }
      if (gasData) {
        data.push(fluidConfig[FluidType.GAS].fluidTypeId)
      }
      if (waterData) {
        data.push(fluidConfig[FluidType.WATER].fluidTypeId)
      }
      return data
    } catch (error) {
      throw error
    }
  }
}