<script setup lang="ts">
import { Layers, Plus, Search, X } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner';
import PosCatalogVariantThumb from '@/components/catalog/PosCatalogVariantThumb.vue';
import { DecimalInput } from '@/components/form/decimal-input';
import { NumberInput } from '@/components/form/number-input';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    Dialog,
    DialogContent,
    DialogHeader,
    DialogTitle,
} from '@/components/ui/dialog';
import { Input } from '@/components/ui/input';
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from '@/components/ui/select';
import { Label } from '@/components/ui/label';
import { apiFetch } from '@/lib/api';
import draft_combinations from '@/routes/admin/manage/cuttings/draft_combinations';
import type { CuttingMaterialCartItem, CuttingRawMaterialCatalogItem } from '@/types/cutting';

export type CuttingCatalogPrice = CuttingRawMaterialCatalogItem['prices'][number];

type SelectedMaterial = {
    raw_material_price_id: number;
    raw_material_name: string;
    variant: string;
    unit: string;
    unit_abbreviation: string;
    stock_input: string;
    stock_formatted?: string;
    material_usage: string;
    images?: CuttingCatalogPrice['images'];
    is_initial?: boolean;
};

const props = defineProps<{
    rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
    existingCartItems: CuttingMaterialCartItem[];
    initialVariant?: {
        rawMaterial: CuttingRawMaterialCatalogItem;
        price: CuttingCatalogPrice;
    } | null;
}>();

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

const emit = defineEmits<{
    'combination-created': [items: CuttingMaterialCartItem[]];
}>();

const search = ref('');
const selectedRawMaterialId = ref('all');
const selectedMaterials = ref<SelectedMaterial[]>([]);
const combinationResult = ref<string>('');
const loading = ref(false);
const selectPortalTarget = ref<HTMLElement>();

const filteredRawMaterials = computed(() => {
    const keyword = search.value.trim().toLowerCase();
    const rawMaterialId = selectedRawMaterialId.value;
    const catalog = props.rawMaterialCatalog;

    let items = catalog;
    if (rawMaterialId !== 'all') {
        const idNum = Number(rawMaterialId);
        items = catalog.filter((rawMaterial) => rawMaterial.id === idNum);
    }

    if (!keyword) {
        return items;
    }

    return items
        .map((rawMaterial) => {
            const matchingPrices = rawMaterial.prices.filter((price) =>
                price.variant.toLowerCase().includes(keyword),
            );

            return {
                ...rawMaterial,
                prices: matchingPrices,
            };
        })
        .filter((rawMaterial) => rawMaterial.prices.length > 0);
});

function isSelected(priceId: number): boolean {
    return selectedMaterials.value.some((item) => item.raw_material_price_id === priceId);
}

function toggleVariant(rawMaterial: CuttingRawMaterialCatalogItem, price: CuttingCatalogPrice) {
    const index = selectedMaterials.value.findIndex(
        (item) => item.raw_material_price_id === price.id,
    );

    if (index !== -1) {
        selectedMaterials.value.splice(index, 1);
    } else {
        selectedMaterials.value.push({
            raw_material_price_id: price.id,
            raw_material_name: rawMaterial.name,
            variant: price.variant,
            unit: rawMaterial.unit,
            unit_abbreviation: rawMaterial.unit_abbreviation,
            stock_input: price.stock_input,
            stock_formatted: price.stock_formatted,
            material_usage: '1',
            images: price.images,
        });
    }
}

function removeSelected(priceId: number) {
    selectedMaterials.value = selectedMaterials.value.filter(
        (item) => item.raw_material_price_id !== priceId,
    );
}

function resetForm() {
    search.value = '';
    selectedRawMaterialId.value = 'all';
    selectedMaterials.value = [];
    combinationResult.value = '';
}

