<script setup lang="ts">
import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue';
import { computed } from 'vue';
import { toast } from 'vue-sonner';
import { DecimalInput } from '@/components/form/decimal-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import MediaDropzone from '@/components/media/MediaDropzone.vue';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Field, FieldError, FieldLabel, FieldGroup, FieldSet } from '@/components/ui/field';
import { useFormDialog } from '@/composables/useFormDialog';
import { useCan } from '@/composables/useCan';
import { formErrors } from '@/lib/form';
import { parseRupiah } from '@/lib/rupiah';
import { update } from '@/routes/admin/master/raw_materials';
import { createMediaUploadState, appendMediaToFormData } from '@/types/media';
import type { RawMaterialListItem, RawMaterialPrice } from '@/types/raw-material';

const open = defineModel<boolean>('open', { default: false });

const props = defineProps<{
    price: RawMaterialPrice | null;
    material: RawMaterialListItem | null;
}>();

const editForm = useForm({
    name: '',
    unit: '',
    prices: [] as any[],
});

function resetForm() {
    editForm.reset();
    editForm.clearErrors();
}

function populateForm(price: RawMaterialPrice | null) {
    resetForm();

    if (!price || !props.material) {
        return;
    }

    editForm.name = props.material.name;
    editForm.unit = props.material.unit;
    editForm.prices = (props.material.prices ?? []).map((p) => ({
        client_id: `price-${crypto.randomUUID()}`,
        id: p.id,
        variant: p.variant,
        price: p.price_input,
        stock: p.stock_input,
        media: createMediaUploadState(p.images ?? []),
    }));
}

useFormDialog({
    open,
    source: () => props.price,
    populate: populateForm,
    reset: resetForm,
});

const editingPriceIndex = computed(() => {
    if (!props.price || !editForm.prices.length) {
        return -1;
    }

    return editForm.prices.findIndex((p) => p.id === props.price!.id);
});

const editingPriceFormItem = computed(() => {
    const idx = editingPriceIndex.value;

    if (idx === -1) {
        return null;
    }

    return editForm.prices[idx];
});

function parseStockValue(value: string): number {
    const parsed = Number.parseFloat(value.replace(',', '.'));

    return Number.isNaN(parsed) ? 0 : parsed;
}

const isUploading = computed(() => {
    return editForm.prices.some((p) => p.media?.pendingUploads > 0);
});

function submit() {
    if (!props.material) {
        return;
    }

    const formData = new FormData();
    formData.append('_method', 'PUT');
    formData.append('name', editForm.name.trim());
    formData.append('unit', editForm.unit);

    editForm.prices.forEach((price, index) => {
        formData.append(`prices[${index}][id]`, String(price.id));
        formData.append(`prices[${index}][variant]`, price.variant.trim());
        formData.append(`prices[${index}][price]`, String(Number.parseInt(parseRupiah(price.price), 10) || 0));
        formData.append(`prices[${index}][stock]`, String(parseStockValue(price.stock)));
        appendMediaToFormData(formData, `prices[${index}]`, price.media);
    });

    editForm.transform(() => formData).post(update.url(props.material.id), {
        forceFormData: true,
        onSuccess: () => {
            open.value = false;
        },
        onError: (errors) => {
            if (errors.system) {
                toast.error(errors.system);
            }
        },
    });
}
</script>

<template>
    <Dialog v-model:open="open">
        <DialogContent class="sm:max-w-md">
            <DialogHeader>
                <DialogTitle>Ubah Varian Bahan Baku</DialogTitle>
                <DialogDescription>
                    Mengubah properti varian untuk bahan baku <strong>{{ material?.name }}</strong>.
                </DialogDescription>
            </DialogHeader>

            <form v-if="editingPriceFormItem" @submit.prevent="submit">
                <FieldGroup>
                    <FieldSet class="grid gap-4">
                        <Field>
                            <FieldLabel for="variant-name" required>Nama Varian</FieldLabel>
                            <Input id="variant-name" v-model="editingPriceFormItem.variant" type="text"
                                placeholder="Masukkan nama varian" />
                            <FieldError :errors="formErrors(editForm, `prices.${editingPriceIndex}.variant`)" />
                        </Field>

                        <div class="grid grid-cols-2 gap-4">
                            <Field>
                                <FieldLabel for="variant-stock" required>Stok</FieldLabel>
                                <DecimalInput id="variant-stock" v-model="editingPriceFormItem.stock" />
                                <FieldError :errors="formErrors(editForm, `prices.${editingPriceIndex}.stock`)" />
                            </Field>

                            <Field>
                                <FieldLabel for="variant-price" required>Harga</FieldLabel>
                                <RupiahInput id="variant-price" v-model="editingPriceFormItem.price" />
                                <FieldError :errors="formErrors(editForm, `prices.${editingPriceIndex}.price`)" />
                            </Field>
                        </div>

                        <MediaDropzone :id="`price_images_${editingPriceFormItem.client_id}`"
                            v-model="editingPriceFormItem.media" label="Foto Varian" :max-files="5" required
                            :errors="formErrors(editForm, `prices.${editingPriceIndex}.s3_keys`)" />
                    </FieldSet>
                </FieldGroup>

                <DialogFooter class="mt-6">
                    <Button type="button" variant="outline" :disabled="editForm.processing" @click="open = false">
                        Batal
                    </Button>
                    <Button type="submit" :disabled="editForm.processing || isUploading">
                        <Save class="size-4" />
                        {{ isUploading ? 'Mengunggah...' : editForm.processing ? 'Menyimpan...' : 'Simpan' }}
                    </Button>
                </DialogFooter>
            </form>
        </DialogContent>
    </Dialog>
</template>
