import { analyzeOperationResults } from "@racletteCore/lib/dataHelper"
import configService from "@racletteCore/lib/configService"
import { $eventbus, $store } from "@racletteCore/main"
import type { SnackbarMessage } from "@racletteOrchestrator/components/snackbar/SnackStack.vue"
/**
 * userNotifier
 */
const shouldBePrevented = (notificationType: string, filter: any) => {
  let prevent = false
  const preventNotifications = configService.getPreventNotifications()
  const preventType = preventNotifications[notificationType]
  if (preventType) {
    if (filter) {
      for (const [key, value] of Object.entries(filter)) {
        if (prevent) return
        if (preventType[key] === value) {
          prevent = true
        }
      }
    }
  }
  return prevent
}
const setServerDisconnected = () => {
  $store.dispatch({
    type: "backend/socket/status",
    payload: { status: 0 },
  })
  $store.dispatch({
    type: "backend/search/status",
    payload: { status: 0 },
  })
}

const setServerConnecting = () => {
  $store.dispatch({
    type: "backend/socket/status",
    payload: { status: 2 },
  })
}

const setServerConnected = () => {
  $store.dispatch({
    type: "backend/socket/status",
    payload: { status: 1, health: 1 },
  })
  $store.dispatch({
    type: "backend/search/status",
    payload: { status: 1 },
  })
}

const dataCreate = (isAnswerToOwnRequest, isSystemAction, items) => {
  items.forEach((item) => {
    if (isAnswerToOwnRequest) {
      $eventbus.emit("ui/addToSnackbar", {
        i18n: "core.dataCreate$displayName$type",
        content: { displayName: item._displayName, type: item._type },
        color: "success",
      })
    } else {
      $store.dispatch({
        type: "notifications/add",
        payload: {
          event: "dataCreate",
          message: {
            i18n: "core.dataCreate$displayName$type",
            content: { displayName: item._displayName, type: item._type },
          },
          item: item._id,
          type: item._type,
          updatedBy: item._source.updatedBy,
        },
      })
    }
  })
}

const dataUpdate = (isAnswerToOwnRequest, isSystemAction, items) => {
  items.forEach((item) => {
    if (isAnswerToOwnRequest) {
      $eventbus.emit("ui/addToSnackbar", {
        i18n: "core.dataUpdate$displayName$type",
        content: { displayName: item._displayName, type: item._type },
        color: "success",
      })
    } else {
      $store.dispatch({
        type: "notifications/add",
        payload: {
          event: "dataUpdate",
          message: {
            i18n: "core.dataUpdate$displayName$type",
            content: { displayName: item._displayName, type: item._type },
          },
          item: item._id,
          type: item._type,
          updatedBy: item._source.updatedBy,
        },
      })
    }
  })
}

const projectUpdate = (isAnswerToOwnRequest, isSystemAction, items) => {
  items.forEach((item) => {
    const displayValues = item._source

    if (isAnswerToOwnRequest) {
      $eventbus.emit("ui/addToSnackbar", {
        i18n: "core.projectUpdate$shorttitle",
        content: { shorttitle: displayValues.shorttitle },
        color: "success",
      })
    } else {
      $store.dispatch({
        type: "notifications/add",
        payload: {
          event: "projectUpdate",
          message: {
            i18n: "core.projectUpdate$shorttitle",
            content: { shorttitle: displayValues.shorttitle },
          },
          item: item._id,
          type: item._type,
          updatedBy: item._source.updatedBy || "system",
        },
      })
    }
  })

  $eventbus.emit("ui/addToSnackbar", {
    i18n: "core.reloadPageHint",
    color: "info",
  })
}

const projectConfigUpdate = (isAnswerToOwnRequest, isSystemAction, items) =>
  $eventbus.emit("ui/addToSnackbar", {
    i18n: "core.reloadPageHint",
    color: "info",
  })

const userConfigUpdate = (isAnswerToOwnRequest, isSystemAction, items) =>
  $eventbus.emit("ui/addToSnackbar", {
    i18n: "core.reloadPageHint",
    color: "info",
  })

const dataDelete = (isAnswerToOwnRequest, isSystemAction, deletedItems) => {
  deletedItems.forEach((item) => {
    if (isAnswerToOwnRequest) {
      $eventbus.emit("ui/addToSnackbar", {
        i18n: "core.dataDelete$displayName$type",
        content: { displayName: item._displayName, type: item._type },
        color: "success",
      })
    } else {
      $store.dispatch({
        type: "notifications/add",
        payload: {
          event: "dataDelete",
          message: {
            i18n: "core.dataDelete$displayName$type",
            content: { displayName: item._displayName, type: item._type },
          },
          item: item._id,
          type: item._type,
          updatedBy: item._source.updatedBy,
        },
      })
    }
  })
}

