import React from 'react';
import {__, CouponsPlus} from '../../globals';
import {CardRenderer} from "../CardRenderers";
import {ComponentMeta} from "../ComponentsMeta";
import {QuantityMeta} from "./Quantity";
import {ComponentAction, ComponentRuntimeData} from "../components";
import {IncompatibleWithAnyProducts} from "../IncompatibleWithAnyProducts";
import {inclusionValueValidatorFieldsMap, InclusionValueValidatorOptions} from "./InclusionValueValidator";
import {SelectOption} from "../fields/MultiSelectSearch";
import {usingTestableOptions} from "./CardHelpers";
import {CartItemSecondaryValueProps} from "../CardItemSecondaryValue";
import {CategoriesOptions} from "./Categories";
import {iconWithClassName} from "../IconWithClassName";
import {fieldsCacheContainer} from "../FieldsCache";
import classNames from "classnames";
import {ColorOptionWithCustomTint, request} from "../Color";
import {colors} from "../Colors";
import {merge} from "lodash";

const type = CouponsPlus?.components?.filters?.Products?.type;
export type ProductsOptions = Pick<InclusionValueValidatorOptions, 'inclusionType'> & {
    mode: 'short', // this dashboard currently only supports short (there's also 'classic' but it's not supported by this component)
    ids: string[]
}

export type ProductMetaData = {
    id: number,
    parent_id?: number, // for variations this is the base product id
    name: string,
    parent_name?: string, // for variations this is the base product name
    price: number
    regular_price: number,
    sale_price: number,
    type: 'simple' | 'grouped' | 'external' | 'variable' | 'variation',
    isVariable: boolean,
    isVariation: boolean,
    typeLabel: string,
    sku: string,
    image_url?: string,
    attributes?: { name: string, value: string }[],
}

export type CustomProductOptionValue = {
    type: 'product',
    option: ProductMetaData
}

