import { ref } from 'vue';
import type { Ref } from 'vue';
import { formErrors } from '@/lib/form';
import type { FormWithErrors } from '@/lib/form';

export interface VariantItem {
    client_id: string;
    id?: number;
    media: unknown;
    [key: string]: unknown;
}

export function useVariantList<T extends VariantItem>(
    prefix: string,
    createEmpty: () => T,
    buildInitial: () => T[],
) {
    const items: Ref<T[]> = ref(buildInitial()) as Ref<T[]>;

    function addItem() {
        items.value = [...items.value, createEmpty()];
    }

    function removeItem(clientId: string) {
        if (items.value.length <= 1) {
            return;
        }

        items.value = items.value.filter((item) => item.client_id !== clientId);
    }

    function setField(clientId: string, key: string, value: unknown) {
        items.value = items.value.map((item) =>
            item.client_id === clientId ? { ...item, [key]: value } : item,
        );
    }

    function indexOf(clientId: string): number {
        return items.value.findIndex((item) => item.client_id === clientId);
    }

    function appendToFormData(
        formData: FormData,
        appendItem: (formData: FormData, index: number, item: T) => void,
        method?: 'post' | 'put',
    ) {
        if (method === 'put') {
            formData.append('_method', 'PUT');
        }

        items.value.forEach((item, index) => {
            if (item.id) {
                formData.append(`${prefix}[${index}][id]`, String(item.id));
            }

            appendItem(formData, index, item);
        });
    }

    function itemErrors(
        form: FormWithErrors,
        clientId: string,
        field: string,
    ): string[] {
        const index = indexOf(clientId);

        if (index === -1) {
            return [];
        }

        return formErrors(form, `${prefix}.${index}.${field}`);
    }

    function allItemErrors(
        form: FormWithErrors,
        field: string,
    ): string[] {
        return items.value.flatMap((item) => itemErrors(form, item.client_id, field));
    }

    return {
        items,
        addItem,
        removeItem,
        setField,
        indexOf,
        appendToFormData,
        itemErrors,
        allItemErrors,
    };
}
