<script setup lang="ts">
import { useForm, usePage } from '@inertiajs/vue3';
import { ShoppingCart } from '@lucide/vue';
import { computed, ref, watch } from 'vue';
import { toast } from 'vue-sonner';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import {
    FieldGroup,
    FieldSet,
} from '@/components/ui/field';
import { useCan } from '@/composables/useCan';
import { OrderChannel } from '@/constants/order-channel';
import { OrderPaymentType } from '@/constants/order-payment-type';
import { OrderStatus } from '@/constants/order-status';
import { PaperSize } from '@/constants/paper-size';
import { parseRupiah } from '@/lib/rupiah';
import type { Auth } from '@/types/auth';
import { appendRootPhotosToFormData, createMediaUploadState } from '@/types/media';
import type { MediaItem, MediaUploadState } from '@/types/media';
import type { EnumOption, OrderCartItem, OrderCatalogItem, SelectOption } from '@/types/order';
import CustomerQuickCreateModal from './CustomerQuickCreateModal.vue';
import OrderPosCartDetailDialog from './OrderPosCartDetailDialog.vue';
import OrderPosCartSummaryItems from './OrderPosCartSummaryItems.vue';
import OrderPosCatalogPanel from './OrderPosCatalogPanel.vue';
import OrderPosCheckoutSection from './OrderPosCheckoutSection.vue';
import OrderPosMetadataFields from './OrderPosMetadataFields.vue';
import { useOrderPosCart } from './useOrderPosCart';

const props = defineProps<{
    customers: SelectOption[];
    marketings: SelectOption[];
    catalog: OrderCatalogItem[];
    channels: EnumOption[];
    storePriceTypes: EnumOption[];
    paymentTypes: EnumOption[];
    initialData?: {
        customer_id: string;
        marketing_id: string;
        channel: string;
        price_type: string;
        payment_type: string;
        is_affiliate: boolean;
        tiktok_order_id: string;
        shopee_order_id: string;
        discount: string;
        nego_price: string;
        notes: string;
        photos?: MediaItem | null;
        status: string;
        items: OrderCartItem[];
    };
    draftItems?: OrderCartItem[];
    submitUrl: string;
    method: 'post' | 'put';
    submitLabel: string;
}>();

const emit = defineEmits<{
    'customer-created': [customer: { id: number; name: string }];
}>();

const isCreateMode = computed(() => props.method === 'post');
const { can } = useCan();
const page = usePage();
const authUser = computed(() => (page.props.auth as Auth).user);
const isMarketingUser = computed(() =>
    (authUser.value?.roles?.includes('marketing-offline') || authUser.value?.roles?.includes('marketing-online')) ?? false,
);
const isCashierUser = computed(() => authUser.value?.roles?.includes('cashier') ?? false);

const defaultMarketingId = computed(() =>
    isMarketingUser.value && authUser.value ? String(authUser.value.id) : '',
);

const form = useForm({
    customer_id: '',
    marketing_id: defaultMarketingId.value || 'none',
    channel: 'store',
    price_type: 'retail',
    payment_type: OrderPaymentType.CASH as string,
    is_affiliate: false,
    tiktok_order_id: '',
    shopee_order_id: '',
    discount: '',
    nego_price: '',
    notes: '',
    status: OrderStatus.PENDING as string,
});

const isStoreChannel = computed(() => form.channel === 'store');
const isMarketplaceChannel = computed(() => form.channel === OrderChannel.SHOPEE || form.channel === OrderChannel.TIKTOK);
const showPhotoInput = computed(() =>
    form.payment_type === OrderPaymentType.QRIS || form.payment_type === OrderPaymentType.TRANSFER,
);

const customerFormOpen = ref(false);
const cartDetailOpen = ref(false);
const printAfterSave = ref(false);
const selectedPaperSize = ref<'58mm' | '80mm'>(PaperSize.MM_80);
const photoState = ref<MediaUploadState>(createMediaUploadState());

const {
    search,
    selectedStockQuality,
    cart,
    filteredCatalog,
    subtotal,
    setCart,
    loadDraftItems,
    getVariantPrice,
    getCartItem,
    lineSubtotal,
    stockQualityLabel,
    addToCart,
    removeFromCart,
    adjustQuantity,
    syncCartItemQuantity,
    decreaseVariantQty,
} = useOrderPosCart({
    catalog: () => props.catalog,
    isCreateMode: () => isCreateMode.value,
    priceType: () => form.price_type,
    isCashierUser: () => isCashierUser.value,
});

const discountAmount = computed(() => Number(parseRupiah(form.discount)) || 0);
const negoPriceAmount = computed(() => Number(parseRupiah(form.nego_price)) || 0);
const totalAmount = computed(() => {
    if (negoPriceAmount.value > 0) {
        return negoPriceAmount.value;
    }

    return Math.max(subtotal.value - discountAmount.value, 0);
});

function onCustomerCreated(customer: { id: number; name: string }) {
    emit('customer-created', customer);
    form.customer_id = String(customer.id);
}

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

    form.customer_id = props.initialData.customer_id;
    form.marketing_id = props.initialData.marketing_id || 'none';
    form.channel = props.initialData.channel;
    form.price_type = props.initialData.price_type;
    form.payment_type = props.initialData.payment_type;
    form.is_affiliate = props.initialData.is_affiliate;
    form.tiktok_order_id = props.initialData.tiktok_order_id;
    form.shopee_order_id = props.initialData.shopee_order_id;
    form.discount = props.initialData.discount;
    form.nego_price = props.initialData.nego_price;
    form.notes = props.initialData.notes;
    form.status = props.initialData.status || OrderStatus.PENDING;
    photoState.value = createMediaUploadState(
        props.initialData.photos ? [props.initialData.photos] : [],
    );
    setCart(props.initialData.items);
}

