import type { FormKitFrameworkContext, FormKitTypeDefinition } from '@formkit/core';
import type { FormKitInputs } from '@formkit/inputs';
import { createSection, label, outer } from '@formkit/inputs';
import type { CascadeSelectEmitsOptions, CascadeSelectProps } from 'primevue/cascadeselect';
import PrimevueCascadeselect from 'primevue/cascadeselect';
import { defineComponent, markRaw, ref } from 'vue';
import { floatLabel } from '../sections/floatLabel';
import { messages } from '../sections/messages';
import { help } from '../sections/help';

// https://formkit.com/inputs/dropdown

type PrimevueSelectListeners = {
  'onUpdate:modelValue': CascadeSelectEmitsOptions['update:modelValue'];
  'onBlur': CascadeSelectEmitsOptions['blur'];
};

const SchemaComponent = defineComponent(
  (vueProps: { context: FormKitFrameworkContext }) => {
    const formkitContext = vueProps.context;
    const listeners: PrimevueSelectListeners = {
      'onUpdate:modelValue': (value: unknown) => {
        formkitContext.node.input(value);
      },
      'onBlur': async (e) => {
        setTimeout(
          () => formkitContext.handlers.blur.call(undefined, e as never),
          166, // 因为会触发两次。所以让blur事件延迟一点，可以考虑优化。（Cascadeselect好像没有这个问题）
        );
      },
    };
    const p_options = ref();
    const loading = ref(true);

    const loadOptions = async () => {
      try {
        let result;
        if (formkitContext.options instanceof Promise) {
          result = await formkitContext.options;
        } else {
          console.warn('未支持的 options 类型 :>> ', typeof formkitContext.options);
        }
        p_options.value = result;
      } catch (error) {
        console.error('Failed to load options:', error);
        p_options.value = [];
      } finally {
        loading.value = false;
      }
    };

    loadOptions(); // 立即加载options

    return () => {
      return (
        <PrimevueCascadeselect
          inputId={formkitContext.id}
          optionLabel={formkitContext.optionLabel as never}
          optionValue={formkitContext.optionValue as never}
          optionGroupChildren={(formkitContext.optionGroupChildren as never) || 'children'}
          optionGroupLabel={(formkitContext.optionGroupLabel as never) || (formkitContext.optionLabel as never)}
          loading={loading.value}
          options={p_options.value}
          invalid={formkitContext.state.invalid}
          fluid
          disabled={!!formkitContext.disabled}
          modelValue={formkitContext._value}
          {...listeners}
        />
      );
    };
  },
  // https://cn.vuejs.org/api/general#definecomponent
  // 目前仍然需要手动声明运行时的 props
  // 在将来，我们计划提供一个 Babel 插件，自动推断并注入运行时 props (就像在单文件组件中的 defineProps 一样)，以便省略运行时 props 的声明。
  {
    props: ['context'],
  },
);

const input = createSection('input', () => ({
  $cmp: markRaw(SchemaComponent) as never,
  bind: '$attrs',
  props: {
    context: '$node.context',
  },
}));

export const PCascadeSelect: FormKitTypeDefinition = {
  type: 'input',
  schema: outer(
    floatLabel(
      input(), //
      label('$label'),
    ),
    help('$help'),
    messages(),
  ),
  props: ['options', 'optionLabel', 'optionValue'],
  schemaMemoKey: '72psvunq45', // Math.random().toString(36).substring(2, 15)
};

type OptionsType = CascadeSelectProps['options'];

declare module '@formkit/inputs' {
  // https://formkit.com/essentials/custom-inputs#typescript-support
  interface FormKitInputProps<Props extends FormKitInputs<Props>> {
    PCascadeSelect: {
      type: 'PCascadeSelect';
      options: Promise<OptionsType>;
      optionLabel: string;
      optionValue: string;
    };
  }
}
