import {ComponentMeta} from "../ComponentsMeta";
import React from "react";
import {FieldsMap, FieldType} from "../fields";
import {NumberProps} from "../fields/Number";
import {__, CouponsPlus} from "../../globals";
import {TabsProps} from "../fields/tabs";
import {CardRenderer} from "../CardRenderers";
import {usingOfferOptions} from "./CardHelpers";
import {renderCurrencyValue} from "../fields/helpers";
import {CardItemSecondaryValue} from "../CardItemSecondaryValue";
import classNames from "classnames";
import {iconWithClassName} from "../IconWithClassName";
import {ListItem} from "./ListItem";
import {RowOptions} from "./Fields/RowOptions";
import {ComponentCategory} from "../components";

export enum DiscountScope {
    FilteredItems = 'filtereditems',
    CartSubtotal = 'cartsubtotal',
}

export type DiscountOptions = {
    type: 'percentage' | 'amount',
    amount: number,
    scope: DiscountScope,
    /**
     * This is the id of the root testable
     *
     * (!) This is exported/imported as a json representation of a NestedTestableNodeData
     */
    /*
        customFilteredItemsSourceMap: string, // todo: this needs to be exported to json upon save and imported from json upon load
    */
    // this is for the quantity
    limit: {
        isEnabled: boolean,
        // only when type is 'fixed'
        amount: number,
        // only when type is 'pattern'
        pattern: {
            discounted: number,
            groupSize: number,
        },
        type: 'fixed' | 'half' | 'pattern'
        //orderBy: 'lowestprice' | 'highestprice'
    },
    hardLimit: {
        isEnabled: boolean,
        amount: number,
    }
} /* & ({
    // for nested data
    customFilteredItemsSourceMap: TestableCompositeDataWithChildren
} | {
    // for state data
    customFilteredItemsSourceMap: string
} | {
    // for when no custom filtered items
    customFilteredItemsSourceMap: undefined
})
*/
export const DiscountMeta: ComponentMeta = {
    id: 'Discount',
    type: 'offers',
    category: ComponentCategory.CartItemDiscounts,
    priority: 1,
    description: ({suggestedScope}) => {
        if(suggestedScope === 'item_discounts') {
            return __('Select a discount that will be applied to all the filtered items.')
        }

    },
    icon: iconWithClassName(({className, context}) => {
        if (context === 'card') {
            return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" className="size-6">
                <path fillRule="evenodd"
                      d="M7.5 6v.75H5.513c-.96 0-1.764.724-1.865 1.679l-1.263 12A1.875 1.875 0 0 0 4.25 22.5h15.5a1.875 1.875 0 0 0 1.865-2.071l-1.263-12a1.875 1.875 0 0 0-1.865-1.679H16.5V6a4.5 4.5 0 1 0-9 0ZM12 3a3 3 0 0 0-3 3v.75h6V6a3 3 0 0 0-3-3Zm-3 8.25a3 3 0 1 0 6 0v-.75a.75.75 0 0 1 1.5 0v.75a4.5 4.5 0 1 1-9 0v-.75a.75.75 0 0 1 1.5 0v.75Z"
                      clipRule="evenodd"/>
            </svg>
        }

        return <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5}
                    stroke="currentColor" className="size-6">
            <path strokeLinecap="round" strokeLinejoin="round"
                  d="M15.75 10.5V6a3.75 3.75 0 1 0-7.5 0v4.5m11.356-1.993 1.263 12c.07.665-.45 1.243-1.119 1.243H4.25a1.125 1.125 0 0 1-1.12-1.243l1.264-12A1.125 1.125 0 0 1 5.513 7.5h12.974c.576 0 1.059.435 1.119 1.007ZM8.625 10.5a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm7.5 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Z"/>
        </svg>
    }),
    fieldsMap: ({options: {scope, type, limit, hardLimit, customFilteredItemsSourceMap}}) => [
        [
            {
                id: 'type',
                renderType: FieldType.Tab,
                fieldProps: {
                    dimUnselected: true,
                } as TabsProps,
                fieldOptions: {}
            }
        ],
        [
            new RowOptions({
                type: 'featured',
                colWidth: 'auto'
            }),
            {
                id: 'amount',
                renderType: FieldType.Number,
                fieldProps: {
                    hasAmountStructure: false,
                    type: type === 'percentage' ? 'percentage' : 'currency',
                    border: false
                } as Partial<NumberProps>
            }
        ],
        [
            {
                id: 'scope',
                title: __('Apply to'),
                renderType: FieldType.Tab,
                fieldProps: {
                    dimUnselected: true,
                    direction: 'vertical',
                } as TabsProps,
                fieldOptions: {}
            },
        ],
        scope as DiscountOptions['scope'] === DiscountScope.FilteredItems && CouponsPlus.implementations.offers.Discount.extra && [
            {
                id: 'limit.isEnabled',
                renderType: FieldType.BooleanButton,
                title: __('Quantity Limit'),
                fieldOptions: {
                    labels: {
                        // above the button
                        top: [
                            limit.type as DiscountOptions['limit']['type'] === 'pattern' ? __('The discount will be applied to * matching item(s) of every * matching from all the filtered  items using a modular arithmetic algorithm. For example, with this setting of * every *, if a customer adds * matching items to the cart, the cheapest * will be discounted. If they add * matching items, the * cheapest will be discounted. If they add only * matching items, nothing will be discounted because this is designed to work in groups of *. The cheapest items will be discounted. regardless of the order in which they were added to the cart.').replace('*', limit.pattern.discounted.toString()).replace('*', limit.pattern.groupSize.toString()).replace('*', limit.pattern.discounted.toString()).replace('*', limit.pattern.groupSize.toString()).replace('*', limit.pattern.groupSize.toString()).replace('*', limit.pattern.discounted.toString()).replace('*', (limit.pattern.groupSize * 2).toString()).replace('*', (limit.pattern.discounted * 2).toString()).replace('*', (limit.pattern.groupSize - 1).toString()).replace('*', limit.pattern.groupSize) : undefined,
                            limit.type as DiscountOptions['limit']['type'] === 'half' ? '' : undefined,
                            limit.type as DiscountOptions['limit']['type'] === 'half' ? __('The discount will be applied to half (50%) of the items.').replace('*', limit.amount.toString()).replace('*', limit.amount.toString()).replace('*', limit.amount.toString()).replace('*', (limit.amount * 2).toString()) : undefined
                        ].filter(a => a),
                        // bellow the button
                        bottom: []
                    },
                    fieldsMap: {
                        true: [
                            [
                                {
                                    id: 'limit.type',
                                    renderType: FieldType.Tab,
                                    fieldProps: {
                                        size: 'extra-small',
                                        dimUnselected: true,
                                    } as TabsProps,
                                    fieldOptions: {}
                                }
                            ],
                            ...((() => {
                                switch (limit.type as DiscountOptions['limit']['type']) {
                                    case 'fixed':
                                        return [
                                            [{
                                                id: 'limit.amount',
                                                renderType: FieldType.Number,
                                                fieldProps: {hasAmountStructure: false} as Partial<NumberProps>
                                            }]
                                        ]
                                    case 'pattern':
                                        return [
                                            [
                                                {
                                                    id: 'limit.pattern.discounted',
                                                    renderType: FieldType.Number,
                                                    fieldProps: {
                                                        hasAmountStructure: false,
                                                    } as Partial<NumberProps>,
                                                },
                                                {
                                                    id: '', renderType: FieldType.Custom, fieldProps: {
                                                        component: <div
                                                            className="w-full h-full flex flex-col items-center justify-center text-base text-gray-550">
                                                            <span>{
                                                                __('* of every * items').replace('*', limit.pattern.discounted)
                                                                    .replace('*', limit.pattern.groupSize)
                                                            }</span>
                                                            <span>{
                                                                __('(buy * get *)').replace('*', limit.pattern.groupSize - limit.pattern.discounted)
                                                                    .replace('*', limit.pattern.discounted)
                                                            }</span>
                                                        </div>
                                                    }
                                                },
                                                {
                                                    id: 'limit.pattern.groupSize',
                                                    renderType: FieldType.Number,
                                                    fieldProps: {
                                                        hasAmountStructure: false,
                                                    } as Partial<NumberProps>
                                                },
                                            ]
                                        ];
                                }
                                return []
                            })())
                        ].filter(a => {
                            return a.length
                        }) as FieldsMap
                    }
                }
            }
        ],
        CouponsPlus.implementations.offers.Discount.extra && [
            {
                id: 'hardLimit.isEnabled',
                renderType: FieldType.BooleanButton,
                title: __('Maximum Amount'),
                fieldOptions: {
                    labels: {
                        // above the button
                        top: hardLimit.isEnabled ? [
                            scope as DiscountOptions['scope'] === 'cartsubtotal' ? __('The maximum discount that can be applied to the cart subtotal.') : undefined,
                            scope as DiscountOptions['scope'] !== 'cartsubtotal' ? __('The maximum discount that can be applied to the cart for this offer.') : undefined,
                            scope as DiscountOptions['scope'] !== 'cartsubtotal' ? __('The discount to apply to the cart will not exceed this amount. This is not a per-item limit.') : undefined,
                            __('This limit applies to this offer only. It is calculated independently of all other offers & discounts from this and other coupons.')
                            /*__('This limit applies only to this specific Discount offer, and is not affected by other offers from this and other coupons in the cart.')*/
                        ] : [].filter(a => a),
                        // bellow the button
                        bottom: []
                    },
                    fieldsMap: {
                        true: [
                            [
                                {
                                    id: 'hardLimit', // the number field will save the value to hardLimit.amount by default. (see hasAmountStructure,)
                                    renderType: FieldType.Number,
                                    fieldProps: {type: 'currency'} as Partial<NumberProps>
                                }
                            ]
                        ]
                    }
                }
            }
        ],
    ]
}

