import type { VxeTableGridOptions } from '@vben/plugins/vxe-table';
import type { Recordable } from '@vben/types';

import { h } from 'vue';

import { IconifyIcon } from '@vben/icons';
import { $t, $te } from '@vben/locales';
import { setupVbenVxeTable, useVbenVxeGrid } from '@vben/plugins/vxe-table';
import { get, isFunction, isString } from '@vben/utils';

import {
  ElButton,
  ElImage,
  ElPopconfirm,
  ElTag,
  ElTooltip,
} from 'element-plus';

import { useVbenForm } from './form';

setupVbenVxeTable({
  configVxeTable: (vxeUI) => {
    vxeUI.setConfig({
      grid: {
        align: 'center',
        border: false,
        columnConfig: {
          resizable: true,
        },
        formConfig: {
          enabled: false,
        },
        minHeight: 180,
        proxyConfig: {
          autoLoad: true,
          response: {
            list: '',
            result: 'items',
            total: 'total',
          },
          showActionMsg: true,
          showResponseMsg: false,
        },
        round: true,
        showOverflow: true,
        size: 'medium',
      } as VxeTableGridOptions,
    });

    vxeUI.renderer.add('CellImage', {
      renderTableDefault(_renderOpts, params) {
        const { column, row } = params;
        const src = row[column.field];
        return h(ElImage, { previewSrcList: [src], src });
      },
    });

    vxeUI.renderer.add('CellLink', {
      renderTableDefault(renderOpts) {
        const { props } = renderOpts;
        return h(
          ElButton,
          { link: true, size: 'small' },
          { default: () => props?.text },
        );
      },
    });

    vxeUI.renderer.add('CellTag', {
      renderTableDefault({ options, props }, { column, row }) {
        const value = get(row, column.field);
        const tagOptions = options ?? [
          { label: $t('common.enabled'), type: 'success', value: true },
          { label: $t('common.disabled'), type: 'danger', value: false },
        ];
        const tagItem = tagOptions.find((item) => item.value === value);
        return h(
          ElTag,
          {
            type: tagItem?.type ?? 'info',
            ...props,
          },
          { default: () => tagItem?.label ?? value },
        );
      },
    });

    vxeUI.renderer.add('CellOperation', {
      renderTableDefault({ attrs, options, props }, { column, row }) {
        const defaultProps = { link: true, size: 'small', ...props };
        const align =
          column.align === 'center'
            ? 'center'
            : column.align === 'left'
              ? 'start'
              : 'end';
        const presets: Recordable<Recordable<any>> = {
          delete: {
            icon: 'ep:delete',
            text: $t('common.delete'),
            type: 'danger',
          },
          edit: {
            icon: 'ep:edit',
            text: $t('common.edit'),
            type: 'primary',
          },
        };
        const operations: Array<Recordable<any>> = (
          options || ['edit', 'delete']
        )
          .map((opt) => {
            if (isString(opt)) {
              return presets[opt]
                ? { code: opt, ...presets[opt], ...defaultProps }
                : {
                    code: opt,
                    text: $te(`common.${opt}`) ? $t(`common.${opt}`) : opt,
                    type: 'primary',
                    ...defaultProps,
                  };
            }

            const buttonConfig = {
              ...defaultProps,
              ...presets[opt.code],
              ...opt,
            };
            if (!buttonConfig.type && !presets[opt.code]) {
              buttonConfig.type = 'primary';
            }
            return buttonConfig;
          })
          .map((opt) => {
            const optBtn: Recordable<any> = {};
            Object.keys(opt).forEach((key) => {
              optBtn[key] = isFunction(opt[key]) ? opt[key](row) : opt[key];
            });
            return optBtn;
          })
          .filter((opt) => opt.show !== false);

        function renderBtn(opt: Recordable<any>, listen = true) {
          const { code, icon, text, ...btnProps } = opt;
          const buttonType =
            btnProps.type === 'danger'
              ? 'danger'
              : btnProps.type === 'primary'
                ? 'primary'
                : 'default';

          const button = h(
            ElButton,
            {
              ...btnProps,
              circle: !!icon,
              link: true,
              onClick: listen
                ? () =>
                    attrs?.onClick?.({
                      code,
                      row,
                    })
                : undefined,
              size: 'small',
              type: buttonType,
            },
            {
              default: () =>
                icon ? h(IconifyIcon, { class: 'size-4', icon }) : text,
            },
          );

          if (!icon) return button;

          return h(
            ElTooltip,
            {
              content: text,
              placement: 'top',
            },
            {
              default: () => button,
            },
          );
        }

        function renderConfirm(opt: Recordable<any>) {
          const { icon, text } = opt;

          const button = h(
            ElButton,
            {
              circle: !!icon,
              link: true,
              size: 'small',
              title: icon ? text : undefined,
              type: 'danger',
            },
            {
              default: () =>
                icon ? h(IconifyIcon, { class: 'size-4', icon }) : text,
            },
          );

          return h(
            ElPopconfirm,
            {
              cancelButtonText: $t('common.cancel'),
              confirmButtonText: $t('common.confirm'),
              confirmButtonType: 'danger',
              onConfirm: () => {
                attrs?.onClick?.({
                  code: opt.code,
                  row,
                });
              },
              title: $t('ui.actionTitle.delete', [attrs?.nameTitle || '']),
            },
            {
              default: () =>
                $t('ui.actionMessage.deleteConfirm', [
                  row[attrs?.nameField || 'name'],
                ]),
              reference: () => button,
            },
          );
        }

        const btns = operations.map((opt) =>
          opt.code === 'delete' ? renderConfirm(opt) : renderBtn(opt),
        );
        return h(
          'div',
          {
            class: 'flex table-operations',
            style: { justifyContent: align },
          },
          btns,
        );
      },
    });
  },
  useVbenForm,
});

export type OnActionClickParams<T = Recordable<any>> = {
  code: string;
  row: T;
};

export type OnActionClickFn<T = Recordable<any>> = (
  params: OnActionClickParams<T>,
) => void;

export { useVbenVxeGrid };

export type * from '@vben/plugins/vxe-table';
