<script setup lang="ts">
import { useForm } from '@inertiajs/vue3';
import { Minus, Plus, Save, Search, ShoppingCart, Trash2 } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner';
import PosCatalogCard from '@/components/admin/manage/PosCatalogCard.vue';
import PosCatalogVariantThumb from '@/components/admin/manage/PosCatalogVariantThumb.vue';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import {
    Empty,
    EmptyDescription,
    EmptyHeader,
    EmptyTitle,
} from '@/components/ui/empty';
import {
    Field,
    FieldError,
    FieldGroup,
    FieldLabel,
    FieldSet,
} from '@/components/ui/field';
import { ImageUploadField } from '@/components/ui/image-upload-field';
import { Input } from '@/components/ui/input';
import { RupiahInput } from '@/components/ui/rupiah-input';
import {
    Select,
    SelectContent,
    SelectGroup,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Separator } from '@/components/ui/separator';
import { Textarea } from '@/components/ui/textarea';
import { apiFetch } from '@/lib/api';
import { getFirstCoverImage } from '@/lib/catalog-cover';
import { FIELD_LIMITS } from '@/lib/field-limits';
import { formErrors } from '@/lib/form';
import { formatRupiah, parseRupiah } from '@/lib/rupiah';
import { appendPhotosToFormData } from '@/types/media';
import type { MediaItem } from '@/types/media';
import type { PurchaseCartItem, PurchaseCatalogItem, SelectOption } from '@/types/purchase';
const props = defineProps<{
    suppliers: SelectOption[];
    catalog: PurchaseCatalogItem[];
    initialData?: {
        supplier_id: string;
        discount: string;
        notes: string;
        items: PurchaseCartItem[];
        photos?: MediaItem | null;
    };
    draftItems?: PurchaseCartItem[];
    submitUrl: string;
    method: 'post' | 'put';
    submitLabel: string;
}>();

const isCreateMode = computed(() => props.method === 'post');
const search = ref('');
const cart = ref<PurchaseCartItem[]>([]);
const existingPhotoId = ref<number | null>(null);

const currentPhotoUrl = computed(() => props.initialData?.photos?.url ?? null);

const form = useForm({
    supplier_id: '',
    discount: '',
    notes: '',
    photos: [] as File[],
    remove_media_ids: [] as number[],
});

const photoFile = computed<File | null>({
    get: () => form.photos[0] ?? null,
    set: (file) => {
        form.photos = file ? [file] : [];
    },
});

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

    form.supplier_id = props.initialData.supplier_id;
    form.discount = props.initialData.discount;
    form.notes = props.initialData.notes;
    form.photos = [];
    form.remove_media_ids = [];
    existingPhotoId.value = props.initialData.photos?.id ?? null;
    cart.value = props.initialData.items.map((item) => ({ ...item }));
}

watch(
    () => props.initialData,
    () => {
        populateForm();
    },
    { immediate: true },
);

function populateDraftItems() {
    if (!isCreateMode.value || !props.draftItems?.length) {
        return;
    }

    cart.value = props.draftItems.map((item) => ({ ...item }));
    toast.info('Keranjang dipulihkan dari data tersimpan.');
}

populateDraftItems();

function upsertCartItem(item: PurchaseCartItem) {
    const index = cart.value.findIndex(
        (cartItem) => cartItem.raw_material_price_id === item.raw_material_price_id,
    );

    if (index === -1) {
        cart.value.push({ ...item });

        return;
    }

    cart.value[index] = { ...item };
}

type CatalogPrice = {
    id: number;
    variant: string;
    price_input: string;
    price_formatted: string;
    images?: PurchaseCatalogItem['prices'][number]['images'];
};

const filteredCatalog = computed(() => {
    const keyword = search.value.trim().toLowerCase();

    if (!keyword) {
        return props.catalog;
    }

    return props.catalog.filter((rawMaterial) =>
        rawMaterial.name.toLowerCase().includes(keyword)
        || rawMaterial.prices.some((price) => price.variant.toLowerCase().includes(keyword)),
    );
});

