import {NodesStore, OfferData, useNodesStore} from "./store";
import {generateIdForType} from "./NodeHelpers";
import {cloneDeep, mergeWith, isArray} from "lodash";
import {CouponsPlus} from "../globals";

export const getOffers = () => {
    const state = useNodesStore.getState();

    return new Offers(state);
};

export type OffersState = Pick<NodesStore, 'offers'>

export class Offers {
    constructor(private readonly state: OffersState) {}
    get(id: string): OfferData | undefined {
        return this.state.offers.find((offer) => offer.id === id);
    }

    add(offers: (OfferData | Omit<OfferData, 'id'>)[]): void {
        // only add the offers that are not already in the state
        offers.forEach((offer) => {
            // @ts-ignore
            if (!('id' in offer)) {
                // @ts-ignore
                offer.id = generateIdForType('offers')
            }
            const offerWithId: OfferData = offer as OfferData

            if (!this.get(offerWithId.id)) {
                this.state.offers.push(this.mergeWithDefaultCardData(offerWithId));
            }
        })
    }

    update(offer: OfferData): void {
        const offerIndex = this.state.offers.findIndex(({id}) => id === offer.id);

        if (offerIndex === -1) {
            return;
        }

        // we had: merge(this.state.offers[offerIndex], offer)
        // but fckass immer had a problem when merging arrays deeply nested in the object structure
        this.state.offers[offerIndex] = offer;

    }
    remove(offerId: string): void {
        const index = this.state.offers.findIndex((offer) => offer.id === offerId);
        if (index !== -1) {
            this.state.offers.splice(index, 1);
        }
    }

    mergeWithDefaultCardData(offerData: OfferData) {
        // we cannot use getComponentMetaData() unfortunately because of the god damn circular dependency issues
        const customizer = (objValue: any, srcValue: any) => {
            // If source value is defined and types don't match (e.g., array vs object), replace instead of merge
            if (srcValue !== undefined && ((isArray(objValue) && !isArray(srcValue)) || (!isArray(objValue) && isArray(srcValue)))) {
                return srcValue;
            }
            // For other cases, let mergeWith handle it (undefined means use default behavior)
            return undefined;
        };

        const offerComponentDefinition = CouponsPlus.components.offers[offerData.type]
            || CouponsPlus?.stubs?.offers?.[offerData.type]

        return mergeWith({options: cloneDeep(offerComponentDefinition?.defaultOptions || {})}, offerData, customizer);
    }

}