watch(() => props.initialData, populateForm, { immediate: true });
loadDraftItems(props.draftItems ?? []);

watch(
    () => form.channel,
    (channel) => {
        if (channel === OrderChannel.SHOPEE) {
            form.price_type = 'shopee';
            form.payment_type = OrderPaymentType.MARKETPLACE;
        } else if (channel === OrderChannel.TIKTOK) {
            form.price_type = 'tiktok';
            form.payment_type = OrderPaymentType.MARKETPLACE;
        } else if (!props.storePriceTypes.some((type) => type.value === form.price_type)) {
            form.price_type = 'retail';
        }

        if (channel === 'store') {
            form.is_affiliate = false;
        }
    },
);

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

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

    if (!isCashierUser.value && form.customer_id) {
        formData.append('customer_id', form.customer_id);
    }

    if (form.marketing_id && form.marketing_id !== 'none') {
        formData.append('marketing_id', form.marketing_id);
    } else if (isMarketingUser.value && authUser.value) {
        formData.append('marketing_id', String(authUser.value.id));
    }

    if (isCashierUser.value) {
        formData.append('channel', 'store');
        formData.append('price_type', 'retail');
        formData.append('payment_type', OrderPaymentType.CASH);
    } else {
        formData.append('channel', form.channel);
        formData.append('price_type', form.price_type);
        formData.append('payment_type', form.payment_type);
    }

    if (!isStoreChannel.value && !isCashierUser.value) {
        formData.append('is_affiliate', form.is_affiliate ? '1' : '0');
    }

    if (!isCashierUser.value) {
        if (form.channel === OrderChannel.TIKTOK && form.tiktok_order_id) {
            formData.append('tiktok_order_id', form.tiktok_order_id);
        }

        if (form.channel === OrderChannel.SHOPEE && form.shopee_order_id) {
            formData.append('shopee_order_id', form.shopee_order_id);
        }
    }

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

    if (showPhotoInput.value) {
        appendRootPhotosToFormData(formData, photoState.value);
    }

    if (isCreateMode.value && printAfterSave.value) {
        formData.append('print', '1');
        formData.append('paper_size', selectedPaperSize.value);
    }

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

    return formData;
}

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

        return;
    }

    const payload = buildFormData();

    form.transform(() => payload).post(props.submitUrl, {
        forceFormData: true,
        onError: (errors: Record<string, string>) => {
            if (errors.system) {
                toast.error(errors.system);
            }
        },
    });
}
</script>

<template>
    <div class="grid gap-4 xl:grid-cols-[1fr_380px]">
        <OrderPosCatalogPanel
            v-model:search="search"
            v-model:selected-stock-quality="selectedStockQuality"
            :is-cashier-user="isCashierUser"
            :filtered-catalog="filteredCatalog"
            :get-variant-price="getVariantPrice"
            :get-cart-item="getCartItem"
            @add-to-cart="addToCart"
            @decrease-qty="decreaseVariantQty"
        />

        <Card class="h-fit xl:sticky xl:top-4">
            <CardHeader class="pb-3">
                <CardTitle class="flex items-center justify-between gap-2 text-base">
                    <span class="flex items-center gap-2">
                        <ShoppingCart class="size-4" />
                        Ringkasan Pesanan
                    </span>
                    <button
                        v-if="cart.length > 0"
                        type="button"
                        class="text-xs font-normal text-primary underline underline-offset-2 hover:text-primary/80"
                        @click="cartDetailOpen = true"
                    >
                        Lihat Detail
                    </button>
                </CardTitle>
            </CardHeader>
            <CardContent>
                <form @submit.prevent="submit">
                    <FieldGroup>
                        <FieldSet class="grid gap-4">
                            <OrderPosMetadataFields
                                :form="form"
                                :channels="channels"
                                :store-price-types="storePriceTypes"
                                :payment-types="paymentTypes"
                                :customers="customers"
                                :marketings="marketings"
                                :is-cashier-user="isCashierUser"
                                :is-store-channel="isStoreChannel"
                                :is-marketplace-channel="isMarketplaceChannel"
                                :is-marketing-user="isMarketingUser"
                                :can-create-customer="can('customers.create')"
                                @open-customer-form="customerFormOpen = true"
                            />

                            <OrderPosCartSummaryItems
                                :cart="cart"
                                :stock-quality-label="stockQualityLabel"
                                :line-subtotal="lineSubtotal"
                                @remove="removeFromCart"
                                @adjust-quantity="adjustQuantity"
                                @sync-quantity="syncCartItemQuantity"
                            />

                            <OrderPosCheckoutSection
                                v-model:print-after-save="printAfterSave"
                                v-model:selected-paper-size="selectedPaperSize"
                                v-model:photo-state="photoState"
                                :form="form"
                                :subtotal="subtotal"
                                :total-amount="totalAmount"
                                :show-photo-input="showPhotoInput"
                                :is-create-mode="isCreateMode"
                                :can-complete="can('orders.complete')"
                                :can-create="can('orders.create')"
                                :cart-empty="cart.length === 0"
                                :submit-label="submitLabel"
                            />
                        </FieldSet>
                    </FieldGroup>
                </form>
            </CardContent>
        </Card>
    </div>

    <CustomerQuickCreateModal v-model:open="customerFormOpen" @created="onCustomerCreated" />

    <OrderPosCartDetailDialog
        v-model:open="cartDetailOpen"
        :cart="cart"
        :stock-quality-label="stockQualityLabel"
        :line-subtotal="lineSubtotal"
        :total-amount="totalAmount"
    />
</template>
