<script setup lang="ts">
import { ref, watch } 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 {
    Dialog,
    DialogContent,
    DialogFooter,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Field, FieldDescription, FieldLabel } from '@/components/ui/field';
import { Input } from '@/components/ui/input';
import { FIELD_LIMITS } from '@/lib/field-limits';
import { parseRupiah } from '@/lib/rupiah';
import { store_new_variant as storeNewVariantRoute } from '@/routes/admin/manage/purchases/draft_items';
import { createMediaUploadState } from '@/types/media';
import type { MediaUploadState } from '@/types/media';
import type { PurchaseCatalogItem } from '@/types/purchase';
import type { RawMaterialPrice } from '@/types/raw-material';

const props = defineProps<{
    rawMaterial: PurchaseCatalogItem | null;
}>();

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

const emit = defineEmits<{
    'variant-added': [rawMaterialId: number, price: RawMaterialPrice];
}>();

const variant = ref('');
const price = ref('');
const stock = ref('0');
const media = ref<MediaUploadState>(createMediaUploadState());
const loading = ref(false);

watch(open, (isOpen) => {
    if (isOpen) {
        variant.value = '';
        price.value = '';
        stock.value = '0';
        media.value = createMediaUploadState();
    }
});

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

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

function getXsrfToken(): string {
    const match = document.cookie
        .split('; ')
        .find((row) => row.startsWith('XSRF-TOKEN='));

    return match ? decodeURIComponent(match.split('=')[1] ?? '') : '';
}

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

    loading.value = true;

    try {
        const formData = new FormData();

        formData.append('raw_material_id', String(props.rawMaterial.id));
        formData.append('variant', variant.value.trim());
        formData.append('price', String(Number.parseInt(parseRupiah(price.value), 10) || 0));
        formData.append('stock', String(parseStockValue(stock.value)));

        media.value.newFiles.forEach((file) => {
            formData.append('photos[]', file);
        });

        const response = await fetch(storeNewVariantRoute.url(), {
            method: 'POST',
            body: formData,
            headers: {
                Accept: 'application/json',
                'X-XSRF-TOKEN': getXsrfToken(),
                'X-Requested-With': 'XMLHttpRequest',
            },
            credentials: 'same-origin',
        });

        if (!response.ok) {
            const contentType = response.headers.get('content-type') ?? '';
            const isJson = contentType.includes('application/json');

            if (isJson) {
                const error = (await response.json().catch(() => ({}))) as {
                    message?: string;
                    errors?: Record<string, string[]>;
                };

                const firstValidationError = error.errors
                    ? Object.values(error.errors).flat()[0]
                    : undefined;

                throw new Error(firstValidationError ?? error.message ?? 'Permintaan gagal diproses.');
            }

            throw new Error(`Permintaan gagal diproses (HTTP ${response.status}).`);
        }

        const data = (await response.json()) as { price: RawMaterialPrice };

        emit('variant-added', props.rawMaterial.id, data.price);
        open.value = false;
        toast.success('Varian baru berhasil ditambahkan.');
    } catch (error) {
        toast.error(error instanceof Error ? error.message : 'Gagal menambahkan varian baru.');
    } finally {
        loading.value = false;
    }
}
</script>

<template>
    <Dialog v-model:open="open">
        <DialogContent class="sm:max-w-lg">
            <DialogHeader>
                <DialogTitle>Tambah Varian Baru</DialogTitle>
            </DialogHeader>

            <p v-if="rawMaterial" class="text-sm text-muted-foreground">
                Bahan baku: <span class="font-medium text-foreground">{{ rawMaterial.name }}</span>
            </p>

            <form class="space-y-4" @submit.prevent="submit">
                <Field>
                    <FieldLabel for="new_variant_name" required>Nama Varian</FieldLabel>
                    <Input id="new_variant_name" v-model="variant" type="text" placeholder="Contoh: Premium / 40s"
                        :maxlength="FIELD_LIMITS.variantName" />
                </Field>

                <div class="grid gap-4 sm:grid-cols-2">
                    <Field>
                        <FieldLabel for="new_variant_stock" required>Stok</FieldLabel>
                        <DecimalInput id="new_variant_stock" v-model="stock" />
                        <FieldDescription>Stok awal varian ini.</FieldDescription>
                    </Field>

                    <Field>
                        <FieldLabel for="new_variant_price" required>Harga</FieldLabel>
                        <RupiahInput id="new_variant_price" v-model="price" />
                        <FieldDescription>Harga per satuan bahan baku.</FieldDescription>
                    </Field>
                </div>

                <MediaDropzone id="new_variant_images" v-model="media" label="Foto Varian" :max-files="5"
                    :required="false" />

                <DialogFooter>
                    <Button type="button" variant="outline" @click="open = false">
                        Batal
                    </Button>
                    <Button type="submit" :disabled="loading || !variant || !price">
                        {{ loading ? 'Menyimpan...' : 'Tambah Varian' }}
                    </Button>
                </DialogFooter>
            </form>
        </DialogContent>
    </Dialog>
</template>
