import { OptionsOrGroups } from 'react-select';
import AsyncSelect from 'react-select/async';
import { Fragment, useEffect, useState } from 'react';
import { coloredToast } from '@/lib/toast';
import NumberFormatter from '@/lib/ribuan';
import { formatRupiah } from '@/utils/formatRupiah';
import {
    findBestFreeItemPromotionLink,
    type PromotionForLink,
    withPromotionLink,
} from '@/utils/orderPromotionLink';

interface Item {
    id: number;
    item_id: string;
    product_image: string;
    product_title: string;
    product_sku: string;
    product_url: string;
    quantity: number;
    amount: number;
    price?: number;
    attributes: any[];
    custom_text: any;
    variation: null | any;
    is_gift_card?: boolean;
    is_free_item?: boolean;
    gift_card_data?: any;
    product?: string;
    product_categories?: string[];
    promotion_id?: string;
    promotion_name?: string;
    promotion_case_id?: number;
}

interface ItemFormProps {
    items: Item[];
    setItems: React.Dispatch<React.SetStateAction<Item[]>>;
    order_status: string;
    promotions?: PromotionForLink[];
}

function applyFreeItemPromotionLink(
    item: Item,
    allItems: Item[],
    promotions: PromotionForLink[]
): Item {
    if (!item.is_free_item) {
        return withPromotionLink(item, null);
    }

    const link = findBestFreeItemPromotionLink(item, promotions, allItems, item.id);
    return withPromotionLink(item, link);
}

