<script setup lang="ts">
import { useForm } from '@inertiajs/vue3';
import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner';
import { parseRupiah } from '@/lib/rupiah';
import type {
    CuttingMaterialCartItem,
    CuttingProductCatalogItem,
    CuttingRawMaterialCatalogItem,
    CuttingResultCartItem,
} from '@/types/cutting';
import {
    appendRootPhotosToFormData,
    createMediaUploadState,
} from '@/types/media';
import type { MediaItem } from '@/types/media';
import type { MediaUploadState } from '@/types/media';
import type { CategoryOption } from '@/types/product';
import type { EnumOption } from '@/types/raw-material';
import CuttingPosCartDetailDialog from './CuttingPosCartDetailDialog.vue';
import CuttingPosMaterialCatalogPanel from './CuttingPosMaterialCatalogPanel.vue';
import CuttingPosResultCatalogPanel from './CuttingPosResultCatalogPanel.vue';
import CuttingPosSummaryPanel from './CuttingPosSummaryPanel.vue';
import { useCuttingPosCart } from './useCuttingPosCart';

const props = defineProps<{
    rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
    productCatalog: CuttingProductCatalogItem[];
    categories: CategoryOption[];
    units: EnumOption[];
    initialData?: {
        description: string;
        images?: MediaItem[];
        sewing_cost?: string;
        other_cost?: string;
        materials: CuttingMaterialCartItem[];
        results: CuttingResultCartItem[];
    };
    draftMaterials?: CuttingMaterialCartItem[];
    draftResults?: CuttingResultCartItem[];
    submitUrl: string;
    method: 'post' | 'put';
    submitLabel: string;
}>();

const isCreateMode = computed(() => props.method === 'post');
const cartDetailOpen = ref(false);

const imageState = ref<MediaUploadState>(createMediaUploadState());
const isUploading = computed(() => imageState.value.pendingUploads > 0);

// Make catalogs mutable so we can add new items from quick-create dialogs
const rawMaterialCatalogState = ref<CuttingRawMaterialCatalogItem[]>([
    ...props.rawMaterialCatalog,
]);
const productCatalogState = ref<CuttingProductCatalogItem[]>([
    ...props.productCatalog,
]);

watch(
    () => props.rawMaterialCatalog,
    (val) => {
        rawMaterialCatalogState.value = [...val];
    },
);
watch(
    () => props.productCatalog,
    (val) => {
        productCatalogState.value = [...val];
    },
);

const form = useForm({
    description: '',
    sewing_cost: '0',
    other_cost: '0',
});

const {
    materialSearch,
    productSearch,
    materialCart,
    resultCart,
    filteredRawMaterials,
    filteredProducts,
    totalMaterialCost,
    totalResultPieces,
    materialLineCost,
    setCarts,
    loadDraftItems,
    getMaterialCartItem,
    getResultCartItem,
    syncResultTotals,
    addMaterial,
    removeMaterial,
    decreaseMaterialQty,
    addResult,
    removeResult,
    decreaseResultQty,
    syncMaterialField,
    syncResultField,
} = useCuttingPosCart({
    rawMaterialCatalog: rawMaterialCatalogState,
    productCatalog: productCatalogState,
    isCreateMode: () => isCreateMode.value,
});

function populateForm() {
    if (!props.initialData) {
        imageState.value = createMediaUploadState();

        return;
    }

    form.description = props.initialData.description;
    form.sewing_cost = props.initialData.sewing_cost ?? '0';
    form.other_cost = props.initialData.other_cost ?? '0';
    imageState.value = createMediaUploadState(props.initialData.images ?? []);
    setCarts(props.initialData.materials, props.initialData.results);
}

watch(() => props.initialData, populateForm, { immediate: true });
loadDraftItems(props.draftMaterials ?? [], props.draftResults ?? []);

