import {FieldItem, FieldRow, FieldType} from "../fields";
import {CouponsPlus} from "../../globals";
import React from "react";
import {MultiSelectProps} from "../fields/MultiSelect";
//import {type CardType, type fieldMeta} from "../cards";
import {PartialDeep} from "type-fest";
import {ComponentMeta} from "../ComponentsMeta";
import {merge} from "lodash";
import {InclusionValueValidatorFields} from "../InclusionValueValidatorFields";

export type InclusionValueValidatorOptions<ExpectedValue = string> = {
    inclusionType: 'allowed' | 'forbidden' | 'allowed-except-forbidden',
    expectedValues: ExpectedValue[],
    excludedSubsetValues: string[], // optional only when supportsExcludingSubset is true
    enableExcludedSubsetValues: boolean, // optional only when supportsExcludingSubset is true
}

export type InclusionValueValidatorFieldsMeta = {
    excludedSubsetValues: fieldMeta<{ supportsExcludingSubset: boolean }>,
}
export const inclusionValueValidatorFieldsMap = (
    type: ComponentMeta['type'],
    id: ComponentMeta['id'],
    selectExtraFieldProps?: FieldItem<PartialDeep<MultiSelectProps<any>>, InclusionValueValidatorOptions>['fieldProps'],
    expectedValuesKey: string = 'expectedValues',
    selectExtraFieldOptions: Record<string, any> = {},
    fieldsBetween: FieldRow[] = [], // unused I believe, so deprecated
    supportedComponents?: {
        inclusionType?: boolean,
        expectedValues?: boolean,
    },
) => {
    supportedComponents = merge({inclusionType: true, expectedValues: true}, supportedComponents);
    // Lazy getter function to avoid circular dependency
    const getComponentMetaData = () => {
        return CouponsPlus.components[type][id] as CardType;
    };

    const getInclusionTypeField = () => {
        const componentMetaData = getComponentMetaData();
        // @ts-ignore
        return componentMetaData?.fields?.['inclusionType']?.meta?.extraLabels as PartialDeep<{
            allowed: {
                placeholder: string,
                aboveList: string
            },
            forbidden: {
                placeholder: string,
                aboveList: string
            }
        }>;
    };

    const getExcludedSubsetValuesField = () => {
        const componentMetaData = getComponentMetaData();
        return componentMetaData?.fields?.['excludedSubsetValues']?.meta?.extraLabels as PartialDeep<{
            allowed: {
                placeholder: string,
                aboveList: string
            },
        }>;
    };

    const getSupportsExcludingSubset = () => {
        const componentMetaData = getComponentMetaData();
        const meta = componentMetaData?.fields?.['excludedSubsetValues']?.meta;
        // @ts-ignore
        return meta?.supportsExcludingSubset || false;
    };

    return [
        [
            {
                id: 'inclusionType',
                renderType: FieldType.Custom,
                fieldProps: (options: InclusionValueValidatorOptions, onUpdate, {componentRuntimeData, field}) => {
                    const componentMetaData = getComponentMetaData();
                    const inclusionTypeField = getInclusionTypeField();
                    const expectedValuesMeta = componentMetaData?.fields?.[expectedValuesKey]?.meta;
                    const expectedValuesOptions = expectedValuesMeta?.__allowed || {};

                    return {
                        component: <InclusionValueValidatorFields
                            type={type}
                            id={id}
                            selectExtraFieldProps={selectExtraFieldProps}
                            selectExtraFieldOptions={selectExtraFieldOptions}
                            supportedComponents={supportedComponents}
                            options={options}
                            componentRuntimeData={componentRuntimeData}
                            onUpdate={onUpdate}
                            inclusionTypeLabels={inclusionTypeField}
                            expectedValuesKey={expectedValuesKey}
                            expectedValuesOptions={expectedValuesOptions}
                        />
                    }
                }
            }
        ],
        ...[/*supportedComponents.inclusionType && [
            {id: 'inclusionType', renderType: FieldType.Tab, fieldProps: {size: 'normal'}},
        ],
            ...fieldsBetween,
            supportedComponents.expectedValues && [
                {
                    id: expectedValuesKey,
                    renderType: FieldType.MultiSelect,
                    // merge here is probably terrible for performance (re-renders) but it will have to do for now
                    fieldProps: (options: InclusionValueValidatorOptions) => {
                        const inclusionTypeField = getInclusionTypeField();
                        return merge({
                                SelectSearchProps: {
                                    placeholder: () => {
                                        if (options.inclusionType === 'allowed') {
                                            return inclusionTypeField?.allowed?.placeholder || __('Search items to include...')
                                        }
                                        return inclusionTypeField?.forbidden?.placeholder || __('Search items to exclude...')
                                    },
                                },
                                SelectStateProps: {
                                    labels: {
                                        above: inclusionTypeField?.[options.inclusionType]?.aboveList
                                    },
                                    defaultItemOptions: {
                                        beforeLabel(): React.ReactNode {
                                            if (options.inclusionType === 'forbidden') {
                                                return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
                                                            fill="currentColor"
                                                            className="min-w-[18px] min-h-[18px] max-w-[18px] max-h-[18px] text-gray-250">
                                                    <path fillRule="evenodd"
                                                          d="m6.72 5.66 11.62 11.62A8.25 8.25 0 0 0 6.72 5.66Zm10.56 12.68L5.66 6.72a8.25 8.25 0 0 0 11.62 11.62ZM5.105 5.106c3.807-3.808 9.98-3.808 13.788 0 3.808 3.807 3.808 9.98 0 13.788-3.807 3.808-9.98 3.808-13.788 0-3.808-3.807-3.808-9.98 0-13.788Z"
                                                          clipRule="evenodd"/>
                                                </svg>

                                            }

                                            return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
                                                        fill="currentColor"
                                                        className="min-w-5 min-h-5 max-w-5 max-h-5 text-gray-250">
                                                <path fillRule="evenodd"
                                                      d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm13.36-1.814a.75.75 0 1 0-1.22-.872l-3.236 4.53L9.53 12.22a.75.75 0 0 0-1.06 1.06l2.25 2.25a.75.75 0 0 0 1.14-.094l3.75-5.25Z"
                                                      clipRule="evenodd"/>
                                            </svg>
                                        }
                                    },
                                }
                            },
                            (typeof selectExtraFieldProps === 'function' ? selectExtraFieldProps(options) : selectExtraFieldProps) || {}
                        );
                    },
                    fieldOptions: selectExtraFieldOptions
                } as FieldItem<MultiSelectProps<any>, InclusionValueValidatorOptions>,

            ],
            [
                {
                    id: 'enableExcludedSubsetValues',
                    wrap: Wrapped,
                    renderType: ({inclusionType, expectedValues, enableExcludedSubsetValues}) => {
                        const supportsExcludingSubset = getSupportsExcludingSubset();
                        return supportsExcludingSubset && inclusionType === 'allowed' && expectedValues.length && !enableExcludedSubsetValues && FieldType.Button;
                    },
                    fieldProps: {
                        children: __('Exclude items...'),
                        onClick: (updateField: UpdateField, onUpdate) => {
                            updateField(true)
                        }
                    }
                }
            ],
            [
                {
                    id: 'excludedSubsetValues',
                    title: __('Excluding items'),
                    renderType: ({inclusionType, excludedSubsetValues, enableExcludedSubsetValues}) => {
                        const supportsExcludingSubset = getSupportsExcludingSubset();
                        return (supportsExcludingSubset && enableExcludedSubsetValues && inclusionType === 'allowed' && FieldType.MultiSelect);
                    },
                    wrap: Wrapped,
                    fieldProps: (options: InclusionValueValidatorOptions) => {
                        const excludedSubsetValuesField = getExcludedSubsetValuesField();
                        return merge({
                                SelectSearchProps: {
                                    placeholder: () => {
                                        return excludedSubsetValuesField?.[options.inclusionType]?.placeholder
                                    },
                                },
                                SelectStateProps: {
                                    labels: {
                                        above: excludedSubsetValuesField?.[options.inclusionType]?.aboveList
                                    },
                                    defaultItemOptions: {
                                        beforeLabel(): React.ReactNode {
                                            return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
                                                        fill="currentColor"
                                                        className="min-w-[18px] min-h-[18px] max-w-[18px] max-h-[18px] text-gray-250">
                                                <path fillRule="evenodd"
                                                      d="m6.72 5.66 11.62 11.62A8.25 8.25 0 0 0 6.72 5.66Zm10.56 12.68L5.66 6.72a8.25 8.25 0 0 0 11.62 11.62ZM5.105 5.106c3.807-3.808 9.98-3.808 13.788 0 3.808 3.807 3.808 9.98 0 13.788-3.807 3.808-9.98 3.808-13.788 0-3.808-3.807-3.808-9.98 0-13.788Z"
                                                      clipRule="evenodd"/>
                                            </svg>
                                        }
                                    },
                                }
                            },
                            (typeof selectExtraFieldProps === 'function' ? selectExtraFieldProps(options) : selectExtraFieldProps) || {}
                        );
                    }
                } as FieldItem<MultiSelectProps<any>, InclusionValueValidatorOptions>,
            ],*/]
    ].filter(field => Array.isArray(field) ? field.length : true);
}