const ItemForm: React.FC<ItemFormProps> = ({ items, setItems, order_status, promotions = [] }) => {
    const itemsEligibilityKey = items
        .map((item) => `${item.id}:${item.is_free_item ? 1 : 0}:${item.item_id}:${item.quantity}:${item.amount}`)
        .join('|');

    useEffect(() => {
        if (!promotions.length) return;

        setItems((prev) => {
            let changed = false;
            const next = prev.map((item) => {
                if (!item.is_free_item) return item;

                const linked = applyFreeItemPromotionLink(item, prev, promotions);
                if (
                    linked.promotion_id !== item.promotion_id ||
                    linked.promotion_name !== item.promotion_name ||
                    linked.promotion_case_id !== item.promotion_case_id
                ) {
                    changed = true;
                    return linked;
                }
                return item;
            });
            return changed ? next : prev;
        });
    }, [promotions, itemsEligibilityKey, setItems]);

    const addItem = () => {
        let maxId = 0;
        maxId = items?.length ? items.reduce((max: number, character: any) => (character.id > max ? character.id : max), items[0].id) : 0;

        setItems([
            ...items,
            {
                id: maxId + 1,
                item_id: '',
                product_image: '',
                product_title: '',
                product_sku: '',
                product_url: '',
                quantity: 0,
                amount: 0,
                attributes: [],
                variation: null,
                custom_text: {},
                is_free_item: false,    
            },
        ]);
    };

    const removeItem = (item: any = null) => {
        setItems(items.filter((d: any) => d.id !== item.id));
    };

    const changeQuantityPrice = (type: string, value: string, id: number) => {
        const updatedItems = items.map((item) => {
            if (item.id === id) {
                return {
                    ...item,
                    [type === 'quantity' ? 'quantity' : 'amount']: Number(value),
                };
            }
            return item;
        });

        const withFreeItemLinks = updatedItems.map((item) =>
            item.is_free_item ? applyLink(item, updatedItems) : item
        );

        setItems(withFreeItemLinks);
    };

    const applyLink = (item: Item, allItems: Item[]) => applyFreeItemPromotionLink(item, allItems, promotions);

    const toggleFreeItem = (id: number) => {
        const updatedItems = items.map((item) => {
            if (item.id !== id) return item;

            const isFree = !item.is_free_item;
            const baseItem = {
                ...item,
                is_free_item: isFree,
                price: isFree ? item.amount || item.price || 0 : item.price,
                amount: isFree ? 0 : item.price || item.amount || 0,
            };

            if (!isFree) {
                return withPromotionLink(baseItem, null);
            }

            return applyLink(baseItem, items.map((row) => (row.id === id ? baseItem : row)));
        });

        setItems(updatedItems);
    };

    const setOrderItems = async (selectedItem: string, id_item: number) => {
        try {
            const id = selectedItem.split(' | ');
            const product_id = id[0];
            const product_item_idx = id[1] || '';
            const payload = {
                product_id,
                product_item_idx,
            };
            const api_url = process.env.API_URL;
            const response = await fetch(`${api_url}api/products/order-item-selected`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                credentials: 'include', // Include this option
                body: JSON.stringify(payload),
            });
            const data = await response.json();
            // Create a copy of the items array
            const updatedItems = items.map((item) => {
                if (item.id !== id_item) return item;

                let image = data.product_images[0] || '';
                let data_attributes = [];
                if (data.variation && data.variation.attributes) {
                    data_attributes = data.variation.attributes.map((attr: any) => attr.name);
                    image = data.variation.image || '';

                    const attributeObject = data.variation.attributes
                        ? data.variation.attributes.reduce((result: any, attribute: any) => {
                              result[attribute.name] = attribute.value.label || attribute.value;
                              return result;
                          }, {})
                        : {};

                    data.variation = {
                        ...data.variation,
                        ...attributeObject,
                    };
                }

                const nextItem = {
                    ...item,
                    item_id: selectedItem,
                    product: product_id,
                    product_categories: data.product_categories || [],
                    product_title: data.product_title,
                    product_url: data.product_url,
                    product_sku: data.product_sku,
                    quantity: 1,
                    amount: item.is_free_item ? 0 : data.product_price,
                    price: data.product_price,
                    attributes: data_attributes,
                    variation: data.variation,
                    product_image: image || data.product_images[0] || '',
                    is_gift_card: false,
                    is_free_item: item.is_free_item || false,
                    gift_card_data: null,
                };

                const draftItems = items.map((row) => (row.id === id_item ? nextItem : row));
                return applyLink(nextItem, draftItems);
            });
            setItems(updatedItems);
        } catch (error) {
            console.error(error);
        }
    };

    const fetchData = async (inputValue: string) => {
        try {
            const api_url = process.env.API_URL;
            const response = await fetch(`${api_url}api/products/order-item?q=${encodeURIComponent(inputValue)}`, {
                method: 'GET',
                headers: {
                    'Content-Type': 'application/json',
                },
                credentials: 'include',
            });

            let data: unknown;
            try {
                data = await response.json();
            } catch {
                coloredToast('danger', 'Gagal membaca respons pencarian produk');
                return [];
            }

            if (!response.ok) {
                const message =
                    typeof data === 'object' && data !== null && 'message' in data && typeof (data as { message: unknown }).message === 'string'
                        ? (data as { message: string }).message
                        : 'Pencarian produk gagal. Coba kata kunci lain.';
                coloredToast(response.status >= 500 ? 'danger' : 'warning', message);
                return [];
            }

            if (!Array.isArray(data)) {
                coloredToast('warning', 'Format respons pencarian tidak valid');
                return [];
            }

            return data
                .filter((item: any) => item?.idx_variation && item?.product_name)
                .map((item: any) => ({ value: item.idx_variation, label: item.product_name }));
        } catch (error) {
            console.error('Error fetching data:', error);
            coloredToast('danger', 'Gagal memuat daftar produk');
            return [];
        }
    };

    let debounceTimeout: any;
    const loadOptions = async (inputValue: string): Promise<OptionsOrGroups<any, any>> => {
        return new Promise<OptionsOrGroups<any, any>>((resolve) => {
            clearTimeout(debounceTimeout);

            if (inputValue.length >= 3) {
                debounceTimeout = setTimeout(async () => {
                    try {
                        const options = await fetchData(inputValue);
                        const filteredOptions = options.filter((option: any) => !items.some((item: any) => item.item_id === option.value));

                        resolve(filteredOptions);
                    } catch (error) {
                        console.error('Error loading options:', error);
                        resolve([]);
                    }
                }, 1000);
            } else {
                resolve([]);
            }
        });
    };
    const [showButton, setShowButton] = useState(true);

    function renderDetail(label: string, value: string, id?: string | null) {
        id = id || '';

        return (
            <div className="flex items-center capitalize">
                <div className="w-1/4 font-semibold">{label}</div>
                {label !== 'status mutasi' ? (
                    <div className={`${value === 'received' ? 'text-warning' : value === 'prepared' ? 'text-info' : value === 'picked' ? 'text-success' : value === 'pending' ? 'text-danger' : ''}`}>
                        : {value}
                    </div>
                ) : (
                    <>
                        :
                        {!value ? (
                            <button className="btn btn-sm btn-outline-info ml-1 mt-2" onClick={() => id && approveMutasi(id)}>
                                Approve
                            </button>
                        ) : (
                            <div className="ml-1 text-success">Approved</div>
                        )}
                    </>
                )}
            </div>
        );
    }

    async function approveMutasi(id: String) {
        try {
            const api_url = process.env.API_URL;
            const response = await fetch(`${api_url}api/click-and-collect/approved-mutasi-varian/${id}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },

                credentials: 'include', // Include this option
            });

            const data = await response.json();

            if (!response.ok) {
                throw Error(data.message);
            }

            if (data.varian_status === true) {
                coloredToast('success', 'notification sent successfully please refresh the page');
            }
        } catch (error) {
            coloredToast('warning', 'notification sent failed, ' + error);
        }
    }

    async function handleSendToStore(clickAndCollectData: String) {
        try {
            const api_url = process.env.API_URL;
            const response = await fetch(`${api_url}api/click-and-collect/send-notification-store/${clickAndCollectData}`, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json',
                },
                credentials: 'include', // Include this option
            });

            const data = await response.json();

            if (!response.ok) {
                throw Error(data.message);
            }

            if (data.store_notified === true) {
                setShowButton(false);
                coloredToast('success', 'notification sent successfully');
            }
        } catch (error) {
            coloredToast('warning', 'notification sent failed, ' + error);
        }
    }

    return (
        <div className="mb-8 table w-full">
            <table>
                <thead>
                    <tr>
                        <th>Item</th>
                        <th className="w-1">Quantity</th>
                        <th className="w-1">Price</th>
                        <th>Total</th>
                        <th className="w-1"></th>
                    </tr>
                </thead>
                <tbody>
                    {items.length <= 0 && (
                        <tr>
                            <td colSpan={5} className="!text-center font-semibold">
                                No Item Available
                            </td>
                        </tr>
                    )}
                    {items.map((item: any) => {
                        return (
                            <Fragment key={item.id}>
                                <tr className="align-top">
                                    <td className="custom-select w-1/3">
                                        {!item.item_id ? (
                                            
                                            <AsyncSelect
                                                loadOptions={loadOptions}
                                                placeholder="Search for product"
                                                value={item.product_id}
                                                classNamePrefix="user-form-select"
                                                onChange={(selectedItem: any) => {
                                                    if (selectedItem) {
                                                        setOrderItems(selectedItem.value, item.id);
                                                    }
                                                }}
                                            />
                                            
                                                
                                        ) : (
                                            <div className="flex items-center gap-2">
                                                <input type="text" readOnly className="w1/3 form-input" value={item.product_title} />
                                               
                                            </div>
                                        )}
                                        {item.attributes.length > 0 && (
                                            <div className="my-4">
                                                {item.attributes.map((attr: string) => {
                                                    let valueAttr = item.variation[attr];
                                                    if (attr === 'color') {
                                                        valueAttr = valueAttr.label || item.variation[attr]; // Assign the label to valueAttr
                                                    }
                                                    return (
                                                        <div key={attr} className="my-2 mx-2 font-bold">
                                                            {attr} : {valueAttr}
                                                        </div>
                                                    );
                                                })}
                                                {/* {item.attributes.map((attr: string) => {
                                                let valueAttr = item.variation.attributes.find((varian: any) => varian.name === attr)?.value;
                                                                                                if (attr === 'color') {
                                                    valueAttr = valueAttr.label; // Assign the label to valueAttr
                                                }
                                                return (
                                                    <div key={attr} className="my-2 font-bold">
                                                        {attr} : {valueAttr}
                                                    </div>
                                                );
                                            })} */}
                                            </div>
                                        )}
                                        
                                        {item.is_gift_card && (
                                            <div className="my-4 rounded p-3">
                                                <div className="mb-2 font-bold text-purple-900">Gift Card Details:</div>
                                                {item.gift_card_data?.card_id && (
                                                    <div className="my-1 text-sm">
                                                        <span className="font-semibold">Card Design:</span> {item.gift_card_data.card_id}
                                                    </div>
                                                )}
                                                {(item.gift_card_data?.title || item.custom_text?.gift_header) && (
                                                    <div className="my-1">
                                                        <span className="font-semibold">Header:</span>
                                                        <div className="whitespace-pre-wrap text-sm">{item.gift_card_data?.title || item.custom_text?.gift_header || ''}</div>
                                                    </div>
                                                )}
                                                {(item.gift_card_data?.description || item.custom_text?.gift_content) && (
                                                    <div className="my-1">
                                                        <span className="font-semibold">Description:</span>
                                                        <div className="whitespace-pre-wrap text-sm">{item.gift_card_data?.description || item.custom_text?.gift_content || ''}</div>
                                                    </div>
                                                )}
                                            </div>
                                        )}
                                        {!item.is_gift_card &&
                                            item.custom_text &&
                                            Object.keys(item.custom_text).length > 0 &&
                                            Object.entries(item.custom_text).map(([name, value]) => (
                                                <div key={name}>
                                                    <div className="my-2 whitespace-break-spaces font-bold">{`${name.replaceAll('_', ' ')} : ${value}`}</div>
                                                </div>
                                            ))}
                                            <label className="mt-2 flex cursor-pointer items-center gap-2">
                                                    <input
                                                        type="checkbox"
                                                        checked={item.is_free_item || false}
                                                        onChange={() => toggleFreeItem(item.id)}
                                                        className="form-checkbox"
                                                    />
                                                    <span className="text-xs text-gray-600">Mark as Free Item</span>
                                                </label>
                                            {item.is_free_item && item.promotion_name && (
                                                <p className="mt-1 text-xs italic text-primary">Promo: {item.promotion_name}</p>
                                            )}
                                    </td>
                                    <td>
                                        <input
                                            type="number"
                                            className="form-input w-20"
                                            placeholder="Quantity"
                                            value={item.quantity}
                                            min={0}
                                            disabled={!item.item_id || order_status !== 'Processing'}
                                            onChange={(e) => changeQuantityPrice('quantity', e.target.value, item.id)}
                                        />
                                    </td>
                                    <td>
                                        {item.is_free_item ? (
                                            <div className="mt-1 font-semibold text-green-600 bg-green-600 text-white px-2 py-1 rounded text-center text-xs">
                                                FREE
                                            </div>
                                        ) : (
                                            <NumberFormatter
                                                className="form-input w-32"
                                                placeholder="Price"
                                                value={item.amount}
                                                min={0}
                                                disabled={!item.item_id || order_status !== 'Processing'}
                                                onChange={(value: any) => changeQuantityPrice('price', value.toString(), item.id)}
                                            />
                                        )}
                                        
                                    </td>
                                    <td>
                                        <div className="mt-2">
                                            {item.is_free_item ? (
                                                <span className="font-semibold text-green-600">FREE</span>
                                            ) : (
                                                formatRupiah(item.quantity * item.amount, 'Rp')
                                            )}
                                        </div>
                                    </td>
                                    <td>
                                        {order_status === 'Processing' && (
                                            <button type="button" onClick={() => removeItem(item)}>
                                                <svg
                                                    xmlns="http://www.w3.org/2000/svg"
                                                    width="20"
                                                    height="20"
                                                    viewBox="0 0 24 24"
                                                    fill="none"
                                                    stroke="currentColor"
                                                    strokeWidth="1.5"
                                                    strokeLinecap="round"
                                                    strokeLinejoin="round"
                                                >
                                                    <line x1="18" y1="6" x2="6" y2="18"></line>
                                                    <line x1="6" y1="6" x2="18" y2="18"></line>
                                                </svg>
                                            </button>
                                        )}
                                    </td>
                                </tr>
                                {item.click_n_collect && (
                                    <tr>
                                        <td colSpan={5}>
                                            <div className="my-2 font-semibold">Click And Collect Detail</div>
                                            {showButton && !item.click_n_collect.store_notified && (
                                                <button className="btn btn-info btn-sm my-3" onClick={() => handleSendToStore(item.click_n_collect._id)}>
                                                    Send notification to Store
                                                </button>
                                            )}
                                            {renderDetail('unique code', item.click_n_collect.unique_code)}
                                            {renderDetail('store', item.click_n_collect.store_name)}
                                            {renderDetail('status', item.click_n_collect.status)}
                                            {item.click_n_collect.keychain_pic && renderDetail('keychain pic', item.click_n_collect.store_name)}
                                            {item.click_n_collect.keychain_pic && renderDetail('keychain code', item.click_n_collect.keychain_code)}
                                            {renderDetail('varian', item.click_n_collect.varian)}
                                            {item.click_n_collect.varian && renderDetail('status mutasi', item.click_n_collect.varian_status, item.click_n_collect._id)}
                                        </td>
                                    </tr>
                                )}
                            </Fragment>
                        );
                    })}
                </tbody>
            </table>
            {order_status === 'Processing' && (
                <div className="m-4">
                    <button type="button" className="btn btn-outline-primary btn-sm" onClick={() => addItem()}>
                        Add Item
                    </button>
                </div>
            )}
        </div>
    );
};

export default ItemForm;
