import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { departmentService, type AllDepartmentsResponse } from '@/services/department'

interface ProjectDepartments {
  projectId: number
  data: AllDepartmentsResponse
  lastFetched: number
}

export const useDepartmentsStore = defineStore('departments', () => {
  // Cache departments by project ID
  const projectDepartments = ref<Map<number, ProjectDepartments>>(new Map())
  const loading = ref<Set<number>>(new Set())
  const error = ref<string | null>(null)

  // In-flight request de-dup: concurrent callers for the same project share one promise
  const inFlightRequests = new Map<number, Promise<AllDepartmentsResponse>>()

  // Cache duration: 5 minutes
  const CACHE_DURATION = 5 * 60 * 1000

  // Get cached departments for a project
  const getProjectDepartments = computed(() => {
    return (projectId: number): AllDepartmentsResponse | null => {
      const cached = projectDepartments.value.get(projectId)
      if (!cached) return null

      // Check if cache is still valid
      const now = Date.now()
      if (now - cached.lastFetched > CACHE_DURATION) {
        // Cache expired, remove it
        projectDepartments.value.delete(projectId)
        return null
      }

      return cached.data
    }
  })

  // Check if departments are currently being loaded for a project
  const isLoading = computed(() => {
    return (projectId: number): boolean => {
      return loading.value.has(projectId)
    }
  })

  // Get all department options (standard + custom) for a project
  const getAllDepartmentOptions = computed(() => {
    return (projectId: number): string[] => {
      const departments = getProjectDepartments.value(projectId)
      if (!departments) return []
      return departments.departments
    }
  })

  // Fetch departments for a project
  async function fetchProjectDepartments(projectId: number, force = false): Promise<AllDepartmentsResponse> {
    // Return cached data if available and not forced
    if (!force) {
      const cached = getProjectDepartments.value(projectId)
      if (cached) {
        return cached
      }
    }

    // Share the in-flight request with any concurrent callers instead of re-fetching
    const existing = inFlightRequests.get(projectId)
    if (existing) {
      return existing
    }

    loading.value.add(projectId)
    error.value = null

    const request = (async () => {
      try {
        const data = await departmentService.getAllDepartments(projectId)

        // Cache the result
        projectDepartments.value.set(projectId, {
          projectId,
          data,
          lastFetched: Date.now()
        })

        return data
      } catch (err: any) {
        error.value = err.response?.data?.detail || 'Failed to fetch departments'
        console.error('Error fetching departments:', err)
        throw err
      } finally {
        loading.value.delete(projectId)
        inFlightRequests.delete(projectId)
      }
    })()

    inFlightRequests.set(projectId, request)
    return request
  }

  // Invalidate cache for a project (useful after creating/updating/deleting departments)
  function invalidateProject(projectId: number) {
    projectDepartments.value.delete(projectId)
  }

  // Clear all cached data
  function clearCache() {
    projectDepartments.value.clear()
    loading.value.clear()
    error.value = null
  }

  // Update cached departments after a change (to avoid refetch)
  function updateProjectDepartments(projectId: number, data: AllDepartmentsResponse) {
    projectDepartments.value.set(projectId, {
      projectId,
      data,
      lastFetched: Date.now()
    })
  }

  return {
    // State
    error,

    // Computed
    getProjectDepartments,
    isLoading,
    getAllDepartmentOptions,

    // Actions
    fetchProjectDepartments,
    invalidateProject,
    clearCache,
    updateProjectDepartments
  }
})
