<script setup lang="ts">
import { Plus, Save } from '@lucide/vue';
import { computed, ref } from 'vue';
import { toast } from 'vue-sonner';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { useCan } from '@/composables/useCan';
import { useVariantList } from '@/composables/useVariantList';
import { apiFetch } from '@/lib/api';
import ProductInfoSection from '@/pages/admin/master/products/form/ProductInfoSection.vue';
import ProductVariantSection from '@/pages/admin/master/products/form/ProductVariantSection.vue';
import type { CuttingProductCatalogItem } from '@/types/cutting';
import { appendMediaToFormData, createMediaUploadState } from '@/types/media';
import type { CategoryOption, ProductVariantFormItem } from '@/types/product';

const { hasRole } = useCan();
const showPrices = !hasRole('admin-bahan-baku');

const props = defineProps<{
    categories: CategoryOption[];
}>();

const open = defineModel<boolean>('open', { required: true });

const emit = defineEmits<{
    'created': [product: CuttingProductCatalogItem];
}>();

const loading = ref(false);

const isUploading = computed(() => 
    variants.value.some((v) => v.media.pendingUploads > 0)
);

function createClientId(): string {
    return `variant-${crypto.randomUUID()}`;
}

const form = ref({
    name: '',
    description: '',
    category_ids: [] as number[],
    errors: {} as Record<string, string>,
});

const {
    items: variants,
    addItem: addVariant,
    removeItem: removeVariant,
    setField: setVariantField,
    appendToFormData,
    itemErrors: variantErrors,
} = useVariantList<ProductVariantFormItem>(
    'variants',
    () => ({
        client_id: createClientId(),
        name: '',
        stock: '0',
        retail_stock: '0',
        prices: {
            distributor: '0',
            agent: '0',
            sub_agent: '0',
            grosir: '0',
            retail: '0',
            tiktok: '0',
            shopee: '0',
            harga_modal: '0',
        },
        media: createMediaUploadState(),
    }),
    () => [{
        client_id: createClientId(),
        name: '',
        stock: '0',
        retail_stock: '0',
        prices: {
            distributor: '0',
            agent: '0',
            sub_agent: '0',
            grosir: '0',
            retail: '0',
            tiktok: '0',
            shopee: '0',
            harga_modal: '0',
        },
        media: createMediaUploadState(),
    }],
);

const copiedPrices = ref<Record<string, string> | null>(null);

function copyPrices(variantPrices: Record<string, string>) {
    copiedPrices.value = { ...variantPrices };
}

function pastePrices(clientId: string) {
    if (!copiedPrices.value) {
        return;
    }

    setVariantField(clientId, 'prices', { ...copiedPrices.value });
}

function applyToAllPrices(variantPrices: Record<string, string>) {
    variants.value.forEach((v) => {
        setVariantField(v.client_id, 'prices', { ...variantPrices });
    });
}

function toggleCategory(categoryId: number, checked: boolean) {
    if (checked) {
        if (!form.value.category_ids.includes(categoryId)) {
            form.value.category_ids = [...form.value.category_ids, categoryId];
        }
    } else {
        form.value.category_ids = form.value.category_ids.filter((id) => id !== categoryId);
    }
}

const categoryError = computed(() => form.value.errors.category_ids ?? '');

function resetForm() {
    form.value = { name: '', description: '', category_ids: [], errors: {} };
    variants.value = [{
        client_id: createClientId(),
        name: '',
        stock: '0',
        retail_stock: '0',
        prices: {
            distributor: '0',
            agent: '0',
            sub_agent: '0',
            grosir: '0',
            retail: '0',
            tiktok: '0',
            shopee: '0',
            harga_modal: '0',
        },
        media: createMediaUploadState(),
    }];
}

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

    formData.append('name', form.value.name.trim());
    formData.append('description', form.value.description.trim());

    form.value.category_ids.forEach((categoryId) => {
        formData.append('category_ids[]', String(categoryId));
    });

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

        if (variant.prices && showPrices) {
            Object.entries(variant.prices as Record<string, string>).forEach(([type, value]) => {
                formData.append(`variants[${index}][prices][${type}]`, String(Number.parseInt(value, 10) || 0));
            });
        }

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

    return formData;
}

async function submit() {
    loading.value = true;
    form.value.errors = {};

    try {
        const payload = buildFormData();
        const { product } = await apiFetch<{ product: CuttingProductCatalogItem }>(
            '/admin/manage/cuttings/quick-create-product',
            {
                method: 'POST',
                body: payload,
            },
        );

        toast.success(`Produk "${product.name}" berhasil ditambahkan.`);
        emit('created', product);
        open.value = false;
        resetForm();
    } catch (error) {
        if (error instanceof Error) {
            toast.error(error.message);
        }
    } finally {
        loading.value = false;
    }
}
</script>

<template>
    <Dialog v-model:open="open">
        <DialogContent class="flex max-h-[90vh] flex-col sm:max-w-5xl">
            <DialogHeader>
                <DialogTitle>Tambah Produk Baru</DialogTitle>
            </DialogHeader>

            <div class="scrollbar-thin flex-1 overflow-y-auto pr-1">
                <form id="quick-create-product-form" @submit.prevent="submit" class="space-y-6">
                    <ProductInfoSection :form="form" :categories="categories" :category-error="categoryError"
                        @update:name="form.name = $event" @update:description="form.description = $event"
                        @toggle-category="toggleCategory" />

                    <ProductVariantSection v-for="(variant, index) in variants" :key="variant.client_id" :form="form"
                        :variant="variant" :index="index" :can-remove="variants.length > 1"
                        :has-copied-prices="!!copiedPrices"
                        :variant-errors="(clientId, field) => variantErrors(form, clientId, field)"
                        @remove="removeVariant(variant.client_id)"
                        @update:name="setVariantField(variant.client_id, 'name', $event)"
                        @update:stock="setVariantField(variant.client_id, 'stock', $event)"
                        @update:retail-stock="setVariantField(variant.client_id, 'retail_stock', $event)"
                        @update:prices="setVariantField(variant.client_id, 'prices', $event)"
                        @update:media="setVariantField(variant.client_id, 'media', $event)"
                        @copy-prices="copyPrices(variant.prices as Record<string, string>)"
                        @paste-prices="pastePrices(variant.client_id)"
                        @apply-to-all-prices="applyToAllPrices(variant.prices as Record<string, string>)" />
                </form>
            </div>

            <div class="flex items-center justify-between gap-2 border-t pt-4">
                <Button type="button" variant="outline" @click="addVariant">
                    <Plus class="size-4" />
                    Tambah Varian
                </Button>

                <div class="flex gap-2">
                    <Button type="button" variant="outline" :disabled="loading" @click="open = false">
                        Batal
                    </Button>
                    <Button type="submit" form="quick-create-product-form" :disabled="loading || isUploading">
                        <Save class="size-4" />
                        {{ isUploading ? 'Mengunggah...' : loading ? 'Menyimpan...' : 'Simpan' }}
                    </Button>
                </div>
            </div>
        </DialogContent>
    </Dialog>
</template>
