import React, {FC, ReactNode} from "react";
import {NodeProps, Position} from "@xyflow/react";
import {OfferData, RenderedNodeDataInBranch, useNodesStore} from "./tree/store";
import {OfferCard} from "./tree/OfferCard";
import {Handle} from "./tree/Handle";
import {colors} from "./tree/Colors";
import {RightContextButton} from "./tree/RightContextButton";
import {__} from "./globals";
import {Color, groupHover, hover} from "./tree/Color";
import {useBranch, useBranchChildrenShallow} from "./tree/TreeHooks";
import {useOpenTestablesPopupWindow} from "./tree/useOpenTestablesPopupWindow";
import {PopupWindowStateContext, TreeContextData} from "./tree/atoms";
import {clone} from "lodash";
import classNames from "classnames";
import {incompatibleOffersFromInsideTiers} from "./tree/actions/SelectOffersNew";
import {FloatingMarker} from "./tree/FloatingMarker";
import {getCardRendererFromType} from "./tree/cards";
import type {CardRenderer} from "./tree/CardRenderers";

export type OffersBranchData = RenderedNodeDataInBranch & {
    renderedNodeType: 'branch-offers',
}
export const getOffersPopupWindowContext = (excludedOfferTypes: string[] = [], windowData?: TreeContextData['mainWindow']): PopupWindowStateContext<TreeContextData> => {
    return {
        id: 'offers-new',
        scope: 'tier-branch',
        data: {
            mainWindow: windowData,
            componentType: 'offer',
            supportsMultipleComponents: false,
            unsupportedComponents: excludedOfferTypes,
            targetType: 'ghost', // root | testableComposite
            mode: 'create'
        }
    } as PopupWindowStateContext<TreeContextData>;
}

type SuggestedScopeMarker = ReturnType<NonNullable<CardRenderer['suggestedScopeMarker']>>;
type SuggestedScopeMarkerData = { prefix?: string, label: string };
const isSuggestedScopeMarkerData = (marker: SuggestedScopeMarker): marker is SuggestedScopeMarkerData => {
    return !!marker && typeof marker === 'object' && 'label' in marker;
}
const getSuggestedScopeMarker = (offer: OfferData, suggestedScope?: string): ReactNode => {
    const offerCardRendererData = getCardRendererFromType(offer.type) as CardRenderer | undefined
    const marker = offerCardRendererData?.suggestedScopeMarker?.(suggestedScope || '')

    if (isSuggestedScopeMarkerData(marker)) {
        return <FloatingMarker prefix={marker.prefix} label={marker.label}/>
    }

    return marker ?? null
}

function OffersCard({
                        isFirst,
                        shiftedOffers,
                        branchId,
                        offer,
                        color,
                        onNewOfferClick,
                        index,
                        afterContentInside,
                        suggestedScope,
                        suggestedScopeMarker
                    }: {
    id?: string,
    isFirst: boolean,
    shiftedOffers: OfferData[],
    branchId: string,
    offer: OfferData,
    color: Color,
    onNewOfferClick: () => any,
    index: number,
    afterContentInside?: ReactNode,
    suggestedScope?: string,
    suggestedScopeMarker?: ReactNode
}) {
    if (!shiftedOffers) {
        return null;
    }
    const itsTheLast = index === shiftedOffers.length - 1 && shiftedOffers.length
    const hasMoreThanOneOffer = shiftedOffers.length > 0 // it will be 0 when there's only one offer (because its been array.shifted out and passed manually)
    const offerCardRendererData = getCardRendererFromType(offer.type) as CardRenderer

    const rightContextButton = <div className={'absolute right-[-2px] translate-x-full top-1/2 translate-y-[-50%]'}>
            <RightContextButton type={'add'}
                               scope={'offer'}
                               color={{
                                   color: colors.gray,
                                   tint: (color, type, context) => {
                                       if (context === 'button.label') {
                                           return color.text(40);
                                       } else if (context === 'hover:button.background') {
                                           return color.background(hover(0));
                                       } else if (context === 'group-hover:anchor') {
                                           // @ts-ignore
                                           return color[type](groupHover(50));
                                       }
                                       // @ts-ignore
                                       return color[type](30);
                                   }
                               }}
                               thickness={2}
                               bringButtonToFrontOnHover={false}
                               uppercased={false}
                               labelSize="text-smaller-1"
                               label={(buttonIsHovered) => false && buttonIsHovered && __('Extra offer')}
                               onClick={onNewOfferClick}
        /></div>

    let itsTheOnlyOffer = isFirst && !hasMoreThanOneOffer;
    let itHasMoreOffersAndThisIsntTheFirstOffer = hasMoreThanOneOffer && !isFirst;
    let isTheLast = shiftedOffers.length === index + 1;
    const showRightContextButton = (itsTheOnlyOffer || (itHasMoreOffersAndThisIsntTheFirstOffer && isTheLast))
    // here render  custom card if supported and enabled
    const customCardExtraData = {
        isFirst, hasMoreThanOneOffer, itsTheLast, afterContentInside, rightContextButton, showRightContextButton, branchId, suggestedScope
    }

    const CustomCard = offerCardRendererData?.CustomCardComponent?.({color, context: 'offers', id: offer.id, localData: offer}, customCardExtraData)

    if (!!CustomCard) {
        return <CustomCard parameters={{color, context: 'offers', id: offer.id, localData: offer}} extraData={customCardExtraData} />
    }

    return <div key={offer?.id} className="relative flex items-center space-x-2">
        <OfferCard id={offer?.id} offer={offer} branchID={branchId} color={color}
                   afterContentInside={() => afterContentInside}
                   afterContent={() => {

                       return <>
                           {suggestedScopeMarker}
                           {showRightContextButton && rightContextButton}
                       </>
                   }}/>
    </div>;
}