const dataMove = (isAnswerToOwnRequest, isSystemAction, items) => {
  items.forEach((item) => {
    if (isAnswerToOwnRequest) {
      $eventbus.emit("ui/addToSnackbar", {
        i18n: "core.dataMove$displayName$type",
        content: { displayName: item._displayName, type: item._type },
        color: "success",
      })
    } else {
      $store.dispatch({
        type: "notifications/add",
        payload: {
          event: "dataMove",
          message: {
            i18n: "core.dataMove$displayName$type",
            content: { displayName: item._displayName, type: item._type },
          },
          item: item._id,
          type: item._type,
          updatedBy: item._source.updatedBy,
        },
      })
    }
  })
}

const batchRetrieved = (count, trigger) =>
  $store.dispatch({
    type: "notifications/add",
    payload: {
      event: "dataSync",
      message: {
        i18n: "core.batch$CountSynced",
        content: { count },
      },
      updatedBy: trigger,
    },
  })
const checkToken = (payload) => {
  const { status, response } = payload
  if (shouldBePrevented("checkToken", { status })) {
    return
  }
  const firstName = response?.firstname || "system"

  if (status === 200) {
    const message = {
      i18n: "core.authentication.welcomeBack$name",
      content: {
        name: `${firstName}`,
      },
      color: "green",
    }
    $eventbus.emit("ui/addToSnackbar", message)
    $store.dispatch({
      type: "notifications/add",
      payload: {
        event: "checkToken",
        message,
        updatedBy: "system",
      },
    })
  }
  if (status === 401) {
    const message = {
      i18n: "core.authentication." + response.code,
      color: "error",
    }
    $eventbus.emit("ui/addToSnackbar", message)
    $store.dispatch({
      type: "notifications/add",
      payload: {
        event: "checkToken",
        message,
        updatedBy: "system",
      },
    })
  }
  if (status === 500) {
    let message
    if (response.code) {
      message = {
        i18n: "core.authentication." + response.code,
        color: "error",
      }
    } else {
      message = {
        message: response.message,
        color: "error",
      }
    }
    $eventbus.emit("ui/addToSnackbar", message)
    $store.dispatch({
      type: "notifications/add",
      payload: {
        event: "checkToken",
        message,
        updatedBy: "system",
      },
    })
  }
}
const newVersionAvailable = () =>
  $eventbus.emit("ui/addToSnackbar", {
    i18n: "core.versionUpdate",
    color: "info",
    timeout: -1,
  })

const dataMergeResponse = (isAnswerToOwnRequest, res) => {
  const analysisResult = analyzeOperationResults(res.operations)

  Object.keys(analysisResult).forEach((operation) => {
    const currentOperation = analysisResult[operation]

    if (currentOperation.failure) {
      Object.keys(currentOperation.failure).forEach((type) =>
        $eventbus.emit("ui/addToSnackbar", {
          i18n: "core.dataSync." + operation + ".$docCountOf$docTypeHaveFailed",
          content: {
            docCount: currentOperation.failure[type],
            docType: type,
          },
          color: "error",
        }),
      )
    }
    if (currentOperation.success) {
      Object.keys(currentOperation.success).forEach((type) =>
        $eventbus.emit("ui/addToSnackbar", {
          i18n:
            "core.dataSync." +
            operation +
            ".$docCountOf$docTypeHaveBeenHandled",
          content: {
            docCount: currentOperation.success[type],
            docType: type,
          },
          color: "success",
        }),
      )
    }
  })
  if (res.totals.received === res.totals.succeeded) {
  }
  if (res.totals.received === res.totals.failed) {
  }
  if (
    res.totals.received &&
    res.totals.failed > 0 &&
    res.totals.succeeded > 0
  ) {
    $eventbus.emit("ui/addToSnackbar", {
      i18n: "core.dataSync.$docCountOf$docTypeHaveFailed$docCount1HaveSucceeded",
      content: {
        docCount: res.totals.failed,
        type: res.docType,
        docCount1: res.totals.succeeded,
      },
      color: "error",
    })
  }
}

const add = (message: string | string[], color = "info") => {
  if (Array.isArray(message)) {
    message.forEach((text) =>
      $eventbus.emit("ui/addToSnackbar", {
        message: text,
        color,
      } satisfies SnackbarMessage),
    )
  } else {
    $eventbus.emit("ui/addToSnackbar", {
      message,
      color,
    } satisfies SnackbarMessage)
  }
}

export {
  add,
  dataCreate,
  dataUpdate,
  dataDelete,
  dataMove,
  batchRetrieved,
  dataMergeResponse,
  projectUpdate,
  projectConfigUpdate,
  userConfigUpdate,
  newVersionAvailable,
  setServerDisconnected,
  setServerConnecting,
  setServerConnected,
  checkToken,
}
