import { writable } from "svelte/store"
import api from "../../api"
import Automation from "./Automation"
import { cloneDeep } from "lodash/fp"
import analytics from "analytics"

const automationActions = store => ({
  fetch: async () => {
    const responses = await Promise.all([
      api.get(`/api/automations`),
      api.get(`/api/automations/definitions/list`),
    ])
    const jsonResponses = await Promise.all(responses.map(x => x.json()))
    store.update(state => {
      let selected = state.selectedAutomation?.automation
      state.automations = jsonResponses[0]
      state.blockDefinitions = {
        TRIGGER: jsonResponses[1].trigger,
        ACTION: jsonResponses[1].action,
      }
      // if previously selected find the new obj and select it
      if (selected) {
        selected = jsonResponses[0].filter(
          automation => automation._id === selected._id
        )
        state.selectedAutomation = new Automation(selected[0])
      }
      return state
    })
  },
  create: async ({ name }) => {
    const automation = {
      name,
      type: "automation",
      definition: {
        steps: [],
      },
    }
    const CREATE_AUTOMATION_URL = `/api/automations`
    const response = await api.post(CREATE_AUTOMATION_URL, automation)
    const json = await response.json()
    store.update(state => {
      state.automations = [...state.automations, json.automation]
      store.actions.select(json.automation)
      return state
    })
  },
  save: async ({ automation }) => {
    const UPDATE_AUTOMATION_URL = `/api/automations`
    const response = await api.put(UPDATE_AUTOMATION_URL, automation)
    const json = await response.json()
    store.update(state => {
      const existingIdx = state.automations.findIndex(
        existing => existing._id === automation._id
      )
      state.automations.splice(existingIdx, 1, json.automation)
      state.automations = state.automations
      store.actions.select(json.automation)
      return state
    })
  },
  delete: async ({ automation }) => {
    const { _id, _rev } = automation
    const DELETE_AUTOMATION_URL = `/api/automations/${_id}/${_rev}`
    await api.delete(DELETE_AUTOMATION_URL)

    store.update(state => {
      const existingIdx = state.automations.findIndex(
        existing => existing._id === _id
      )
      state.automations.splice(existingIdx, 1)
      state.automations = state.automations
      state.selectedAutomation = null
      state.selectedBlock = null
      return state
    })
  },
  trigger: async ({ automation }) => {
    const { _id } = automation
    return await api.post(`/api/automations/${_id}/trigger`)
  },
  test: async ({ automation }, testData) => {
    const { _id } = automation
    const response = await api.post(`/api/automations/${_id}/test`, testData)
    const json = await response.json()
    store.update(state => {
      state.selectedAutomation.testResults = json
      return state
    })
  },
  select: automation => {
    store.update(state => {
      state.selectedAutomation = new Automation(cloneDeep(automation))
      state.selectedBlock = null
      return state
    })
  },
  addTestDataToAutomation: data => {
    store.update(state => {
      state.selectedAutomation.addTestData(data)
      return state
    })
  },
  addBlockToAutomation: block => {
    store.update(state => {
      const newBlock = state.selectedAutomation.addBlock(cloneDeep(block))
      state.selectedBlock = newBlock
      return state
    })
    analytics.captureEvent("Added Automation Block", {
      name: block.name,
    })
  },
  deleteAutomationBlock: block => {
    store.update(state => {
      const idx =
        state.selectedAutomation.automation.definition.steps.findIndex(
          x => x.id === block.id
        )
      state.selectedAutomation.deleteBlock(block.id)

      // Select next closest step
      const steps = state.selectedAutomation.automation.definition.steps
      let nextSelectedBlock
      if (steps[idx] != null) {
        nextSelectedBlock = steps[idx]
      } else if (steps[idx - 1] != null) {
        nextSelectedBlock = steps[idx - 1]
      } else {
        nextSelectedBlock =
          state.selectedAutomation.automation.definition.trigger || null
      }
      state.selectedBlock = nextSelectedBlock
      return state
    })
  },
})

export const getAutomationStore = () => {
  const INITIAL_AUTOMATION_STATE = {
    automations: [],
    blockDefinitions: {
      TRIGGER: [],
      ACTION: [],
    },
    selectedAutomation: null,
  }
  const store = writable(INITIAL_AUTOMATION_STATE)
  store.actions = automationActions(store)
  return store
}