export const DiscountRenderer: CardRenderer = {
    type: DiscountMeta.id,
    prefix: "*",
//    example: __ ('Buy 1 t-shirt, get 1 free, Buy 2 t-shirts, get 1 at 50% off'),
    icon: DiscountMeta.icon!,
    AboveComputedValue: () => false, // No above computed value for this card
    ComputedValue: usingOfferOptions<DiscountOptions>(({type, amount}, {color,}) => {
        const renderOfferMainValue = (value: string | number, type?: 'normal' | 'number' | 'percentage' | 'amount' | 'fixed-price') => {
            let off = <span
                className={'opacity-60'}>OFF</span>;
            return <div
                className={classNames("flex items-center text-3x font-semibold subpixel-antialiased leading-5 whitespace-nowrap", {
                    'tracking-tighter': (['number', 'percentage'] as typeof type[]).includes(type),
                })}>
                {type === 'amount' && <div className="font-semibold flex items-center space-x-1">
                    {<div>{renderCurrencyValue(value)}</div>} {off}
                </div>}
                {type === 'fixed-price' && <div className="font-semibold flex items-center space-x-1">
                    <span className={'opacity-60 font-normal'}>For</span>{
                    <div>{renderCurrencyValue(value)}</div>}
                </div>}
                {!['amount'].includes(type) && value}
                {type === 'percentage' && <span className="font-medium antialiased tracking-normal">% {off}</span>}
            </div>;
        }
        const renderDiscountValue = () => {
            if (type === 'percentage') {
                return renderOfferMainValue(amount, 'percentage');
            }
            if (type === 'amount') {
                return renderOfferMainValue(amount, 'amount');
            }
        }
        //const cardData = getCardComponentData('offer', type);
        return <div className="space-y-1">
            <div>
                <div className={`${color.text(10)} flex items-center`}>
                    {false && <span className="max-w-[6px] overflow-hidden text-4x font-black translate-y-1/4">-</span>}
                    <div className="--flex --items-center space-y-1">
                        {false && <span className={'opacity-60 px-1'}>-</span>}
                        {true && <CardItemSecondaryValue color={{
                            color,
                            tint: (color) => color.text(20)
                        }}>{__('Discount')}</CardItemSecondaryValue>}
                        {<div className={'flex items-center space-x-1'}>
                            {renderDiscountValue()}
                            {/*
                        {interpolateElements(__(' {1} for {2} '), {
                            1: renderOfferMainValue(quantity),
                            2: renderDiscountValue(),
                        })}
*/}
                        </div>}
                    </div>
                </div>
            </div>
        </div>

    }),
    OutsideComputedValue: usingOfferOptions<DiscountOptions>(({scope, limit, hardLimit}, {color,},) => {
        const text = {
            [DiscountScope.FilteredItems]: __('Applied to: [filtered items] '),
            [DiscountScope.CartSubtotal]: __('Applied to: [cart subtotal]'),
        }[scope];

        const parts = text.split(/\[([^\]]+)\]/);

        return <ul className={`min-w-[fit-content] text-smaller-1 leading-3 text-gray-550
         px-2 py-1 font-medium`}>
            <ListItem>
                {parts.map((part, index) => {
                    // Every second element (index 1, 3, 5...) will be the captured group
                    if (index % 2 === 1) {
                        return <span key={index}
                                     className={classNames('inline-flex items-center space-x-1 font-semibold px-1 leading-4 rounded-6  bg-opacity-40', {
                                         'bg-gray-250': scope === DiscountScope.CartSubtotal,
                                         'bg-purple-tint-20 text-purple-tint-70': scope === DiscountScope.FilteredItems,
                                     })}>{scope === DiscountScope.FilteredItems &&
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor"
                                 className="min-w-[10px] min-h-[10px] max-w-[10px] max-h-[10px]">
                                <path
                                    d="M7.628 1.099a.75.75 0 0 1 .744 0l5.25 3a.75.75 0 0 1 0 1.302l-5.25 3a.75.75 0 0 1-.744 0l-5.25-3a.75.75 0 0 1 0-1.302l5.25-3Z"/>
                                <path
                                    d="m2.57 7.24-.192.11a.75.75 0 0 0 0 1.302l5.25 3a.75.75 0 0 0 .744 0l5.25-3a.75.75 0 0 0 0-1.303l-.192-.11-4.314 2.465a2.25 2.25 0 0 1-2.232 0L2.57 7.239Z"/>
                                <path
                                    d="m2.378 10.6.192-.11 4.314 2.464a2.25 2.25 0 0 0 2.232 0l4.314-2.465.192.11a.75.75 0 0 1 0 1.303l-5.25 3a.75.75 0 0 1-.744 0l-5.25-3a.75.75 0 0 1 0-1.303Z"/>
                            </svg>}<span>{part}</span>{scope === DiscountScope.FilteredItems &&
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="currentColor"
                                 className="min-w-[10px] min-h-[10px] max-w-[10px] max-h-[10px]">
                                <path fillRule="evenodd"
                                      d="M2 13.25a.75.75 0 0 1 .75-.75h6.5V4.56l-.97.97a.75.75 0 0 1-1.06-1.06l2.25-2.25a.75.75 0 0 1 1.06 0l2.25 2.25a.75.75 0 0 1-1.06 1.06l-.97-.97v8.69A.75.75 0 0 1 10 14H2.75a.75.75 0 0 1-.75-.75Z"
                                      clipRule="evenodd"/>
                            </svg>
                        }</span>;
                    }
                    return part;
                })}
            </ListItem>
            {limit.isEnabled && <ListItem>
                {__('Limited to: *').replace('*', {
                    ['pattern']: __('* of every * items').replace('*', limit.pattern.discounted).replace('*', limit.pattern.groupSize),
                    ['fixed']: __('* items').replace('*', limit.amount),
                    ['half']: __('1/2 the items'),
                }[limit.type as DiscountOptions['limit']['type']])}
            </ListItem>}
            {hardLimit.isEnabled && <ListItem>
                <div className={'flex items-center space-x-1'}>

                    <span>
                        {__('Up to * off').split(/(\*)/).map((part, index) => {
                            // Every second element (index 1, 3, 5...) will be the captured asterisk
                            if (index % 2 === 1 && part === '*') {
                                return <span key={index}
                                             className="font-black text-gray-600">{renderCurrencyValue(hardLimit.amount)}</span>;
                            }
                            return part;
                        })}
                    </span>
                </div>
            </ListItem>}
        </ul>
    }),
}