import type { CompositionSlot } from "@racletteOrchestrator/router/routeParserHelper"
import { computed } from "vue"
import { useRoute, useRouter } from "vue-router"
import {
  DEFAULT_SLOT_NAME,
  parseRouteToCompositionSlots,
  transformToOriginalState,
} from "@racletteOrchestrator/router/routeParserHelper"
import { compose, urlCompose } from "@racletteOrchestrator/router/routeParser"
import {
  clone,
  mergeDeepRight,
  pick,
  evolve,
  when,
  is,
  pickBy,
  complement,
  isNil,
} from "ramda"
import type { InteractionLink } from "@shared/types"
import {
  getCompositionById,
  getLocalizedName,
  getCompositionIdByPath,
} from "@racletteCore/store/reducers/compositions/selectors"
import useInteractionLinks from "./useInteractionLinks"

export const useRouteState = () => {
  const route = useRoute()
  const router = useRouter()
  const { state: interactionLinks } = useInteractionLinks()

  const composed = computed(() => compose(route.fullPath))

  const compositionSlots = computed<CompositionSlot[]>(() =>
    parseRouteToCompositionSlots(route.fullPath, undefined, true),
  )

  const getInteractionLinkUrl = (slot: CompositionSlot) => {
    const newSlots = clone(compositionSlots.value)
    const found = newSlots.find((item) => item.slotName === slot.slotName)

    if (found) {
      Object.assign(found, slot)
    } else {
      newSlots.push(slot)
    }

    const newState = transformToOriginalState(newSlots)
    const newUrl = urlCompose(newState)

    return newUrl
  }

  const getCompositionLinkForSlotName = (slotName) =>
    computed(() =>
      compositionSlots.value.find((slot) => slot.slotName === slotName),
    )

  const updateSlot = (slot: CompositionSlot) => {
    const cleanedSlot = evolve(
      {
        slotParams: when(is(Object), pickBy(complement(isNil))),
      },
      slot,
    )

    const newUrl = getInteractionLinkUrl(cleanedSlot)
    router.push({ path: "/" + newUrl })
  }

  const removeSlot = (slotName: string) => {
    const filteredCompositions = compositionSlots.value.filter(
      (value) => value.slotName !== slotName,
    )

    const urlState = transformToOriginalState(filteredCompositions)
    const newUrl = urlCompose(urlState)

    // router.push({ name: "app.space.page", params: { pageId: newUrl } })
    router.push({ path: "/" + newUrl })
  }

  // TODO: think about to move that method into new composable useInteractionLink
  const triggerInteractionLink = (
    interactionLink: InteractionLink,
    requestedParams: Record<string, string> = {},
  ): CompositionSlot | undefined => {
    const targetSlotName = interactionLink.slotType ?? DEFAULT_SLOT_NAME
    const targetComposition = getCompositionById(interactionLink.composition)

    if (!targetComposition) {
      console.error(
        `No composition with id ${interactionLink.composition} found.`,
      )
      return undefined
    }

    const currentSlotParams =
      compositionSlots.value.find((slot) => slot.slotName === targetSlotName)
        ?.slotParams ?? {}
    // Merge current and requested parameters, then filter to only allowed ones
    const allowedParams = interactionLink.queryParameters ?? []
    const mergedParams = mergeDeepRight(currentSlotParams, requestedParams)
    const finalParams = pick(allowedParams, mergedParams)

    const compositionSlot: CompositionSlot = {
      slotName: targetSlotName,
      slotValue: getLocalizedName(targetComposition.pathname),
      slotParams: finalParams,
    }

    updateSlot(compositionSlot)
  }

  const triggerInteractionLinkById = (
    id: string,
    requestedParams: Record<string, string> = {},
  ) => {
    const found = interactionLinks.value.find(
      (interactionLink) => interactionLink._id === id,
    )

    if (found) {
      triggerInteractionLink(found, requestedParams)
    } else {
      console.error(`InteractionLink ${id} not found!`)
    }
  }
  const getCurrentCompositionId = (compositionPath: string): string => {
    return getCompositionIdByPath(compositionPath)
  }
  return {
    composed,
    compositionSlots,
    getCompositionLinkForSlotName,
    getInteractionLinkUrl,
    updateSlot,
    removeSlot,
    triggerInteractionLink,
    triggerInteractionLinkById,
    getCurrentCompositionId,
  }
}

export default useRouteState
