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

const props = defineProps<{
    rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
    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 photoState = ref<MediaUploadState>(createMediaUploadState());

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

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

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

const {
    materialSearch,
    selectedRawMaterialId,
    materialCart,
    resultCart,
    filteredRawMaterials,
    totalMaterialCost,
    totalResultPieces,
    materialLineCost,
    setCarts,
    loadDraftItems,
    getMaterialCartItem,
    addMaterial,
    removeMaterial,
    decreaseMaterialQty,
    syncMaterialField,
    removeCombination,
    syncCombinationResult,
} = useCuttingPosCart({
    rawMaterialCatalog: rawMaterialCatalogState,
    isCreateMode: () => isCreateMode.value,
});

// Confirmation Dialog states
const showDeleteConfirm = ref(false);
const deleteType = ref<'material' | 'combination' | null>(null);
const deleteIndex = ref<number | null>(null);
const deleteCombinationId = ref<number | null>(null);

const deleteConfirmTitle = computed(() => {
    if (deleteType.value === 'combination') {
        return 'Hapus Kombinasi?';
    }
    return 'Hapus Bahan Baku?';
});

const deleteConfirmDescription = computed(() => {
    if (deleteType.value === 'combination') {
        return 'Apakah Anda yakin ingin menghapus kombinasi bahan baku ini dari keranjang? Tindakan ini tidak dapat dibatalkan.';
    }
    return 'Apakah Anda yakin ingin menghapus bahan baku ini dari keranjang? Tindakan ini tidak dapat dibatalkan.';
});

function confirmRemoveMaterial(index: number) {
    deleteType.value = 'material';
    deleteIndex.value = index;
    showDeleteConfirm.value = true;
}

function confirmRemoveCombination(combinationId: number) {
    deleteType.value = 'combination';
    deleteCombinationId.value = combinationId;
    showDeleteConfirm.value = true;
}

async function handleConfirmDelete() {
    if (deleteType.value === 'material' && deleteIndex.value !== null) {
        await removeMaterial(deleteIndex.value);
    } else if (deleteType.value === 'combination' && deleteCombinationId.value !== null) {
        await removeCombination(deleteCombinationId.value);
    }

    showDeleteConfirm.value = false;
    deleteType.value = null;
    deleteIndex.value = null;
    deleteCombinationId.value = null;
}

function populateForm() {
    if (!props.initialData) {
        return;
    }

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

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

if (isCreateMode.value && resultCart.value.length === 0) {
    resultCart.value.push({
        product_name: '',
        cutting_result: '',
        sample: '',
        original_outside_sample: '',
    });
}

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, photoState.value);

    if (props.method === 'put') {
        const combinationResults: Record<number, number | null> = {};
        materialCart.value.forEach(item => {
            if (item.combination_id && item.combination_material_result !== undefined) {
                combinationResults[item.combination_id] = item.combination_material_result;
            }
        });

        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,
            );

            if (item.material_result !== undefined && item.material_result !== null) {
                formData.append(
                    `materials[${index}][material_result]`,
                    item.material_result,
                );
            }

            if (item.combination_id) {
                formData.append(
                    `materials[${index}][combination_id]`,
                    String(item.combination_id),
                );

                const combinationResult = combinationResults[item.combination_id];

                if (combinationResult !== undefined && combinationResult !== null) {
                    formData.append(
                        `materials[${index}][combination_material_result]`,
                        String(combinationResult),
                    );
                }
            }
        });
    }

    resultCart.value.forEach((item, index) => {
        formData.append(
            `results[${index}][product_name]`,
            item.product_name ?? '',
        );
        formData.append(
            `results[${index}][cutting_result]`,
            item.cutting_result === '' ? '' : String(item.cutting_result ?? 0),
        );
        formData.append(
            `results[${index}][sample]`,
            item.sample === '' ? '' : String(item.sample ?? 0),
        );
        formData.append(
            `results[${index}][original_outside_sample]`,
            item.original_outside_sample === '' ? '' : String(item.original_outside_sample ?? 0),
        );
    });

    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 onCombinationCreated(items: CuttingMaterialCartItem[]) {
    for (const item of items) {
        materialCart.value.push({ ...item });
    }
}
</script>

<template>
    <div class="grid min-w-0 gap-4 xl:grid-cols-[1fr_400px]">
        <div class="min-w-0 space-y-4 order-last xl:order-first">
            <CuttingPosMaterialCatalogPanel v-model:material-search="materialSearch"
                v-model:selected-raw-material-id="selectedRawMaterialId"
                :filtered-raw-materials="filteredRawMaterials" :raw-material-catalog="rawMaterialCatalogState"
                :material-cart="materialCart" :get-material-cart-item="getMaterialCartItem" :units="units"
                @add-material="addMaterial" @decrease-material-qty="decreaseMaterialQty"
                @combination-created="onCombinationCreated" />
        </div>

        <CuttingPosSummaryPanel class="order-first xl:order-last" :form="form" :material-cart="materialCart"
            :result-cart="resultCart" :total-result-pieces="totalResultPieces" :submit-label="submitLabel"
            @submit="submit" :is-create-mode="isCreateMode" v-model:photo-state="photoState"
            @open-detail="cartDetailOpen = true" @remove-material="confirmRemoveMaterial"
            @sync-material-field="syncMaterialField"
            @remove-combination="confirmRemoveCombination" @sync-combination-result="syncCombinationResult" />
    </div>

    <CuttingPosCartDetailDialog v-model:open="cartDetailOpen" :form="form" :material-cart="materialCart" :result-cart="resultCart"
        :material-line-cost="materialLineCost" :total-material-cost="totalMaterialCost" :total-result-pieces="totalResultPieces"
        :is-create-mode="isCreateMode"
        @remove-material="confirmRemoveMaterial"
        @sync-material-field="syncMaterialField"
        @remove-combination="confirmRemoveCombination"
        @sync-combination-result="syncCombinationResult" />

    <!-- Floating Cart button on mobile -->
    <button
        v-if="materialCart.length + resultCart.length > 0"
        type="button"
        class="fixed top-50 right-6 z-50 flex size-14 items-center justify-center rounded-full bg-primary text-primary-foreground shadow-lg transition-transform hover:scale-105 active:scale-95 xl:hidden"
        @click="cartDetailOpen = true"
    >
        <ShoppingCart class="size-6" />
        <span class="absolute -right-1 -top-1 flex size-6 items-center justify-center rounded-full bg-destructive text-[11px] font-bold text-destructive-foreground">
            {{ (materialCart.length + resultCart.length) > 99 ? '99+' : (materialCart.length + resultCart.length) }}
        </span>
    </button>

    <!-- Confirm deletion dialog -->
    <ConfirmDialog
        v-model:open="showDeleteConfirm"
        :title="deleteConfirmTitle"
        :description="deleteConfirmDescription"
        confirm-label="Hapus"
        cancel-label="Batal"
        destructive
        @confirm="handleConfirmDelete"
    />
</template>
