import { defineStore } from 'pinia'
import { type CreateCommentDto, type CommentDto, ResponseError } from '~/.api-client'
import { useCommentApi } from '~/composables/comment/useCommentApi'

export const useCommentStore = defineStore('Comment', () => {
  type FormElementId = string
  const commentApi = useCommentApi()
  const comments = ref<Record<FormElementId, CommentDto[]>>({})
  const loadedForms = ref(new Set<string>())

  async function load(applicationFormId: string) {
    if (loadedForms.value.has(applicationFormId)) return
    const { data, error } = await useAsyncData(`comments:${applicationFormId}`, () =>
      commentApi.getCommentsByApplicationFormId(applicationFormId)
    )
    if (error.value) {
      console.error('Failed loading comments:', error.value)
      return
    }
    comments.value =
      data.value?.content.reduce((acc: Record<FormElementId, CommentDto[]>, comment: CommentDto) => {
        const formElementId = comment.formElementId
        if (!acc[formElementId]) {
          acc[formElementId] = []
        }
        acc[formElementId].push(comment)
        return acc
      }, {}) || {}
    loadedForms.value.add(applicationFormId)
  }

  async function createComment(
    applicationFormId: string,
    formElementId: string,
    createCommentDto: CreateCommentDto
  ): Promise<CommentDto> {
    try {
      const newComment = await commentApi.createComment(applicationFormId, formElementId, createCommentDto)
      if (!comments.value[formElementId]) {
        comments.value[formElementId] = []
      }
      comments.value[formElementId].push(newComment)
      return newComment
    } catch (e: unknown) {
      if (e instanceof ResponseError) {
        console.error('Failed creating comment:', e.response)
      } else {
        console.error('Failed creating comment:', e)
      }
      return Promise.reject(e)
    }
  }

  async function updateComment(id?: string, commentDto?: CommentDto): Promise<CommentDto> {
    if (!id || !commentDto) {
      return Promise.reject(new Error('ID or comment DTO missing'))
    }

    try {
      const updatedComment = await commentApi.updateComment(id, commentDto)
      const formElementId = updatedComment.formElementId
      const index = comments.value?.[formElementId]?.findIndex((comment) => comment.id === id) ?? -1
      if (index !== -1 && comments.value?.[formElementId][index]) {
        comments.value[formElementId][index] = updatedComment
      }
      return updatedComment
    } catch (e: unknown) {
      if (e instanceof ResponseError) {
        console.error(`Failed updating comment with ID ${id}:`, e.response)
      } else {
        console.error(`Failed updating comment with ID ${id}:`, e)
      }
      return Promise.reject(e)
    }
  }

  async function deleteCommentById(id: string): Promise<void> {
    try {
      await commentApi.deleteCommentById(id)
      for (const formElementId in comments.value) {
        const index = comments.value[formElementId].findIndex((comment) => comment.id === id)
        if (index !== -1) {
          comments.value[formElementId].splice(index, 1)
          break
        }
      }
    } catch (e: unknown) {
      if (e instanceof ResponseError) {
        console.error(`Failed deleting comment with ID ${id}:`, e.response)
      } else {
        console.error(`Failed deleting comment with ID ${id}:`, e)
      }
      return Promise.reject(e)
    }
  }

  return { load, createComment, updateComment, deleteCommentById, comments }
})