const subtotal = computed(() =>
    cart.value.reduce((sum, item) => sum + lineSubtotal(item), 0),
);

const discountAmount = computed(() => Number(parseRupiah(form.discount)) || 0);

const total = computed(() => Math.max(subtotal.value - discountAmount.value, 0));

function lineSubtotal(item: PurchaseCartItem): number {
    const quantity = Number(item.quantity) || 0;

    return Math.round(quantity * item.unit_price);
}

async function syncDraftItem(priceId: number, quantity: number) {
    const { item } = await apiFetch<{ item: PurchaseCartItem }>('/admin/manage/purchases/draft-items', {
        method: 'POST',
        body: JSON.stringify({
            raw_material_price_id: priceId,
            quantity,
        }),
    });

    upsertCartItem(item);
}

async function addToCart(rawMaterial: PurchaseCatalogItem, price: CatalogPrice) {
    const existing = cart.value.find(
        (item) => item.raw_material_price_id === price.id,
    );
    const nextQty = existing ? (Number(existing.quantity) || 0) + 1 : 1;

    if (isCreateMode.value) {
        try {
            await syncDraftItem(price.id, nextQty);
        } catch (error) {
            toast.error(error instanceof Error ? error.message : 'Gagal menyimpan item ke keranjang.');
        }

        return;
    }

    if (existing) {
        existing.quantity = String(nextQty);

        return;
    }

    cart.value.push({
        raw_material_price_id: price.id,
        raw_material_name: rawMaterial.name,
        variant: price.variant,
        unit_abbreviation: rawMaterial.unit_abbreviation,
        quantity: '1',
        unit_price: Number(price.price_input),
        images: price.images ?? [],
    });
}

async function removeFromCart(index: number) {
    const item = cart.value[index];

    if (isCreateMode.value) {
        try {
            await apiFetch(`/admin/manage/purchases/draft-items/${item.raw_material_price_id}`, {
                method: 'DELETE',
            });
        } catch (error) {
            toast.error(error instanceof Error ? error.message : 'Gagal menghapus item dari keranjang.');

            return;
        }
    }

    cart.value.splice(index, 1);
}

async function adjustQuantity(index: number, delta: number) {
    const item = cart.value[index];
    const nextQty = (Number(item.quantity) || 0) + delta;

    if (nextQty <= 0) {
        await removeFromCart(index);

        return;
    }

    if (isCreateMode.value) {
        try {
            await syncDraftItem(item.raw_material_price_id, nextQty);
        } catch (error) {
            toast.error(error instanceof Error ? error.message : 'Gagal memperbarui jumlah item.');
        }

        return;
    }

    item.quantity = String(nextQty);
}

async function syncCartItemQuantity(index: number) {
    const item = cart.value[index];
    const nextQty = Number(item.quantity) || 0;

    if (nextQty <= 0) {
        await removeFromCart(index);

        return;
    }

    if (!isCreateMode.value) {
        return;
    }

    try {
        await syncDraftItem(item.raw_material_price_id, nextQty);
    } catch (error) {
        toast.error(error instanceof Error ? error.message : 'Gagal memperbarui jumlah item.');
    }
}

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

    if (props.method === 'put') {
        formData.append('_method', 'PUT');
    }

    formData.append('supplier_id', form.supplier_id);
    formData.append('discount', parseRupiah(form.discount));
    formData.append('notes', form.notes);

    if (props.method === 'put') {
        cart.value.forEach((item, index) => {
            formData.append(`items[${index}][raw_material_price_id]`, String(item.raw_material_price_id));
            formData.append(`items[${index}][quantity]`, item.quantity);
        });
    }

    const removeMediaIds = [...form.remove_media_ids];

    if (form.photos.length > 0 && existingPhotoId.value !== null) {
        removeMediaIds.push(existingPhotoId.value);
    }

    appendPhotosToFormData(formData, form.photos, removeMediaIds);

    return formData;
}

