import { ref, watch } from 'vue'
import { defineStore } from 'pinia'
import { api } from 'boot/axios'

import { useChatsStore } from 'stores/chats'
import { useUsersStore } from 'stores/users'
import { useCompaniesStore } from 'stores/companies'

import type { Project, ProjectParams } from 'types/Project'

export const useProjectsStore = defineStore('projects', () => {
  const projects = ref<Project[]>([])
  const currentProjectId = ref<number | null>(null)
  const lastProjectId = ref<number | null>(null)
  const isInit = ref<boolean>(false)
  const chatsStore = useChatsStore()
  const usersStore = useUsersStore()
  const companiesStore = useCompaniesStore()
  const isLoading = ref(false)
  
  async function init() {
  // guard for double request
    if (isLoading.value) return
    isLoading.value = true
    
    try {
      const { data } = await api.get('/project')
      const projectsAPI = data.data
      projects.value = projectsAPI
      isInit.value = true
    } catch (error) {
      console.error('Failed to init projects:', error)
    } finally {
      isLoading.value = false
    }
  }

  function reset () {
    projects.value = []
    isInit.value = false
    currentProjectId.value = null
  }
  
  async function add (projectData: ProjectParams) {
    const { data } = await api.post('/project', projectData)
    const newProjectAPI = data.data
    projects.value.push(newProjectAPI)
    return newProjectAPI
  }

  async function update (id: number, projectData: ProjectParams) {
    const { data } = await api.put('/project/'+ id, projectData)
    const projectAPI =data.data
    const idx = projects.value.findIndex(item => item.id === id)
    if (projects.value[idx]) Object.assign(projects.value[idx], projectAPI)
  }

  async function archive (id: number) {
    const { data } = await api.put('/project/'+ id + '/archive')
    const projectAPI = data.data
    const idx = projects.value.findIndex(item => item.id === projectAPI.id)
    if (projects.value[idx] && projectAPI.is_archived) Object.assign(projects.value[idx], projectAPI)
  }

  async function restore (id: number) {
    const { data } = await api.put('/project/'+ id + '/restore')
    const projectAPI = data.data
    const idx = projects.value.findIndex(item => item.id === projectAPI.id)
    if (projects.value[idx] && !projectAPI.is_archived) Object.assign(projects.value[idx], projectAPI)
  }

  function projectById (id: number) {
    return projects.value.find(el =>el.id === id)
  }

  function setCurrentProjectId (id: number | null | undefined) {
    currentProjectId.value = (typeof id ==='number') ? id : null
  }

  function setLastProjectId (id: number | null | undefined) {
    lastProjectId.value = (typeof id ==='number') ? id : null
  }

  async function initStores () {
    resetStores()
    await Promise.all([
      chatsStore.init(),
      usersStore.init(),
      companiesStore.init()
    ])
  }

   function resetStores () {
    chatsStore.reset()
    usersStore.reset()
    companiesStore.reset()
  }

  watch (currentProjectId, async (newId) => {
    if (newId) {
      await initStores()
    } else {
      resetStores()
    }
  }, { flush: 'sync' })

  return {
    init,
    reset,
    isInit,
    projects,
    currentProjectId,
    lastProjectId,
    add,
    update,
    archive,
    restore,
    projectById,
    setCurrentProjectId,
    setLastProjectId,
    initStores,
    resetStores
  }
})
