/*
 * @Author: 赵伟
 * @Date: 2024-04-16 13:58:08
 * @Description: 创建实验
 */
import PageTitle from '@/components/PageTitle';
import { AutoMLEnsembleClass, AutoMLTaskType, AutoMLType } from '@/enums';
import { addAutoMLReq, getAutoMLInfoReq, updateAutoMLReq } from '@/services/autoML';
import { convertEmptyStringToUndefined, parseJsonText, trimCharacter } from '@/utils';
import { safeInvoke } from '@/utils/functional';
import { to } from '@/utils/promise';
import { useLocation, useNavigate, useParams } from '@umijs/max';
import { App, Button, Form } from 'antd';
import { omit } from 'lodash';
import { useEffect } from 'react';
import BasicConfig from '../components/CreateForm/BasicConfig';
import DatasetConfig from '../components/CreateForm/DatasetConfig';
import ExecuteConfig from '../components/CreateForm/ExecuteConfig';
import TextExecuteConfig from '../components/CreateForm/TextExecuteConfig';
import TrialConfig from '../components/CreateForm/TrialConfig';
import VideoExecuteConfig from '../components/CreateForm/VideoExecuteConfig';
import { AutoMLData, FormData } from '../types';
import styles from './index.less';

function CreateAutoML() {
  const navigate = useNavigate();
  const [form] = Form.useForm();
  const { message } = App.useApp();
  const params = useParams();
  const id = safeInvoke(Number)(params.id);
  const { pathname } = useLocation();
  const isCopy = pathname.includes('copy');
  const type = Form.useWatch('type', form);

  useEffect(() => {
    // 获取服务详情
    const getAutoMLInfo = async (id: number) => {
      const [res] = await to(getAutoMLInfoReq({ id }));
      if (res && res.data) {
        const autoMLInfo: AutoMLData = res.data;
        const { name: name_str, description, type, param } = autoMLInfo;
        const paramObj = parseJsonText(param);
        const {
          include_classifier: include_classifier_str,
          include_feature_preprocessor: include_feature_preprocessor_str,
          include_regressor: include_regressor_str,
          exclude_classifier: exclude_classifier_str,
          exclude_feature_preprocessor: exclude_feature_preprocessor_str,
          exclude_regressor: exclude_regressor_str,
          metrics: metrics_str,
          ...rest
        } = paramObj;
        const include_classifier = include_classifier_str?.split(',').filter(Boolean);
        const include_feature_preprocessor = include_feature_preprocessor_str
          ?.split(',')
          .filter(Boolean);
        const include_regressor = include_regressor_str?.split(',').filter(Boolean);
        const exclude_classifier = exclude_classifier_str?.split(',').filter(Boolean);
        const exclude_feature_preprocessor = exclude_feature_preprocessor_str
          ?.split(',')
          .filter(Boolean);
        const exclude_regressor = exclude_regressor_str?.split(',').filter(Boolean);
        const metricsObj = safeInvoke(parseJsonText)(metrics_str) ?? {};
        const metrics = Object.entries(metricsObj).map(([key, value]) => ({
          name: key,
          value,
        }));
        const name = isCopy ? `${name_str}-copy` : name_str;

        const formData = {
          ...rest,
          include_classifier,
          include_feature_preprocessor,
          include_regressor,
          exclude_classifier,
          exclude_feature_preprocessor,
          exclude_regressor,
          metrics,
          name,
          description,
          type,
        };

        form.setFieldsValue(formData);
      }
    };

    // 编辑，复制
    if (id && !Number.isNaN(id)) {
      getAutoMLInfo(id);
    } else {
      // 新建，不设置 form 的 type 初始值，是为了编辑和复制的时候，form 跳动
      form.setFieldValue('type', AutoMLType.Table);
    }
  }, [id, form, isCopy]);

  // 创建、更新、复制实验
  const createExperiment = async (formData: FormData) => {
    const { name, description, type } = formData;
    const include_classifier = formData['include_classifier']?.join(',');
    const include_feature_preprocessor = formData['include_feature_preprocessor']?.join(',');
    const include_regressor = formData['include_regressor']?.join(',');
    const exclude_classifier = formData['exclude_classifier']?.join(',');
    const exclude_feature_preprocessor = formData['exclude_feature_preprocessor']?.join(',');
    const exclude_regressor = formData['exclude_regressor']?.join(',');
    const formMetrics = formData['metrics'];
    const metrics =
      formMetrics && Array.isArray(formMetrics) && formMetrics.length > 0
        ? formMetrics.reduce((acc, cur) => {
            acc[cur.name] = cur.value;
            return acc;
          }, {} as Record<string, number>)
        : undefined;

    const target_columns = trimCharacter(formData['target_columns'], ',');

    // 根据后台要求，修改表单数据
    const param = {
      ...omit(formData, ['name', 'description', 'type']),
      include_classifier: convertEmptyStringToUndefined(include_classifier),
      include_feature_preprocessor: convertEmptyStringToUndefined(include_feature_preprocessor),
      include_regressor: convertEmptyStringToUndefined(include_regressor),
      exclude_classifier: convertEmptyStringToUndefined(exclude_classifier),
      exclude_feature_preprocessor: convertEmptyStringToUndefined(exclude_feature_preprocessor),
      exclude_regressor: convertEmptyStringToUndefined(exclude_regressor),
      metrics: metrics ? JSON.stringify(metrics) : undefined,
      target_columns,
    };

    const object = {
      name,
      description,
      type,
      param: JSON.stringify(param),
    };

    const params =
      id && !isCopy
        ? {
            id: id,
            ...object,
          }
        : object;

    const request = id && !isCopy ? updateAutoMLReq : addAutoMLReq;
    const [res] = await to(request(params));
    if (res) {
      message.success('操作成功');
      navigate(-1);
    }
  };

  // 提交
  const handleSubmit = (values: FormData) => {
    createExperiment(values);
  };

  // 取消
  const cancel = () => {
    navigate(-1);
  };

  let buttonText = '新建';
  let title = '新建实验';
  if (id) {
    if (isCopy) {
      title = '复制实验';
      buttonText = '确定';
    } else {
      title = '编辑实验';
      buttonText = '更新';
    }
  }

  return (
    <div className={styles['create-automl']}>
      <PageTitle title={title}></PageTitle>
      <div className={styles['create-automl__content']}>
        <div>
          <Form
            name="create-automl"
            labelCol={{ flex: '160px' }}
            labelAlign="left"
            form={form}
            onFinish={handleSubmit}
            size="large"
            autoComplete="off"
            scrollToFirstError
            initialValues={{
              task_type: AutoMLTaskType.Classification,
              shuffle: false,
              ensemble_class: AutoMLEnsembleClass.Default,
              greater_is_better: true,
              ensemble_size: 50,
              ensemble_nbest: 50,
              max_models_on_disc: 50,
              memory_limit: 3072,
              per_run_time_limit: 600,
              time_left_for_this_task: 3600,
              resampling_strategy: 'holdout',
              test_size: 0.25,
              train_size: 0.67,
              seed: 1,
              is_validate: false,
              is_test: false,
            }}
          >
            <BasicConfig />

            {type === AutoMLType.Table ? (
              <>
                <ExecuteConfig />
                <TrialConfig />
                <DatasetConfig />
              </>
            ) : type === AutoMLType.Text ? (
              <TextExecuteConfig />
            ) : (
              <VideoExecuteConfig />
            )}

            <Form.Item wrapperCol={{ offset: 0, span: 16 }} style={{ marginTop: '40px' }}>
              <Button type="primary" htmlType="submit">
                {buttonText}
              </Button>
              <Button
                type="default"
                htmlType="button"
                onClick={cancel}
                style={{ marginLeft: '20px' }}
              >
                取消
              </Button>
            </Form.Item>
          </Form>
        </div>
      </div>
    </div>
  );
}

export default CreateAutoML;
