<script setup lang="ts">
import { useForm } from '@inertiajs/vue3';
import { Save } from '@lucide/vue';
import { computed } from 'vue';
import { toast } from 'vue-sonner';
import { NumberInput } from '@/components/form/number-input';
import { RupiahInput } from '@/components/form/rupiah-input';
import MediaDropzone from '@/components/media/MediaDropzone.vue';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogDescription,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Field, FieldError, FieldLabel, FieldGroup, FieldSet } from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { useFormDialog } from '@/composables/useFormDialog';
import { formErrors } from '@/lib/form';
import { update } from '@/routes/admin/master/products';
import { createMediaUploadState, appendMediaToFormData } from '@/types/media';
import type { ProductListItem, Variant } from '@/types/product';
import { PRICE_TYPES, PRICE_TYPE_LABELS } from '@/types/product';

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

const props = defineProps<{
    variant: Variant | null;
    product: ProductListItem | null;
}>();

const editForm = useForm({
    name: '',
    description: '',
    category_ids: [] as number[],
    status: 'active',
    variants: [] as any[],
});

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

function populateForm(variant: Variant | null) {
    resetForm();

    if (!variant || !props.product) {
        return;
    }

    editForm.name = props.product.name;
    editForm.description = props.product.description ?? '';
    editForm.category_ids = (props.product.categories ?? []).map((c) => c.id);
    editForm.status = props.product.status ?? 'active';

    editForm.variants = (props.product.variants ?? []).map((v) => {
        const prices: Record<string, string> = {
            distributor: '0',
            agent: '0',
            sub_agent: '0',
            grosir: '0',
            retail: '0',
            tiktok: '0',
            shopee: '0',
            harga_modal: '0',
        };
        v.prices?.forEach((price) => {
            if (price.type) {
                prices[price.type] = String(price.price);
            }
        });

        return {
            client_id: `variant-${crypto.randomUUID()}`,
            id: v.id,
            name: v.name,
            stock: String(v.stock),
            reject_stock: String(v.reject_stock),
            retail_stock: String(v.retail_stock),
            prices,
            media: createMediaUploadState(v.images ?? []),
        };
    });
}

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

const editingVariantIndex = computed(() => {
    if (!props.variant || !editForm.variants.length) {
        return -1;
    }

    return editForm.variants.findIndex((v) => v.id === props.variant!.id);
});

const editingVariantFormItem = computed(() => {
    const idx = editingVariantIndex.value;

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

    return editForm.variants[idx];
});

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

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

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

    editForm.category_ids.forEach((id) => {
        formData.append('category_ids[]', String(id));
    });

    editForm.variants.forEach((v, index) => {
        if (v.id) {
            formData.append(`variants[${index}][id]`, String(v.id));
        }

        formData.append(`variants[${index}][name]`, v.name.trim());
        formData.append(`variants[${index}][stock]`, String(Number.parseInt(v.stock, 10) || 0));
        formData.append(`variants[${index}][reject_stock]`, String(Number.parseInt(v.reject_stock, 10) || 0));
        formData.append(`variants[${index}][retail_stock]`, String(Number.parseInt(v.retail_stock, 10) || 0));

        if (v.prices) {
            Object.entries(v.prices).forEach(([type, value]) => {
                formData.append(`variants[${index}][prices][${type}]`, String(Number.parseInt(String(value), 10) || 0));
            });
        }

        appendMediaToFormData(formData, `variants[${index}]`, v.media);
    });

    editForm.transform(() => formData).post(update.url(props.product.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-lg max-h-[85vh] overflow-y-auto">
            <DialogHeader>
                <DialogTitle>Ubah Varian Produk</DialogTitle>
                <DialogDescription>
                    Mengubah properti varian untuk produk <strong>{{ product?.name }}</strong>.
                </DialogDescription>
            </DialogHeader>

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

                        <div class="grid grid-cols-3 gap-4">
                            <Field>
                                <FieldLabel for="variant-stock" required>Stok Bagus</FieldLabel>
                                <NumberInput id="variant-stock" v-model="editingVariantFormItem.stock" />
                                <FieldError :errors="formErrors(editForm, `variants.${editingVariantIndex}.stock`)" />
                            </Field>

                            <Field>
                                <FieldLabel for="variant-reject-stock" required>Stok Reject</FieldLabel>
                                <NumberInput id="variant-reject-stock" v-model="editingVariantFormItem.reject_stock" />
                                <FieldError :errors="formErrors(editForm, `variants.${editingVariantIndex}.reject_stock`)" />
                            </Field>

                            <Field>
                                <FieldLabel for="variant-retail-stock" required>Stok Ecer</FieldLabel>
                                <NumberInput id="variant-retail-stock" v-model="editingVariantFormItem.retail_stock" />
                                <FieldError
                                    :errors="formErrors(editForm, `variants.${editingVariantIndex}.retail_stock`)" />
                            </Field>
                        </div>

                        <div class="border-t pt-4 mt-2">
                            <h4 class="text-sm font-semibold mb-3">Harga Varian</h4>
                            <div class="grid gap-3 grid-cols-2 md:grid-cols-3">
                                <Field v-for="type in PRICE_TYPES" :key="type">
                                    <FieldLabel class="text-xs" :for="`variant-price-${type}`" required>
                                        {{ PRICE_TYPE_LABELS[type] }}
                                    </FieldLabel>
                                    <RupiahInput :id="`variant-price-${type}`"
                                        v-model="editingVariantFormItem.prices[type]" />
                                    <FieldError
                                        :errors="formErrors(editForm, `variants.${editingVariantIndex}.prices.${type}`)" />
                                </Field>
                            </div>
                        </div>

                        <MediaDropzone :id="`variant_images_${editingVariantFormItem.client_id}`"
                            v-model="editingVariantFormItem.media" label="Foto Varian" :max-files="5" required
                            :errors="formErrors(editForm, `variants.${editingVariantIndex}.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>