export const OffersBranch: FC<{ data: OffersBranchData } & NodeProps> = ({id}) => {
    const getOffer = useNodesStore(store => store.getOffer)
    const branch = useBranch(id)
    const offers = clone(useBranchChildrenShallow<OfferData>(id) ?? [])
    const allSelectedOffers = clone(offers)
    const openTestablesPopup = useOpenTestablesPopupWindow();

    const addBranchOffer = useNodesStore(store => store.addBranchOffer)
    // @ts-ignore

    const openPopup = () => {
        // @ts-ignore
        openTestablesPopup({
            // @ts-ignore
            context: getOffersPopupWindowContext([
                ...allSelectedOffers.map(o => o.type),
                ...(branch?.isInsideAnotherBranch() ? incompatibleOffersFromInsideTiers : [])
            ], {
                title: __('Add another offer'),
                description: __('You can combine multiple offers per branch like a cart discount + gift, cart discount + shipping discount, etc.')
            }),
            onClose: (data) => {
                const {status, components} = data

                if (status === 'success' && components?.length > 0) {
                    addBranchOffer(components[0], id)
                }
            }
        })
    }


    if (!offers || !branch) {
        console.error('OffersBranch: offers or branch not found', id)
        return null;
    }
    const color = colors.blue;
    const firstOffer = offers.shift()!


    if (offers.length === 0 && !firstOffer) {
        return null
    }

    const isInsideBranch = branch.isInsideAnotherBranch()
    const suggestedScope = branch.getTreeNode().suggestedScope

    return <div className={'relative flex items-start gap-1'}>
        <div className={isInsideBranch ? 'relative flex items-center' : ''}>
            <OffersCard isFirst
                        shiftedOffers={offers}
                        offer={firstOffer}
                        branchId={id}
                        color={color}
                         index={0}
                         onNewOfferClick={openPopup}
                         suggestedScope={suggestedScope}
                         suggestedScopeMarker={getSuggestedScopeMarker(firstOffer, suggestedScope)}
                         afterContentInside={<div className={classNames({
                             'relative -top-y-4 z-[100000]': !isInsideBranch,
                         })}>
                            <Handle
                                id={isInsideBranch ? `left` : 'top'}
                                type={'target'}
                                position={isInsideBranch ? Position.Left : Position.Top}
                                color={color}
                            />
                        </div>}
            />
        </div>
        {offers.map((offer, index) => {
            return <>
                {true &&
                    <div className={'text-gray-500 h-full pt-4'}>
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"
                             className="min-w-5 min-h-5 max-w-5 max-h-5">
                            <path
                                d="M10.75 4.75a.75.75 0 0 0-1.5 0v4.5h-4.5a.75.75 0 0 0 0 1.5h4.5v4.5a.75.75 0 0 0 1.5 0v-4.5h4.5a.75.75 0 0 0 0-1.5h-4.5v-4.5Z"/>
                        </svg>
                    </div>}
                <OffersCard isFirst={false} shiftedOffers={offers} offer={offer} branchId={id} color={color}
                            index={index}
                            suggestedScope={suggestedScope}
                            suggestedScopeMarker={getSuggestedScopeMarker(offer, suggestedScope)}
                            onNewOfferClick={openPopup}/>
            </>
        })}
    </div>
}