function buildFormData(): FormData {
    const formData = new FormData();

    if (props.method === 'put') {
        formData.append('_method', 'PUT');
    }

    formData.append('description', form.description);
    formData.append(
        'sewing_cost',
        String(Number.parseInt(parseRupiah(form.sewing_cost), 10) || 0),
    );
    formData.append(
        'other_cost',
        String(Number.parseInt(parseRupiah(form.other_cost), 10) || 0),
    );

    appendRootPhotosToFormData(formData, imageState.value);

    if (props.method === 'put') {
        materialCart.value.forEach((item, index) => {
            formData.append(
                `materials[${index}][raw_material_price_id]`,
                String(item.raw_material_price_id),
            );
            formData.append(
                `materials[${index}][material_usage]`,
                item.material_usage,
            );
        });
        resultCart.value.forEach((item, index) => {
            formData.append(
                `results[${index}][product_variant_id]`,
                String(item.product_variant_id),
            );
            formData.append(
                `results[${index}][cutting_result]`,
                String(item.cutting_result),
            );
            formData.append(`results[${index}][sample]`, String(item.sample));
            formData.append(
                `results[${index}][original_outside_sample]`,
                String(item.original_outside_sample),
            );
        });
    }

    return formData;
}

function submit() {
    if (materialCart.value.length === 0) {
        toast.error('Tambahkan minimal satu bahan baku.');

        return;
    }

    if (resultCart.value.length === 0) {
        toast.error('Tambahkan minimal satu hasil produk.');

        return;
    }

    const payload = buildFormData();

    form.transform(() => payload).post(props.submitUrl, {
        forceFormData: true,
        onError: (errors: Record<string, string>) => {
            if (errors.system) {
                toast.error(errors.system);
            } else {
                const firstError = Object.values(errors)[0];

                if (firstError) {
                    toast.error(firstError);
                } else {
                    toast.error('Perbaiki kesalahan pada form.');
                }
            }
        },
    });
}

function onRawMaterialCreated(rawMaterial: CuttingRawMaterialCatalogItem) {
    // Add to catalog
    rawMaterialCatalogState.value.push(rawMaterial);

    // Auto-add the first price variant to cart
    const firstPrice = rawMaterial.prices[0];

    if (firstPrice) {
        addMaterial(rawMaterial, firstPrice);
    }
}

function onProductCreated(product: CuttingProductCatalogItem) {
    // Add to catalog
    productCatalogState.value.push(product);

    // Auto-add the first variant to cart
    const firstVariant = product.variants[0];

    if (firstVariant) {
        addResult(product, firstVariant);
    }
}
</script>

<template>
    <div class="grid gap-4 xl:grid-cols-[1fr_400px]">
        <div class="space-y-4">
            <CuttingPosMaterialCatalogPanel v-model:material-search="materialSearch"
                :filtered-raw-materials="filteredRawMaterials" :get-material-cart-item="getMaterialCartItem"
                :units="units" @add-material="addMaterial" @decrease-material-qty="decreaseMaterialQty"
                @raw-material-created="onRawMaterialCreated" />

            <CuttingPosResultCatalogPanel v-model:product-search="productSearch" :filtered-products="filteredProducts"
                :get-result-cart-item="getResultCartItem" @add-result="addResult" :is-create-mode="isCreateMode"
                :categories="categories" @decrease-result-qty="decreaseResultQty" @product-created="onProductCreated" />
        </div>

        <CuttingPosSummaryPanel v-model:image-state="imageState" :form="form" :material-cart="materialCart"
            :result-cart="resultCart" :total-result-pieces="totalResultPieces" :submit-label="submitLabel"
            @submit="submit" :is-create-mode="isCreateMode" :is-uploading="isUploading"
            @open-detail="cartDetailOpen = true" @remove-material="removeMaterial"
            @sync-material-field="syncMaterialField" @remove-result="removeResult"
            @sync-result-totals="syncResultTotals" @sync-result-field="syncResultField" />
    </div>

    <CuttingPosCartDetailDialog v-model:open="cartDetailOpen" :material-cart="materialCart" :result-cart="resultCart"
        :material-line-cost="materialLineCost" :total-material-cost="totalMaterialCost"
        :is-create-mode="isCreateMode" />
</template>