function initFromVariant() {
    if (props.initialVariant) {
        const { rawMaterial, price } = props.initialVariant;
        const existingCartItem = props.existingCartItems.find(
            (item) => item.raw_material_price_id === price.id,
        );

        selectedMaterials.value = [{
            raw_material_price_id: price.id,
            raw_material_name: rawMaterial.name,
            variant: price.variant,
            unit: rawMaterial.unit,
            unit_abbreviation: rawMaterial.unit_abbreviation,
            stock_input: price.stock_input,
            stock_formatted: price.stock_formatted,
            material_usage: existingCartItem?.material_usage ?? '1',
            images: price.images,
            is_initial: true,
        }];
    }
}

async function submit() {
    if (selectedMaterials.value.length < 2) {
        toast.error('Pilih minimal 2 bahan baku untuk dikombinasikan.');

        return;
    }

    for (const item of selectedMaterials.value) {
        if (!item.material_usage || item.material_usage.trim() === '') {
            toast.error(`Pemakaian untuk ${item.raw_material_name} - ${item.variant} wajib diisi.`);

            return;
        }
    }

    loading.value = true;

    try {
        const data = await apiFetch<{ items: CuttingMaterialCartItem[] }>(draft_combinations.store.url(), {
            method: 'POST',
            body: JSON.stringify({
                materials: selectedMaterials.value.map((item) => ({
                    raw_material_price_id: item.raw_material_price_id,
                    material_usage: item.material_usage,
                })),
                material_result: combinationResult.value ? Number(combinationResult.value) : null,
            }),
        });

        toast.success('Kombinasi bahan baku berhasil ditambahkan.');
        emit('combination-created', data.items);
        open.value = false;
        resetForm();
    } catch (error) {
        if (error instanceof Error) {
            toast.error(error.message);
        }
    } finally {
        loading.value = false;
    }
}

watch(open, (value) => {
    if (value) {
        initFromVariant();
    } else {
        resetForm();
    }
});
</script>

