import { computed, ref, type MaybeRefOrGetter, toValue } from 'vue';
import { toast } from 'vue-sonner';
import { apiFetch } from '@/lib/api';
import { store as syncDraftRoute, destroy as destroyDraftRoute } from '@/routes/admin/manage/purchases/draft_items';
import type { PurchaseCartItem, PurchaseCatalogItem } from '@/types/purchase';

export type PurchaseCatalogPrice = {
    id: number;
    variant: string;
    price_input: string;
    price_formatted: string;
    images?: PurchaseCatalogItem['prices'][number]['images'];
};

export function usePurchasePosCart(options: {
    catalog: MaybeRefOrGetter<PurchaseCatalogItem[]>;
    isCreateMode: MaybeRefOrGetter<boolean>;
}) {
    const search = ref('');
    const cart = ref<PurchaseCartItem[]>([]);

    function setCart(items: PurchaseCartItem[]) {
        cart.value = items.map((item) => ({ ...item }));
    }

    function loadDraftItems(items: PurchaseCartItem[]) {
        if (!toValue(options.isCreateMode) || items.length === 0) {
            return;
        }

        cart.value = items.map((item) => ({ ...item }));
    }

    function upsertCartItem(item: PurchaseCartItem) {
        const index = cart.value.findIndex(
            (cartItem) => cartItem.raw_material_price_id === item.raw_material_price_id,
        );

        if (index === -1) {
            cart.value.push({ ...item });

            return;
        }

        cart.value[index] = { ...item };
    }

    const filteredCatalog = computed(() => {
        const keyword = search.value.trim().toLowerCase();
        const catalog = toValue(options.catalog);

        if (!keyword) {
            return catalog;
        }

        return catalog.filter((rawMaterial) =>
            rawMaterial.name.toLowerCase().includes(keyword)
            || rawMaterial.prices.some((price) => price.variant.toLowerCase().includes(keyword)),
        );
    });

    const subtotal = computed(() =>
        cart.value.reduce((sum, item) => sum + lineSubtotal(item), 0),
    );

    function getCartItem(priceId: number): PurchaseCartItem | undefined {
        return cart.value.find((item) => item.raw_material_price_id === priceId);
    }

    function lineSubtotal(item: PurchaseCartItem): number {
        const quantity = Number(item.quantity) || 0;

        return Math.round(quantity * item.unit_price);
    }

    async function syncDraftItem(priceId: number, quantity: number) {
        const { item } = await apiFetch<{ item: PurchaseCartItem }>(syncDraftRoute.url(), {
            method: 'POST',
            body: JSON.stringify({
                raw_material_price_id: priceId,
                quantity,
            }),
        });

        upsertCartItem(item);
    }

    async function addToCart(rawMaterial: PurchaseCatalogItem, price: PurchaseCatalogPrice) {
        const existing = cart.value.find(
            (item) => item.raw_material_price_id === price.id,
        );
        const nextQty = existing ? (Number(existing.quantity) || 0) + 1 : 1;

        if (toValue(options.isCreateMode)) {
            try {
                await syncDraftItem(price.id, nextQty);
            } catch (error) {
                toast.error(error instanceof Error ? error.message : 'Gagal menyimpan item ke keranjang.');
            }

            return;
        }

        if (existing) {
            existing.quantity = String(nextQty);

            return;
        }

        cart.value.push({
            raw_material_price_id: price.id,
            raw_material_name: rawMaterial.name,
            variant: price.variant,
            unit_abbreviation: rawMaterial.unit_abbreviation,
            quantity: '1',
            unit_price: Number(price.price_input),
            images: price.images ?? [],
        });
    }

    async function removeFromCart(index: number) {
        const item = cart.value[index];

        if (toValue(options.isCreateMode)) {
            try {
                await apiFetch(destroyDraftRoute.url(item.raw_material_price_id), {
                    method: 'DELETE',
                });
            } catch (error) {
                toast.error(error instanceof Error ? error.message : 'Gagal menghapus item dari keranjang.');

                return;
            }
        }

        cart.value.splice(index, 1);
    }

    async function adjustQuantity(index: number, delta: number) {
        const item = cart.value[index];
        const nextQty = (Number(item.quantity) || 0) + delta;

        if (nextQty <= 0) {
            await removeFromCart(index);

            return;
        }

        if (toValue(options.isCreateMode)) {
            try {
                await syncDraftItem(item.raw_material_price_id, nextQty);
            } catch (error) {
                toast.error(error instanceof Error ? error.message : 'Gagal memperbarui jumlah item.');
            }

            return;
        }

        item.quantity = String(nextQty);
    }

    async function syncCartItemQuantity(index: number) {
        const item = cart.value[index];
        const nextQty = Number(item.quantity) || 0;

        if (nextQty <= 0) {
            await removeFromCart(index);

            return;
        }

        if (!toValue(options.isCreateMode)) {
            return;
        }

        try {
            await syncDraftItem(item.raw_material_price_id, nextQty);
        } catch (error) {
            toast.error(error instanceof Error ? error.message : 'Gagal memperbarui jumlah item.');
        }
    }

    async function decreasePriceQty(priceId: number) {
        const index = cart.value.findIndex((item) => item.raw_material_price_id === priceId);

        if (index !== -1) {
            await adjustQuantity(index, -1);
        }
    }

    return {
        search,
        cart,
        filteredCatalog,
        subtotal,
        setCart,
        loadDraftItems,
        getCartItem,
        lineSubtotal,
        addToCart,
        removeFromCart,
        adjustQuantity,
        syncCartItemQuantity,
        decreasePriceQty,
        upsertCartItem,
    };
}
