import { root } from '@repo/core'
import {
    CategoryController,
    type ListCategoriesWithTagsInput,
    type ListCategoriesWithTagsResult,
} from '@repo/sdk'
import { useState, useEffect } from 'react'
import { create } from 'zustand'

import { type ApiError } from '@/lib/types'

import { OWNER_ID } from '@/lib/auth'
import { handleError } from './use-error'

interface CategoriesWithTagsState {
    data: ListCategoriesWithTagsResult | null | undefined
    loading: boolean
    error: ApiError | null
    hasLoaded: boolean
}

export const useCategoriesWithTagsStore = create<CategoriesWithTagsState>((set) => ({
    data: undefined,
    loading: false,
    error: null,
    hasLoaded: false,
}))

export const useCategoriesWithTags = (params?: ListCategoriesWithTagsInput) => {
    const store = useCategoriesWithTagsStore()
    const [localLoading, setLocalLoading] = useState(false)

    useEffect(() => {
        if (!store.hasLoaded && !store.loading && !localLoading) {
            load()
        }
    }, [])

    const load = async (inputParams?: ListCategoriesWithTagsInput) => {
        if (store.loading || localLoading) return

        try {
            setLocalLoading(true)
            useCategoriesWithTagsStore.setState({ loading: true })
            const category = root.get(CategoryController)

            // Merge params: inputParams > params > defaults
            const mergedParams = {
                page: 1,
                limit: 1000,
                isActive: true,
                orderBy: 'sortOrder' as const,
                order: 'desc' as const,
                ownerId: OWNER_ID,
                ...(params ?? {}),
                ...(inputParams ?? {}),
            }

            const { data, error } = await handleError(async () => await category.listWithTags(mergedParams))

            if (error) {
                useCategoriesWithTagsStore.setState({ data: null, error, loading: false, hasLoaded: true })
                return
            }
            useCategoriesWithTagsStore.setState({ data, loading: false, error: null, hasLoaded: true })
        } catch (e) {
            useCategoriesWithTagsStore.setState({ error: e as ApiError, loading: false, hasLoaded: true })
        } finally {
            setLocalLoading(false)
        }
    }

    return {
        load,
        loading: store.loading || localLoading,
        error: store.error,
        data: store.data,
    }
}