const onlyHasQuantityFilter = (filters: ComponentRuntimeData[]) => {
    return filters.length === 1 && filters[0].type === QuantityMeta.id;
}
export const CustomProductsFieldLabel = ({
                                             label,
                                             id,
                                             value,
                                             size = 'normal',
                                             color,
                                             showType = true
                                         }: SelectOption<CustomProductOptionValue> & {
    size?: 'normal' | 'small',
    showType?: boolean | 'variation'
} & Partial<ColorOptionWithCustomTint>) => {
    if (!value) {
        return __('Could not load product')
    }
    const {option: {name, type, parent_name, image_url, attributes, typeLabel}} = value;

    const nameToUse = type === 'variation' ? parent_name || name : name;
    label = label || nameToUse || id;
    //alright here lets first check if this type is a variable product, add an extra label containing "any variations"
    let topExtraLabel = '';
    const isVariation = type === 'variation';

    if (showType) {
        if (type === 'variable') {
            topExtraLabel = /*showType !== 'variation' &&*/ __('Any Variations')
        } else {
            if (isVariation) {
            } else if (showType !== 'variation') {
                topExtraLabel = typeLabel
            }
        }
    }

    return <div className="space-y-1">
        <div className="flex items-center space-x-2">
            {image_url && <img src={image_url} alt={label} className={classNames('rounded-5 border-none', {
                'w-6 h-6': size === 'normal',
                'w-5 h-5': size === 'small',
            })}/>}
            <span>{label}</span>
            {topExtraLabel && <span className="text-smaller-1 opacity-60 font-medium">{topExtraLabel}</span>}
            {attributes?.length && <div className="flex items-center space-x-1">
                {attributes.map((({name, value}) => (value && <div className="flex flex-col">
                    {false && <span className="text-smaller-3 text-gray-350">{name}:</span>}<span
                    className={classNames('inline-flex px-1 h-5  rounded-5 items-center', {
                        'text-smaller-1': size === 'normal',
                        'text-smaller-2': size === 'small',
                        'text-gray-450 bg-gray-150': !color,
                        [color ? `${request(color).background(20)} ${request(color)?.get('text.light.primary')}` : 'no-custom-color']: !!color,
                    })}>{value}
                        </span>
                </div>)))}
            </div>}
        </div>
    </div>
};
export const ProductsFieldProps = (extraProps: Record<any, any> | undefined) => {
    const ogProps = {
        SelectStateProps: {
            defaultItemOptions: {
                Label: CustomProductsFieldLabel
            }
        },
        SelectSearchProps: {
            MultiSelectSearchItemProps: {
                options: {
                    Label: CustomProductsFieldLabel
                }
            },
            customOptionValueResolver: (option) => ({
                type: 'product',
                option
            }),
        }
    };
    if (extraProps === undefined) {
        // let's avoid an extra unnecessary merge (may prevent re-renders)
        return ogProps
    }
    return merge(ogProps, extraProps);
}
export const ProductsMeta: ComponentMeta = IncompatibleWithAnyProducts({
    id: type,
    type: 'filters',
    category: 'common',
    priority: 10,
    supportsCustomTitleForSuggestedScopes: (suggestedScope) => ['bogo', 'item_discounts', 'cart_discounts'].includes(suggestedScope),
    description: ({suggestedScope}) => {
        if (suggestedScope === 'bogo') {
            return __('Select the products that the customer must buy to be eligible for the BOGO offer.')
        } else if (suggestedScope === 'item_discounts') {
            return __('Select the products that will be discounted.')
        } else if (suggestedScope === 'cart_discounts') {
            return __('Select the products that will trigger the cart discount when purchased.')
        }
    },
    prename: (filters) => onlyHasQuantityFilter(filters) ? 'No Specific' : 'No Excluded',
    action: (filters) => onlyHasQuantityFilter(filters) ? ComponentAction.Select : ComponentAction.Exclude,
    icon: iconWithClassName(({className, context}) => {
        if (context === 'card') {
            // solid
            return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                <path d="M12.378 1.602a.75.75 0 0 0-.756 0L3 6.632l9 5.25 9-5.25-8.622-5.03ZM21.75 7.93l-9 5.25v9l8.628-5.032a.75.75 0 0 0 .372-.648V7.93ZM11.25 22.18v-9l-9-5.25v8.57a.75.75 0 0 0 .372.648l8.628 5.033Z" />
            </svg>
        }
        // outline
        return <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor">
            <path strokeLinecap="round" strokeLinejoin="round" d="m21 7.5-9-5.25L3 7.5m18 0-9 5.25m9-5.25v9l-9 5.25M3 7.5l9 5.25M3 7.5v9l9 5.25m0-9v9" />
        </svg>
    }),
    fieldsMap: [
        ...inclusionValueValidatorFieldsMap(
        'filters',
        type,
        options => ProductsFieldProps(),
        'ids'
    )],
})

type ProductsTestableData = { inclusionType: 'allowed' | 'forbidden' }
export const ProductsRenderer: CardRenderer = {
    type: type,
    prefix: "[Specific] *",
    example: __('Organic Cotton Crew Neck T-Shirt (any size, or only large, etc.)'),
    icon: ProductsMeta.icon!,
    AboveComputedValue: usingTestableOptions<CategoriesOptions>(({inclusionType, expectedValues}, {id, context}) => {
        // @ts-ignore
        return {
            classNames: '---pl-[10px] --min-w-20',
            label: inclusionType === 'forbidden' ? __('Excluding') : undefined,
        } as CartItemSecondaryValueProps

    }),
    ComputedValue: usingTestableOptions<ProductsOptions>(({inclusionType, ids}, {color}) => {
        color = color || colors.purple
        return <div className="space-y-1">
            {ids.map((id) => {
                const selectedProductOption: SelectOption<CustomProductOptionValue> | undefined = fieldsCacheContainer.get('products').get(id) as SelectOption<CustomProductOptionValue> | undefined

                if (!selectedProductOption) {
                    return '?'
                }

                // will change ts in the future
                let color = colors.purple

                return <CustomProductsFieldLabel size={'small'} {...selectedProductOption} color={color}
                                                 showType={'variation'}/>
            })}
            {ids.length === 0 &&
                <span
                    className={`text-base ${request(color)?.text?.(60) ?? colors.purple.text(60)}`}>{__('Select Products')}</span>}
        </div>
    }),
}