/**
 * Dictionary group state management.
 */

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { ElMessage } from 'element-plus'
import {
  createGroup,
  deleteGroup,
  getGroupById,
  getGroups,
  updateGroup
} from '@/api/dictionary/group'
import { useUserStore } from '@/store/modules/user'
import { $t } from '@/locales'
import { DictionaryScope } from '@/enums/Dictionary'

const DEFAULT_PAGE = 1
const DEFAULT_PAGE_SIZE = 20

export const useDictionaryGroupStore = defineStore('dictionaryGroupStore', () => {
  const groups = ref<Api.Dictionary.DictionaryGroupDto[]>([])
  const currentGroup = ref<Api.Dictionary.DictionaryGroupDto | null>(null)
  const loading = ref(false)
  const error = ref<string | null>(null)
  const pagination = ref({
    page: DEFAULT_PAGE,
    pageSize: DEFAULT_PAGE_SIZE,
    totalCount: 0,
    totalPages: 0
  })

  const systemGroups = computed(() =>
    groups.value.filter((group) => group.scope === DictionaryScope.System)
  )

  const businessGroups = computed(() =>
    groups.value.filter((group) => group.scope === DictionaryScope.Business)
  )

  const resolveTenantId = () => {
    const userStore = useUserStore()
    return userStore.info?.tenantId || '0'
  }

  const applyPageResult = (result: Api.Common.PageResult<Api.Dictionary.DictionaryGroupDto>) => {
    groups.value = Array.isArray(result.items) ? result.items : []
    pagination.value = {
      page: result.page,
      pageSize: result.pageSize,
      totalCount: result.totalCount,
      totalPages: result.totalPages
    }
  }

  const fetchGroups = async (
    scope?: Api.Dictionary.DictionaryScope,
    page: number = DEFAULT_PAGE,
    pageSize: number = DEFAULT_PAGE_SIZE
  ) => {
    loading.value = true
    error.value = null

    try {
      const result = await getGroups({
        Page: page,
        PageSize: pageSize,
        scope
      })
      applyPageResult(result)
      return result
    } catch (err) {
      error.value = err instanceof Error ? err.message : $t('dictionary.errors.loadGroups')
      ElMessage.error(error.value)
      return null
    } finally {
      loading.value = false
    }
  }

  const fetchGroupById = async (groupId: string) => {
    loading.value = true
    error.value = null

    try {
      const result = await getGroupById(groupId)
      currentGroup.value = result
      return result
    } catch (err) {
      error.value = err instanceof Error ? err.message : $t('dictionary.errors.loadGroup')
      ElMessage.error(error.value)
      return null
    } finally {
      loading.value = false
    }
  }

  const createGroupAction = async (data: Api.Dictionary.CreateDictionaryGroupRequest) => {
    loading.value = true
    error.value = null

    const snapshot = [...groups.value]
    const previousCurrentGroup = currentGroup.value
    const tempId = `temp-${Date.now()}`
    const tempGroup: Api.Dictionary.DictionaryGroupDto = {
      id: tempId,
      tenantId: String(resolveTenantId()),
      code: data.code,
      name: data.name,
      scope: data.scope,
      allowOverride: data.allowOverride,
      isEnabled: true,
      description: data.description ?? null,
      createdAt: new Date().toISOString(),
      updatedAt: null,
      rowVersion: '',
      items: []
    }

    groups.value = [tempGroup, ...groups.value]

    try {
      const result = await createGroup(data)
      const index = groups.value.findIndex((group) => group.id === tempId)
      if (index >= 0) {
        groups.value.splice(index, 1, result)
      } else {
        groups.value = [result, ...groups.value]
      }
      currentGroup.value = result
      pagination.value.totalCount += 1
      pagination.value.totalPages = Math.max(
        1,
        Math.ceil(pagination.value.totalCount / pagination.value.pageSize)
      )
      return result
    } catch (err) {
      groups.value = snapshot
      currentGroup.value = previousCurrentGroup
      error.value = err instanceof Error ? err.message : $t('dictionary.errors.createGroup')
      ElMessage.error(error.value)
      return null
    } finally {
      loading.value = false
    }
  }

  const updateGroupAction = async (
    groupId: string,
    data: Api.Dictionary.UpdateDictionaryGroupRequest
  ) => {
    loading.value = true
    error.value = null

    const snapshot = [...groups.value]
    const index = groups.value.findIndex((group) => group.id === groupId)
    if (index >= 0) {
      groups.value.splice(index, 1, {
        ...groups.value[index],
        ...data,
        updatedAt: new Date().toISOString()
      })
    }

    try {
      const result = await updateGroup(groupId, data)
      if (index >= 0) {
        groups.value.splice(index, 1, result)
      }
      if (currentGroup.value?.id === groupId) {
        currentGroup.value = result
      }
      return result
    } catch (err) {
      groups.value = snapshot
      error.value = err instanceof Error ? err.message : $t('dictionary.errors.updateGroup')
      ElMessage.error(error.value)
      return null
    } finally {
      loading.value = false
    }
  }

  const deleteGroupAction = async (groupId: string) => {
    loading.value = true
    error.value = null

    const snapshot = [...groups.value]
    groups.value = groups.value.filter((group) => group.id !== groupId)
    if (currentGroup.value?.id === groupId) {
      currentGroup.value = null
    }

    try {
      await deleteGroup(groupId)
      pagination.value.totalCount = Math.max(0, pagination.value.totalCount - 1)
      pagination.value.totalPages = Math.max(
        0,
        Math.ceil(pagination.value.totalCount / pagination.value.pageSize)
      )
      return true
    } catch (err) {
      groups.value = snapshot
      error.value = err instanceof Error ? err.message : $t('dictionary.errors.deleteGroup')
      ElMessage.error(error.value)
      return false
    } finally {
      loading.value = false
    }
  }

  return {
    groups,
    currentGroup,
    loading,
    error,
    pagination,
    systemGroups,
    businessGroups,
    fetchGroups,
    fetchGroupById,
    createGroup: createGroupAction,
    updateGroup: updateGroupAction,
    deleteGroup: deleteGroupAction
  }
})