function submit() {
    if (cart.value.length === 0) {
        toast.error('Tambahkan minimal satu bahan baku ke keranjang.');

        return;
    }

    if (!form.supplier_id) {
        toast.error('Pilih supplier terlebih dahulu.');

        return;
    }

    const payload = buildFormData();

    form.transform(() => payload).post(props.submitUrl, {
        forceFormData: true,
        onError: () => {
            toast.error('Gagal menyimpan data. Periksa kembali formulir.');
        },
    });
}
</script>

<template>
    <div class="grid gap-4 xl:grid-cols-[1fr_380px]">
        <Card class="min-w-0">
            <CardHeader class="pb-3">
                <CardTitle class="text-base">Pilih Bahan Baku</CardTitle>
            </CardHeader>
            <CardContent class="space-y-4">
                <div class="relative">
                    <Search class="absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" />
                    <Input v-model="search" placeholder="Cari bahan baku..." class="pl-9" />
                </div>

                <div v-if="filteredCatalog.length === 0" class="py-12 text-center text-sm text-muted-foreground">
                    <Empty>
                        <EmptyHeader>
                            <EmptyTitle>Tidak ada bahan baku ditemukan</EmptyTitle>
                            <EmptyDescription>
                                Silakan lakukan pencarian untuk menemukan bahan baku yang Anda cari.
                            </EmptyDescription>
                        </EmptyHeader>
                    </Empty>
                </div>

                <div v-else class="columns-1 gap-4 sm:columns-2 xl:columns-3">
                    <PosCatalogCard v-for="rawMaterial in filteredCatalog" :key="rawMaterial.id"
                        :title="rawMaterial.name" :cover-image="getFirstCoverImage(rawMaterial.prices)">
                        <template #header-extra>
                            <Badge variant="secondary" class="mt-1.5">
                                {{ rawMaterial.unit_label }}
                            </Badge>
                        </template>

                        <p v-if="!rawMaterial.prices.length" class="px-3 py-4 text-sm text-muted-foreground">
                            Belum ada varian
                        </p>
                        <div v-for="price in rawMaterial.prices" :key="price.id"
                            class="flex cursor-pointer items-center gap-2.5 px-3 py-2.5 transition-colors hover:bg-muted/30"
                            @click="addToCart(rawMaterial, price)">
                            <PosCatalogVariantThumb :items="price.images" />
                            <div class="min-w-0 flex-1">
                                <p class="truncate text-sm font-medium">
                                    {{ price.variant }}
                                </p>
                                <p class="text-xs tabular-nums text-muted-foreground">
                                    {{ price.price_formatted }}
                                </p>
                            </div>
                            <Button type="button" variant="outline" size="icon-sm" class="shrink-0"
                                @click.stop="addToCart(rawMaterial, price)">
                                <Plus class="size-3.5" />
                            </Button>
                        </div>
                    </PosCatalogCard>
                </div>
            </CardContent>
        </Card>

        <Card class="h-fit xl:sticky xl:top-4">
            <CardHeader class="pb-3">
                <CardTitle class="flex items-center gap-2 text-base">
                    <ShoppingCart class="size-4" />
                    Ringkasan Belanja
                </CardTitle>
            </CardHeader>
            <CardContent>
                <form @submit.prevent="submit">
                    <FieldGroup>
                        <FieldSet class="grid gap-4">
                            <Field>
                                <FieldLabel for="supplier" required>Supplier</FieldLabel>
                                <Select v-model="form.supplier_id">
                                    <SelectTrigger id="supplier" class="w-full">
                                        <SelectValue placeholder="Pilih supplier" />
                                    </SelectTrigger>
                                    <SelectContent>
                                        <SelectGroup>
                                            <SelectItem v-for="supplier in suppliers" :key="supplier.value"
                                                :value="String(supplier.value)">
                                                {{ supplier.label }}
                                            </SelectItem>
                                        </SelectGroup>
                                    </SelectContent>
                                </Select>
                                <FieldError :errors="formErrors(form, 'supplier_id')" />
                            </Field>

                            <div v-if="cart.length === 0"
                                class="rounded-lg border border-dashed text-center text-sm text-muted-foreground">
                                <Empty>
                                    <EmptyHeader>
                                        <EmptyTitle>Keranjang masih kosong</EmptyTitle>
                                        <EmptyDescription>
                                            Pilih varian bahan baku di sebelah kiri untuk menambahkan ke keranjang.
                                        </EmptyDescription>
                                    </EmptyHeader>
                                </Empty>
                            </div>

                            <div v-else class="scrollbar-thin max-h-80 space-y-3 overflow-y-auto overscroll-y-contain">
                                <div v-for="(item, index) in cart" :key="item.raw_material_price_id"
                                    class="rounded-lg border p-3">
                                    <div class="flex gap-3">
                                        <div class="min-w-0 flex-1 space-y-2">
                                            <div class="flex items-start justify-between gap-2">
                                                <div class="min-w-0">
                                                    <p class="truncate text-sm font-medium">
                                                        {{ item.raw_material_name }}
                                                    </p>
                                                    <p class="truncate text-xs text-muted-foreground">
                                                        {{ item.variant }}
                                                    </p>
                                                </div>
                                                <Button type="button" variant="ghost" size="icon"
                                                    class="text-destructive hover:text-destructive size-7 shrink-0"
                                                    @click="removeFromCart(index)">
                                                    <Trash2 class="size-3.5" />
                                                </Button>
                                            </div>

                                            <Field>
                                                <FieldLabel class="text-xs">Jumlah ({{ item.unit_abbreviation }})
                                                </FieldLabel>
                                                <div class="flex items-center gap-1">
                                                    <Button type="button" variant="outline" size="icon"
                                                        class="size-8 shrink-0" @click="adjustQuantity(index, -1)">
                                                        <Minus class="size-3.5" />
                                                    </Button>
                                                    <Input v-model="item.quantity" type="number" min="0.0001"
                                                        step="0.0001" class="h-8 text-center"
                                                        @change="syncCartItemQuantity(index)" />
                                                    <Button type="button" variant="outline" size="icon"
                                                        class="size-8 shrink-0" @click="adjustQuantity(index, 1)">
                                                        <Plus class="size-3.5" />
                                                    </Button>
                                                </div>
                                            </Field>

                                            <p class="text-xs text-muted-foreground">
                                                Harga satuan Rp {{ formatRupiah(item.unit_price) }}
                                            </p>

                                            <p class="text-right text-sm font-medium">
                                                Rp {{ formatRupiah(lineSubtotal(item)) }}
                                            </p>
                                        </div>
                                    </div>
                                </div>
                            </div>

                            <Separator />

                            <div class="space-y-2 text-sm">
                                <div class="flex justify-between">
                                    <span class="text-muted-foreground">Subtotal</span>
                                    <span class="font-medium">Rp {{ formatRupiah(subtotal) }}</span>
                                </div>
                                <Field>
                                    <FieldLabel for="discount">Diskon</FieldLabel>
                                    <RupiahInput id="discount" v-model="form.discount" placeholder="0" />
                                    <FieldError :errors="formErrors(form, 'discount')" />
                                </Field>
                                <div class="flex justify-between text-base font-semibold">
                                    <span>Total</span>
                                    <span class="text-primary">Rp {{ formatRupiah(total) }}</span>
                                </div>
                            </div>

                            <Field>
                                <FieldLabel for="notes">Keterangan</FieldLabel>
                                <Textarea id="notes" v-model="form.notes" placeholder="Contoh: Belanja batch 2" rows="2"
                                    :maxlength="FIELD_LIMITS.notes" />
                                <FieldError :errors="formErrors(form, 'notes')" />
                            </Field>

                            <ImageUploadField id="purchase-photos" v-model="photoFile" label="Bukti Transaksi"
                                :current-url="currentPhotoUrl" :errors="formErrors(form, 'photos')" />

                            <Button type="submit" class="w-full" :disabled="form.processing || cart.length === 0">
                                <Save class="size-4" />
                                {{ form.processing ? 'Menyimpan...' : submitLabel }}
                            </Button>
                        </FieldSet>
                    </FieldGroup>
                </form>
            </CardContent>
        </Card>
    </div>
</template>
