<script lang="ts" setup>
import type { Recordable } from '@vben/types';

import type { ApiConfig } from '../../form/types';

import { type PropType, reactive, ref } from 'vue';

import { useVbenModal } from '@vben/common-ui';
import { isFunction } from '@vben/utils';

import { Checkbox, message, Pagination } from 'ant-design-vue';

import { useVbenForm } from '#/adapter/form';
import { EnumApi, QueryApi } from '#/api';
import { requestClient } from '#/api/request';
import { get } from '#/utils';

import SelectCardItem from './select-card-item.vue';

defineOptions({
  name: 'SelectCard',
});

const props = defineProps({
  multiple: {
    type: Boolean as PropType<boolean>,
    default: true,
  },
  title: {
    type: String as PropType<string>,
    default: '选择数据',
  },
  showTree: {
    type: Boolean as PropType<boolean>,
    default: false,
  },
  immediate: {
    type: Boolean,
    default: true,
  },
});
const emit = defineEmits(['success']);
const cardData = ref<Recordable<any>[]>([]);

const state = reactive<{
  api: ApiConfig;
  config: {
    bgcolor: string;
    color: string;
    fillColor: string;
    type: string;
  };
  disabledIds: number[] | string[];
  fieldNames: Recordable<any>[];
  key: number | string;
  keyName: string;
  page: { pageIndex: number; pageSize: number; total: number };
  searchName: string;
  selectedIds: number[];
  selectedList: Recordable<any>[];
}>({
  page: {
    pageIndex: 1,
    pageSize: 9,
    total: 0,
  },
  selectedIds: [],
  selectedList: [],
  disabledIds: [],
  api: {
    type: 'none',
    method: 'get',
    params: {},
    result: 'items',
    url: null,
  },
  keyName: 'id',
  key: '',
  searchName: '',
  fieldNames: [
    { title: '名称', value: 'title', maxLength: 12 },
    { title: '电话', value: 'phone', maxLength: 8 },
  ],
  config: {
    type: 'none',
    fillColor: '#f1ecfe',
    bgcolor: '#f5f1fd',
    color: '#b389ff',
  },
});

const fetch = async () => {
  const api: any =
    typeof state.api.url === 'string' || !state.api.url
      ? (params: any) => {
          Object.assign(params, state.page);
          if (state.api.type === 'enum') {
            return EnumApi.getList(params);
          } else if (state.api.type === 'api') {
            return QueryApi.postOptions(params);
          } else
            return (requestClient as any)[state.api.method](
              state.api.url as any,
              state.api.method === 'get' ? { params } : params,
            );
        }
      : state.api.url;
  if (!api || !isFunction(api)) return;
  try {
    const res = await api(state.api.params);
    if (Array.isArray(res)) {
      cardData.value = res;
    } else {
      cardData.value = state.api.result ? get(res, state.api.result) : [];
      state.page.total = res.total || 0;
    }
  } catch (error) {
    console.warn(error);
  } finally {
    // setState({ loading: false });
  }
};

const [Form, { resetForm }] = useVbenForm({
  layout: 'horizontal',
  commonConfig: {
    componentProps: {
      class: 'w-full',
    },
  },
  schema: [
    {
      component: 'Input',
      componentProps: {
        placeholder: '请输入',
      },
      fieldName: 'keyword',
      label: '关键字',
    },
  ],
  submitButtonOptions: {
    content: '查询',
  },
  wrapperClass: 'grid-cols-2',
  handleSubmit: async (values: Record<string, any>) => {
    if (state.searchName) {
      state.page.pageIndex = 1;
      state.api.params[state.searchName] = values.keyword;
      await fetch();
    }
  },
  handleReset: async () => {
    resetForm();
    state.page.pageIndex = 1;
    state.api.params[state.searchName] = '';
    await fetch();
  },
});

const [Modal, { close, setState, getData }] = useVbenModal({
  onConfirm: async () => {
    try {
      close();
      emit('success', {
        key: state.key,
        ids: [...state.selectedIds],
        list: [...state.selectedList],
      });
    } catch {
      message.error('操作失败');
    } finally {
      setState({ confirmLoading: false });
    }
  },
  onOpenChange: async (isOpen: boolean) => {
    if (isOpen) {
      setState({ loading: true });
      const data = getData<Record<string, any>>();
      state.key = data.baseData.key;
      state.searchName = data.baseData.searchName || '';
      state.selectedIds = data.baseData.selectedIds || [];
      state.disabledIds = data.baseData.disabledIds || [];
      state.fieldNames = data.baseData.fieldNames || [];
      Object.assign(state.api, data.baseData.api);
      Object.assign(state.config, data.baseData.config);
      state.page.pageIndex = 1;
      await fetch();
      setState({ loading: false });
    }
  },
});

const hancelClick = (item: any) => {
  if (
    state.disabledIds &&
    Array.isArray(state.disabledIds) &&
    state.disabledIds.includes(item[state.keyName] as never)
  ) {
    return;
  }

  if (props.multiple) {
    if (state.selectedIds.includes(item[state.keyName])) {
      state.selectedIds.splice(
        state.selectedIds.indexOf(item[state.keyName]),
        1,
      );
      state.selectedList.splice(
        state.selectedList.findIndex(
          (ele) => ele[state.keyName] === item[state.keyName],
        ),
        1,
      );
    } else {
      state.selectedIds.push(item[state.keyName]);
      state.selectedList.push(item);
    }
  } else {
    if (state.selectedIds.includes(item[state.keyName])) {
      state.selectedIds = [];
      state.selectedList = [];
    } else {
      state.selectedIds = [item[state.keyName]];
    }
  }
};

const handelPageChange = async (pageIndex: number) => {
  setState({ loading: true });
  state.page.pageIndex = pageIndex;
  await fetch();
  setState({ loading: false });
};
</script>

<template>
  <Modal :title="`选择${title}`" class="w-[1000px]">
    <div class="select-card flex justify-between">
      <div class="ml-4 flex-1">
        <div class="select-card-header">
          <div class="flex justify-between">
            <div class="text-foreground text-lg font-semibold">
              {{ title }}列表
            </div>
          </div>
          <Form class="mt-4" />
        </div>
        <div class="select-card-body">
          <SelectCardItem
            v-for="(item, index) in cardData"
            :key="index"
            :class="
              state.selectedIds.includes(item[state.keyName])
                ? 'picked'
                : 'not-picked'
            "
            :config="state.config"
            :disabled="
              state.disabledIds &&
              state.disabledIds.includes(item[state.keyName] as never)
                ? true
                : false
            "
            :field-names="state.fieldNames"
            :model="item"
            @click="hancelClick(item)"
          >
            <template #check>
              <Checkbox
                :checked="state.selectedIds.includes(item[state.keyName])"
                size="small"
              />
            </template>
          </SelectCardItem>
          <div class="select-card-pagination">
            <Pagination
              v-model:current="state.page.pageIndex"
              :page-size="state.page.pageSize"
              :total="state.page.total"
              show-less-items
              show-quick-jumper
              size="small"
              @change="handelPageChange"
            />
          </div>
        </div>
      </div>
    </div>
  </Modal>
</template>

<style lang="less" scoped>
.select-card {
  display: flex;
  height: 500px;
  margin: 10px;
  overflow: auto;
  position: relative;

  &-body {
    display: flex;
    flex-wrap: wrap;
    padding: 10px 0;
    overflow-y: auto;
  }

  &-pagination {
    // width: 100%;
    position: absolute;
    text-align: right;
    bottom: 10px;
    right: 10px;
  }
}
</style>