<template>
    <Dialog v-model:open="open">
        <DialogContent class="flex max-h-[90vh] flex-col sm:max-w-4xl">
            <DialogHeader>
                <DialogTitle>Kombinasi Bahan Baku</DialogTitle>
            </DialogHeader>

            <div class="scrollbar-thin flex-1 overflow-y-auto pr-1">
                <div class="space-y-4">
                    <div v-if="selectedMaterials.length > 0" class="rounded-lg border p-3 space-y-2">
                        <p class="text-sm font-medium">Bahan Baku Terpilih ({{ selectedMaterials.length }})</p>
                        <div class="space-y-2">
                            <div v-for="item in selectedMaterials" :key="item.raw_material_price_id"
                                class="flex flex-col gap-2 rounded-md border p-2 sm:flex-row sm:items-center"
                                :class="item.is_initial ? 'border-primary bg-primary/5' : ''">
                                <div class="flex items-center gap-2 flex-1 min-w-0">
                                    <PosCatalogVariantThumb :items="item.images" :title="`${item.raw_material_name} - ${item.variant}`" />
                                    <div class="min-w-0 flex-1">
                                        <p class="text-sm font-medium">
                                            {{ item.raw_material_name }} - {{ item.variant }}
                                        </p>
                                        <Badge variant="outline" class="text-xs mt-0.5 select-none font-normal">
                                            Stok: {{ item.stock_formatted }}
                                        </Badge>
                                    </div>
                                    <Button type="button" variant="ghost" size="icon-sm"
                                        class="text-destructive shrink-0 sm:hidden" @click="removeSelected(item.raw_material_price_id)">
                                        <X class="size-3.5" />
                                    </Button>
                                </div>
                                <div class="flex items-center gap-2 sm:gap-1">
                                    <Label class="text-xs whitespace-nowrap">Pemakaian:</Label>
                                    <DecimalInput v-model="item.material_usage" class="h-7 w-20" />
                                    <span class="text-xs text-muted-foreground">{{ item.unit_abbreviation }}</span>
                                    <Button type="button" variant="ghost" size="icon-sm"
                                        class="text-destructive shrink-0 hidden sm:inline-flex" @click="removeSelected(item.raw_material_price_id)">
                                        <X class="size-3.5" />
                                    </Button>
                                </div>
                            </div>
                        </div>
                    </div>

                    <div class="flex flex-col gap-2 sm:flex-row sm:items-center">
                        <div class="relative flex-1">
                            <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 lain untuk dikombinasikan..."
                                class="pl-9" />
                        </div>
                        <div class="w-full sm:w-60">
                            <Select v-model:model-value="selectedRawMaterialId">
                                <SelectTrigger class="w-full">
                                    <SelectValue placeholder="Semua Bahan Baku" />
                                </SelectTrigger>
                                <SelectContent :to="selectPortalTarget">
                                    <SelectItem value="all">Semua Bahan Baku</SelectItem>
                                    <SelectItem v-for="item in rawMaterialCatalog" :key="item.id" :value="String(item.id)">
                                        {{ item.name }}
                                    </SelectItem>
                                </SelectContent>
                            </Select>
                        </div>
                    </div>

                    <div v-if="filteredRawMaterials.length === 0"
                        class="py-8 text-center text-sm text-muted-foreground">
                        Tidak ada bahan baku ditemukan.
                    </div>

                    <div v-else class="space-y-3">
                        <div v-for="rawMaterial in filteredRawMaterials" :key="rawMaterial.id"
                            class="rounded-lg border p-3">
                            <div class="mb-2 flex items-center gap-2">
                                <p class="text-sm font-medium">{{ rawMaterial.name }}</p>
                                <Badge variant="outline" class="text-xs">
                                    {{ rawMaterial.unit_label }}
                                </Badge>
                            </div>

                            <div class="space-y-1">
                                <div v-for="price in rawMaterial.prices" :key="price.id"
                                    class="flex items-center gap-2.5 rounded-md px-2 py-1.5 transition-all duration-200"
                                    :class="[
                                        isSelected(price.id) ? 'border-2 border-primary bg-primary/5' : 'cursor-pointer hover:bg-muted/30',
                                    ]" @click="!isSelected(price.id) && toggleVariant(rawMaterial, price)">
                                    <PosCatalogVariantThumb :items="price.images" :title="`${rawMaterial.name} - ${price.variant}`" />
                                    <div class="min-w-0 flex-1">
                                        <p class="text-sm">{{ price.variant }}</p>
                                        <p class="text-xs tabular-nums text-muted-foreground">
                                            Stok: {{ price.stock_formatted }}
                                        </p>
                                    </div>
                                    <Button v-if="!isSelected(price.id)" type="button" variant="outline" size="icon-sm"
                                        class="shrink-0" @click.stop="toggleVariant(rawMaterial, price)">
                                        <Plus class="size-3.5" />
                                    </Button>
                                    <Badge v-else variant="secondary" class="text-xs">
                                        Terpilih
                                    </Badge>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="flex flex-col gap-3 border-t pt-4 sm:flex-row sm:items-center sm:justify-between">
                <div class="flex flex-wrap items-center gap-3">
                    <div class="flex items-center gap-2">
                        <Label class="text-sm whitespace-nowrap">Hasil:</Label>
                        <NumberInput v-model="combinationResult" class="h-8 w-20" placeholder="0" />
                        <span class="text-xs text-muted-foreground">pcs</span>
                    </div>
                    <p class="text-sm text-muted-foreground">
                        {{ selectedMaterials.length }} bahan dipilih
                    </p>
                </div>
                <div class="flex gap-2">
                    <Button type="button" variant="outline" class="flex-1 sm:flex-none" :disabled="loading" @click="open = false">
                        Batal
                    </Button>
                    <Button type="button" class="flex-1 sm:flex-none" :disabled="loading || selectedMaterials.length < 2" @click="submit">
                        <Layers class="size-4 mr-1" />
                        {{ loading ? 'Menyimpan...' : 'Simpan Kombinasi' }}
                    </Button>
                </div>
            </div>
            <div ref="selectPortalTarget" class="contents"></div>
        </DialogContent>
    </Dialog>
</template>
