import { createStore } from 'zustand'
import type { LassoToolsProviderProps, LassoToolsStore } from './types'
import type { LassoToolsState } from '../types'
import { DEFAULT_LASSO_TOOLS_MODES } from '../const'

/**
 * Creates a Zustand store for managing lasso tools state across multiple map instances.
 *
 * @param initProps - Array of initial lasso tool state configurations, one per map instance.
 * @returns A Zustand store with lasso tools state and actions (setEnabled, setValue, setVisibility, setModeSelected, setModeInstance).
 */
export const createLassoToolsStore = (
  initProps: LassoToolsProviderProps['values'],
) => {
  return createStore<LassoToolsStore>()((set) => {
    const defaultProps = initProps.reduce(
      (acc, curr) => {
        const {
          enabled = false,
          mapId,
          modeInstance = new DEFAULT_LASSO_TOOLS_MODES.polygon.mode(),
          modes = DEFAULT_LASSO_TOOLS_MODES,
          modeSelected = DEFAULT_LASSO_TOOLS_MODES.polygon.value,
          values = {},
          selectedId = null,
          editing = false,
          maskLayerIds = null,
          messages = [],
        } = curr
        acc[mapId] = {
          enabled,
          modeInstance,
          modes,
          modeSelected,
          values,
          selectedId,
          editing,
          maskLayerIds,
          messages,
        }
        return acc
      },
      {} as LassoToolsStore['data'],
    )

    return {
      data: defaultProps,
      setEnabled: (mapId, enabled) => {
        set((state) => ({
          data: {
            ...state.data,
            [mapId]: {
              ...state.data[mapId]!,
              enabled,
              visible: enabled,
              // Disabling the tool (action toggle / Esc / Enter commit) clears
              // the contextual toolbar selection and any in-progress edit flag.
              ...(enabled ? {} : { selectedId: null, editing: false }),
            },
          },
        }))
      },
      setValue: (mapId, id, value) => {
        set((state) => {
          const values = { ...state.data[mapId]!.values }

          const _value =
            values[id] ??
            ({
              type: 'mask',
            } as LassoToolsState['values'][number])

          values[id] = {
            ..._value,
            ...value,
            id,
          }

          if (!value) {
            delete values[id]
          }

          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                values,
              },
            },
          }
        })
      },
      setVisibility: (mapId, valueId, visible) => {
        set((state) => {
          const values = { ...state.data[mapId]!.values }
          const _value =
            values[valueId] ?? ({} as LassoToolsState['values'][number])

          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                values: {
                  ...values,
                  [valueId]: {
                    ..._value,
                    properties: {
                      ..._value.properties,
                      visible,
                    },
                  },
                },
              },
            },
          }
        })
      },
      setModeSelected: (mapId, mode) => {
        set((state) => {
          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                modeSelected: mode,
              },
            },
          }
        })
      },
      setModeInstance: (mapId, modeInstance) => {
        set((state) => {
          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                modeInstance,
              },
            },
          }
        })
      },
      setSelectedId: (mapId, selectedId) => {
        set((state) => {
          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                selectedId,
              },
            },
          }
        })
      },
      setEditing: (mapId, editing) => {
        set((state) => {
          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                editing,
              },
            },
          }
        })
      },
      setMaskLayerIds: (mapId, maskLayerIds) => {
        set((state) => {
          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                maskLayerIds,
              },
            },
          }
        })
      },
      setMessages: (mapId, messages) => {
        set((state) => {
          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                messages,
              },
            },
          }
        })
      },
      addMessage: (mapId, message) => {
        set((state) => {
          // At most one message per entity: same id replaces the previous one.
          const messages = state.data[mapId]!.messages.filter(
            (m) => m.id !== message.id,
          )
          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                messages: [...messages, message],
              },
            },
          }
        })
      },
      removeMessage: (mapId, id) => {
        set((state) => {
          return {
            data: {
              ...state.data,
              [mapId]: {
                ...state.data[mapId]!,
                messages: state.data[mapId]!.messages.filter(
                  (m) => m.id !== id,
                ),
              },
            },
          }
        })
      },
    }
  })
}
