import {
    getAcceptedProdQty,
    getAcceptedProdSubtotal,
    mapOrderItemsToPromoLines,
    type OrderItemForPromo,
} from '@/utils/promotionEligibility';

export interface FreeItemValue {
    productId: string;
    active?: boolean;
}

export interface PromotionCaseForLink {
    id: number;
    value: number;
    case_type: string;
    promo_value: string | string[] | FreeItemValue[];
}

export interface PromotionForLink {
    id?: string;
    _id?: string;
    promotion_type?: string;
    promotion_name: string;
    promotion_start?: string;
    promotion_end?: string;
    promotion_case?: PromotionCaseForLink[];
    promotion_merge_free_items?: boolean;
    promotion_include_categories?: string[];
    promotion_exclude_categories?: string[];
    promotion_included_products?: string[];
    promotion_excluded_products?: string[];
}

export interface PromotionLinkFields {
    promotion_id: string;
    promotion_name: string;
    promotion_case_id: number;
}

export type OrderItemWithPromo = OrderItemForPromo & {
    id?: number;
    item_id?: string;
    product?: string;
    promotion_id?: string;
    promotion_name?: string;
    promotion_case_id?: number;
};

export const isSamePromotion = (
    rowPromotionId: string | undefined,
    rowPromotionName: string | undefined,
    targetId: string,
    targetName: string
) => {
    if (targetId && rowPromotionId) return rowPromotionId === targetId;
    return !!targetName && rowPromotionName === targetName;
};

export const parsePromoValueProductIds = (promoValue: PromotionCaseForLink['promo_value']): string[] => {
    if (!promoValue) return [];

    if (Array.isArray(promoValue)) {
        if (promoValue.length > 0 && typeof promoValue[0] === 'object' && 'productId' in promoValue[0]) {
            return (promoValue as FreeItemValue[])
                .filter((item) => item.active !== false)
                .map((item) => item.productId)
                .filter(Boolean);
        }
        return (promoValue as string[]).filter(Boolean);
    }

    if (typeof promoValue === 'string') {
        try {
            const parsed = JSON.parse(promoValue);
            if (Array.isArray(parsed)) {
                return parsePromoValueProductIds(parsed as PromotionCaseForLink['promo_value']);
            }
        } catch {
            return promoValue
                .split(',')
                .map((id) => id.trim())
                .filter(Boolean);
        }
    }

    return [];
};

export function normalizeProductId(id: string | undefined | null): string {
    if (id == null) return '';
    return String(id).trim();
}

export function productIdInPromoList(productId: string, promoProductIds: string[]): boolean {
    const normalized = normalizeProductId(productId);
    if (!normalized) return false;
    return promoProductIds.some((pid) => normalizeProductId(pid) === normalized);
}

function parseProductIdFromItemId(itemId: string | undefined): string {
    if (!itemId) return '';
    const part = String(itemId).split(' | ')[0]?.trim();
    return part || '';
}

function isFreeItemCaseMetricEligible(
    promotion: PromotionForLink,
    caseValue: number,
    allItems: OrderItemWithPromo[]
): boolean {
    const promotionType = promotion.promotion_type || '';
    if (caseValue <= 0) return false;

    const lines = mapOrderItemsToPromoLines(allItems);
    if (!lines.length) return false;

    if (promotionType === 'qty_of_cart') {
        return getAcceptedProdQty(lines, promotion) >= caseValue;
    }
    if (promotionType === 'subtotal_of_cart' || promotionType === 'birthday') {
        const required = caseValue > 0 ? caseValue : 1;
        return getAcceptedProdSubtotal(lines, promotion) >= required;
    }

    return false;
}

export function getOrderItemProductKey(item: { item_id?: string; product?: string }) {
    const productId = normalizeProductId(item.product || parseProductIdFromItemId(item.item_id));
    const parts = String(item.item_id || '').split(' | ');
    const itemIdx = parts.length > 1 ? parts[1].trim() : null;
    return { productId, itemIdx: itemIdx || null };
}

export function orderItemsMatchProduct(
    item: { item_id?: string; product?: string },
    productId: string,
    productItemIdx: string | number | null | undefined
): boolean {
    const { productId: pid, itemIdx } = getOrderItemProductKey(item);
    if (normalizeProductId(pid) !== normalizeProductId(productId)) return false;

    const expectedIdx =
        productItemIdx != null && productItemIdx !== '' ? String(productItemIdx) : null;
    if (expectedIdx === null) return true;
    return itemIdx === expectedIdx;
}

export function isPromotionFreeItemCaseUsed(
    items: OrderItemWithPromo[],
    promotionId: string,
    promotionName: string,
    promotionCase: PromotionCaseForLink,
    excludeItemId?: number
): boolean {
    if (promotionCase.case_type !== 'free_item') return false;

    return items.some((item) => {
        if (excludeItemId != null && item.id === excludeItemId) return false;
        if (!item.is_free_item) return false;
        if (!isSamePromotion(item.promotion_id, item.promotion_name, promotionId, promotionName)) {
            return false;
        }
        return (
            Number(item.promotion_case_id) === Number(promotionCase.id) ||
            (!item.promotion_case_id && item.promotion_name === promotionName)
        );
    });
}

/** Pilih promotion free_item eligible dengan tier (case value) tertinggi. */
export function findBestFreeItemPromotionLink(
    item: OrderItemWithPromo,
    promotions: PromotionForLink[],
    allItems: OrderItemWithPromo[],
    excludeItemId?: number
): PromotionLinkFields | null {
    if (!item.is_free_item) return null;

    const { productId } = getOrderItemProductKey(item);
    if (!productId) return null;

    let best: (PromotionLinkFields & { tier: number }) | null = null;

    for (const promo of promotions) {
        const promoId = String(promo.id || promo._id || '');
        if (!promoId || !promo.promotion_name) continue;

        const cases = promo.promotion_case || [];

        for (const pc of cases) {
            if (pc.case_type !== 'free_item') continue;

            const tier = Number(pc.value) || 0;
            if (!isFreeItemCaseMetricEligible(promo, tier, allItems)) continue;

            const productIds = parsePromoValueProductIds(pc.promo_value);
            if (!productIdInPromoList(productId, productIds)) continue;

            if (isPromotionFreeItemCaseUsed(allItems, promoId, promo.promotion_name, pc, excludeItemId)) {
                continue;
            }

            if (!best || tier > best.tier) {
                best = {
                    promotion_id: promoId,
                    promotion_name: promo.promotion_name,
                    promotion_case_id: pc.id,
                    tier,
                };
            }
        }
    }

    if (!best) return null;

    const { tier: _tier, ...link } = best;
    return link;
}

export function withPromotionLink<T extends OrderItemWithPromo>(
    item: T,
    link: PromotionLinkFields | null
): T {
    if (!link) {
        const next = { ...item };
        delete next.promotion_id;
        delete next.promotion_name;
        delete next.promotion_case_id;
        return next;
    }

    return {
        ...item,
        promotion_id: link.promotion_id,
        promotion_name: link.promotion_name,
        promotion_case_id: link.promotion_case_id,
    };
}

export function findUpgradeableManualFreeItem(
    items: OrderItemWithPromo[],
    productId: string,
    productItemIdx: string | number | null | undefined
): OrderItemWithPromo | undefined {
    return items.find((item) => {
        if (!item.is_free_item) return false;
        if (item.promotion_id || item.promotion_name) return false;
        return orderItemsMatchProduct(item, productId, productItemIdx);
    });
}
