<script setup lang="ts">
import type { FormInstance } from 'element-plus';

import type { BotInfo } from '@easyflow/types';

import type {
  ActionButton,
  CardPrimaryAction,
} from '#/components/page/CardList.vue';

import { computed, markRaw, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router';

import { EasyFlowFormModal } from '@easyflow/common-ui';
import { $t } from '@easyflow/locales';

import { Delete, Edit, Plus, Promotion, Setting } from '@element-plus/icons-vue';
import {
  ElForm,
  ElFormItem,
  ElInput,
  ElInputNumber,
  ElMessage,
  ElMessageBox,
  ElTag,
} from 'element-plus';
import { tryit } from 'radash';

import {
  submitBotDeleteApproval,
  submitBotOfflineApproval,
  submitBotPublishApproval,
} from '#/api';
import { api } from '#/api/request';
import defaultAvatar from '#/assets/ai/bot/defaultBotAvatar.png';
import HeaderSearch from '#/components/headerSearch/HeaderSearch.vue';
import CardList from '#/components/page/CardList.vue';
import PageData from '#/components/page/PageData.vue';
import PageSide from '#/components/page/PageSide.vue';
import {
  canAiResourceDelete,
  canAiResourceOffline,
  canAiResourcePublish,
  canAiResourceRepublish,
  isAiResourceApprovalPending,
  resolveAiResourceDisplayStatus,
} from '#/views/ai/shared/publish-status';
import { useDictStore } from '#/store';

import Modal from './modal.vue';

interface FieldDefinition {
  // 字段名称
  prop: string;
  // 字段标签
  label: string;
  // 字段类型：input, number, select, radio, checkbox, switch, date, datetime
  type?: 'input' | 'number';
  // 是否必填
  required?: boolean;
  // 占位符
  placeholder?: string;
}

onMounted(() => {
  initDict();
  getSideList();
});

const router = useRouter();
const pageDataRef = ref();
const modalRef = ref<InstanceType<typeof Modal>>();
const dictStore = useDictStore();

// 操作按钮配置
const headerButtons = [
  {
    key: 'create',
    text: `${$t('button.create')}${$t('bot.chatAssistant')}`,
    icon: markRaw(Plus),
    type: 'primary',
    data: { action: 'create' },
    permission: '/api/v1/documentCollection/save',
  },
];
function resolveNavTitle(row: BotInfo) {
  return (row as Record<string, any>)?.title || row?.name || '';
}
const primaryAction: CardPrimaryAction = {
  icon: Setting,
  text: $t('button.setting'),
  onClick(row: BotInfo) {
    router.push({
      path: `/ai/bots/setting/${row.id}`,
      query: {
        pageKey: '/ai/bots',
        navTitle: resolveNavTitle(row),
      },
    });
  },
};

const actions: ActionButton[] = [
  {
    icon: Edit,
    text: $t('button.edit'),
    placement: 'inline',
    onClick(row: BotInfo) {
      modalRef.value?.open('edit', row);
    },
  },
  {
    icon: Promotion,
    text: (row: BotInfo) =>
      canAiResourceRepublish(row.displayPublishStatus, row.publishStatus)
        ? $t('button.republish')
        : $t('button.publish'),
    permission: '/api/v1/bot/save',
    placement: 'inline',
    visible: (row: BotInfo) =>
      canAiResourcePublish(row.displayPublishStatus, row.publishStatus) ||
      canAiResourceRepublish(row.displayPublishStatus, row.publishStatus),
    onClick(row: BotInfo) {
      handlePublishAction(row);
    },
  },
  {
    icon: Promotion,
    text: $t('button.offline'),
    permission: '/api/v1/bot/save',
    placement: 'menu',
    visible: (row: BotInfo) => canAiResourceOffline(row.displayPublishStatus, row.publishStatus),
    onClick(row: BotInfo) {
      handleOfflineAction(row);
    },
  },
  {
    icon: Delete,
    text: $t('button.delete'),
    tone: 'danger',
    permission: '/api/v1/bot/remove',
    placement: 'menu',
    visible: (row: BotInfo) => canAiResourceDelete(row.displayPublishStatus, row.publishStatus),
    onClick(row: BotInfo) {
      handleSubmitDeleteApproval(row);
    },
  },
];

function isRepublishAction(bot: BotInfo) {
  return canAiResourceRepublish(bot.displayPublishStatus, bot.publishStatus);
}

const handlePublishAction = async (bot: BotInfo) => {
  if (
    isAiResourceApprovalPending(bot.displayPublishStatus, bot.publishStatus)
  ) {
    ElMessage.warning($t('bot.publishPendingHint'));
    return;
  }
  try {
    await ElMessageBox.confirm(
      isRepublishAction(bot)
        ? $t('bot.submitRepublishApprovalConfirm')
        : $t('bot.submitPublishApprovalConfirm'),
      $t('message.noticeTitle'),
      {
        confirmButtonText: $t('button.confirm'),
        cancelButtonText: $t('button.cancel'),
        type: 'info',
      },
    );
  } catch {
    return;
  }
  const res = await submitBotPublishApproval(String(bot.id));
  if (res.errorCode === 0) {
    ElMessage.success(res.message || $t('message.saveOkMessage'));
    pageDataRef.value?.reload?.();
  }
};
const handleOfflineAction = async (bot: BotInfo) => {
  if (
    isAiResourceApprovalPending(bot.displayPublishStatus, bot.publishStatus)
  ) {
    ElMessage.warning($t('bot.publishPendingHint'));
    return;
  }
  try {
    await ElMessageBox.confirm(
      $t('bot.submitOfflineApprovalConfirm'),
      $t('message.noticeTitle'),
      {
        confirmButtonText: $t('button.confirm'),
        cancelButtonText: $t('button.cancel'),
        type: 'warning',
      },
    );
  } catch {
    return;
  }
  const res = await submitBotOfflineApproval(String(bot.id));
  if (res.errorCode === 0) {
    ElMessage.success(res.message || $t('message.saveOkMessage'));
    pageDataRef.value?.reload?.();
  }
};
const handleSubmitDeleteApproval = async (bot: BotInfo) => {
  if (
    isAiResourceApprovalPending(bot.displayPublishStatus, bot.publishStatus)
  ) {
    ElMessage.warning($t('bot.deletePendingHint'));
    return;
  }
  try {
    await ElMessageBox.confirm(
      $t('bot.submitDeleteApprovalConfirm'),
      $t('message.noticeTitle'),
      {
        confirmButtonText: $t('button.confirm'),
        cancelButtonText: $t('button.cancel'),
        type: 'warning',
      },
    );
  } catch {
    return;
  }
  const res = await submitBotDeleteApproval(String(bot.id));
  if (res.errorCode === 0) {
    ElMessage.success(res.message || $t('message.saveOkMessage'));
    pageDataRef.value?.reload?.();
  }
};
function resolvePublishStatusMetaByInstance(
  displayPublishStatus?: string,
  publishStatus?: string,
) {
  switch (resolveAiResourceDisplayStatus(displayPublishStatus, publishStatus)) {
    case 'PUBLISHED':
      return {
        label: $t('bot.publishStatusPublished'),
        type: 'success' as const,
      };
    case 'PUBLISH_PENDING':
      return {
        label: $t('bot.publishStatusPublishPending'),
        type: 'warning' as const,
      };
    case 'OFFLINE_PENDING':
      return {
        label: $t('bot.publishStatusOfflinePending'),
        type: 'warning' as const,
      };
    case 'OFFLINE':
      return {
        label: $t('bot.publishStatusOffline'),
        type: 'info' as const,
      };
    case 'DELETE_PENDING':
      return {
        label: $t('bot.publishStatusDeletePending'),
        type: 'danger' as const,
      };
    default:
      return {
        label: $t('bot.publishStatusDraft'),
        type: 'info' as const,
      };
  }
}

const handleSearch = (params: string) => {
  pageDataRef.value.setQuery({ title: params, isQueryOr: true });
};
const handleButtonClick = () => {
  modalRef.value?.open('create');
};

const fieldDefinitions = ref<FieldDefinition[]>([
  {
    prop: 'categoryName',
    label: $t('aiWorkflowCategory.categoryName'),
    type: 'input',
    required: true,
    placeholder: $t('aiWorkflowCategory.categoryName'),
  },
  {
    prop: 'sortNo',
    label: $t('aiWorkflowCategory.sortNo'),
    type: 'number',
    required: false,
    placeholder: $t('aiWorkflowCategory.sortNo'),
  },
]);

const formData = ref<any>({});
const dialogVisible = ref(false);
const formRef = ref<FormInstance>();
const saveLoading = ref(false);
const sideList = ref<any[]>([]);
const controlBtns = [
  {
    icon: Edit,
    label: $t('button.edit'),
    onClick(row: any) {
      showControlDialog(row);
    },
  },
  {
    type: 'danger',
    icon: Delete,
    label: $t('button.delete'),
    onClick(row: any) {
      removeCategory(row);
    },
  },
];
const footerButton = {
  icon: Plus,
  label: $t('button.add'),
  onClick() {
    showControlDialog({});
  },
};

const formRules = computed(() => {
  const rules: Record<string, any[]> = {};
  fieldDefinitions.value.forEach((field) => {
    const fieldRules = [];
    if (field.required) {
      fieldRules.push({
        required: true,
        message: `${$t('message.required')}`,
        trigger: 'blur',
      });
    }
    if (fieldRules.length > 0) {
      rules[field.prop] = fieldRules;
    }
  });
  return rules;
});
function initDict() {
  dictStore.fetchDictionary('dataStatus');
}
function changeCategory(category: any) {
  pageDataRef.value.setQuery({ categoryId: category.id });
}
function showControlDialog(item: any) {
  formRef.value?.resetFields();
  formData.value = { ...item };
  dialogVisible.value = true;
}
function removeCategory(row: any) {
  ElMessageBox.confirm($t('message.deleteAlert'), $t('message.noticeTitle'), {
    confirmButtonText: $t('message.ok'),
    cancelButtonText: $t('message.cancel'),
    type: 'warning',
    beforeClose: (action, instance, done) => {
      if (action === 'confirm') {
        instance.confirmButtonLoading = true;
        api
          .post('/api/v1/botCategory/remove', { id: row.id })
          .then((res) => {
            instance.confirmButtonLoading = false;
            if (res.errorCode === 0) {
              ElMessage.success(res.message);
              done();
              getSideList();
            }
          })
          .catch(() => {
            instance.confirmButtonLoading = false;
          });
      } else {
        done();
      }
    },
  }).catch(() => {});
}
function handleSubmit() {
  formRef.value?.validate((valid) => {
    if (valid) {
      saveLoading.value = true;
      const url = formData.value.id
        ? '/api/v1/botCategory/update'
        : '/api/v1/botCategory/save';
      api.post(url, formData.value).then((res) => {
        saveLoading.value = false;
        if (res.errorCode === 0) {
          ElMessage.success(res.message);
          dialogVisible.value = false;
          getSideList();
        }
      });
    }
  });
}
const getSideList = async () => {
  const [, res] = await tryit(api.get)('/api/v1/botCategory/visibleList', {
    params: { sortKey: 'sortNo', sortType: 'asc' },
  });

  if (res && res.errorCode === 0) {
    sideList.value = [
      {
        id: '',
        categoryName: $t('common.allCategories'),
      },
      ...res.data,
    ];
  }
};
</script>

<template>
  <div class="flex h-full flex-col gap-6 p-6">
    <HeaderSearch
      :buttons="headerButtons"
      @search="handleSearch"
      @button-click="handleButtonClick"
    />
    <div class="flex flex-1 gap-6">
      <PageSide
        label-key="categoryName"
        value-key="id"
        :menus="sideList"
        :control-btns="controlBtns"
        :footer-button="footerButton"
        @change="changeCategory"
      />
      <div class="h-[calc(100vh-192px)] flex-1 overflow-auto">
        <PageData
          ref="pageDataRef"
          page-url="/api/v1/bot/page"
          :page-sizes="[12, 18, 24]"
          :page-size="12"
        >
          <template #default="{ pageList }">
            <CardList
              :default-icon="defaultAvatar"
              :data="pageList"
              :primary-action="primaryAction"
              :actions="actions"
            >
              <template #corner="{ item }">
                <ElTag
                  size="small"
                  effect="plain"
                  round
                  :type="resolvePublishStatusMetaByInstance(item.displayPublishStatus, item.publishStatus).type"
                >
                  {{ resolvePublishStatusMetaByInstance(item.displayPublishStatus, item.publishStatus).label }}
                </ElTag>
              </template>
            </CardList>
          </template>
        </PageData>
      </div>
    </div>
    <!-- 创建&编辑Bot弹窗 -->
    <Modal ref="modalRef" @success="pageDataRef.setQuery({})" />

    <EasyFlowFormModal
      v-model:open="dialogVisible"
      :closable="!saveLoading"
      :title="formData.id ? `${$t('button.edit')}` : `${$t('button.add')}`"
      :confirm-loading="saveLoading"
      :confirm-text="$t('button.confirm')"
      :submitting="saveLoading"
      @confirm="handleSubmit"
    >
      <ElForm
        ref="formRef"
        :model="formData"
        :rules="formRules"
        label-position="top"
        class="easyflow-modal-form easyflow-modal-form--compact"
      >
        <!-- 动态生成表单项 -->
        <ElFormItem
          v-for="field in fieldDefinitions"
          :key="field.prop"
          :label="field.label"
          :prop="field.prop"
        >
          <ElInput
            v-if="!field.type || field.type === 'input'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder"
          />
          <ElInputNumber
            v-else-if="field.type === 'number'"
            v-model="formData[field.prop]"
            :placeholder="field.placeholder"
            style="width: 100%"
          />
        </ElFormItem>
      </ElForm>
    </EasyFlowFormModal>
  </div>
</template>
