/*
 * @Author: 赵伟
 * @Date: 2024-04-16 13:58:08
 * @Description: 创建模型部署
 */
import KFIcon from '@/components/KFIcon';
import PageTitle from '@/components/PageTitle';
import ResourceSelect, {
  requiredValidator,
  type ParameterInputObject,
} from '@/components/ResourceSelect';
import SubAreaTitle from '@/components/SubAreaTitle';
import { CommonTabKeys } from '@/enums';
import { useComputingResource } from '@/hooks/resource';
import { ResourceSelectorType } from '@/pages/Pipeline/components/ResourceSelectorModal';
import {
  createModelDeploymentReq,
  restartModelDeploymentReq,
  updateModelDeploymentReq,
} from '@/services/modelDeployment';
import { camelCaseToUnderscore, underscoreToCamelCase } from '@/utils';
import { to } from '@/utils/promise';
import {
  getSessionStorageItem,
  modelDeploymentInfoKey,
  removeSessionStorageItem,
} from '@/utils/sessionStorage';
import { modalConfirm } from '@/utils/ui';
import { useNavigate } from '@umijs/max';
import { App, Button, Col, Flex, Form, Input, Row, Select } from 'antd';
import { omit, pick } from 'lodash';
import { useEffect, useState } from 'react';
import { ModelDeploymentData, ModelDeploymentOperationType } from '../types';
import styles from './index.less';

// 表单数据
export type FormData = {
  serviceName: string; // 服务名称
  description: string; // 描述
  model: ParameterInputObject; // 模型
  image: ParameterInputObject; // 镜像
  resource: string; // 资源规格
  replicas: string; // 副本数量
  modelPath: string; // 模型路径
  env: { key: string; value: string }[]; // 环境变量
};

function ModelDeploymentCreate() {
  const navigate = useNavigate();
  const [form] = Form.useForm();
  const [resourceStandardList, filterResourceStandard] = useComputingResource();
  const [operationType, setOperationType] = useState(ModelDeploymentOperationType.Create);
  const [modelDeploymentInfo, setModelDeploymentInfo] = useState<ModelDeploymentData | undefined>(
    undefined,
  );
  const { message } = App.useApp();

  useEffect(() => {
    const res = getSessionStorageItem(modelDeploymentInfoKey, true);
    if (res) {
      setOperationType(res.operationType);
      setModelDeploymentInfo(res);
      const formData = underscoreToCamelCase(res) as FormData;
      form.setFieldsValue(formData);
    }
    return () => {
      removeSessionStorageItem(modelDeploymentInfoKey);
    };
  }, []);

  // 创建
  const createModelDeployment = async (formData: FormData) => {
    const envList = formData['env'] ?? [];
    const image = formData['image'];
    const model = formData['model'];
    const env = envList.reduce((acc, cur) => {
      acc[cur.key] = cur.value;
      return acc;
    }, {} as Record<string, string>);

    // 根据后台要求，修改表单数据
    const object = camelCaseToUnderscore({
      ...omit(formData, ['replicas', 'env', 'image', 'model']),
      replicas: Number(formData.replicas),
      env,
      image: image.value,
      model: pick(model, ['id', 'version', 'path', 'showValue']),
    });

    const params =
      operationType === ModelDeploymentOperationType.Create
        ? object
        : {
            ...pick(modelDeploymentInfo, ['service_id', 'service_ins_id']),
            update_model: {
              ...pick(object, ['description', 'env', 'replicas', 'resource', 'image']),
            },
          };

    let request = createModelDeploymentReq;
    if (operationType === ModelDeploymentOperationType.Restart) {
      request = restartModelDeploymentReq;
    } else if (operationType === ModelDeploymentOperationType.Update) {
      request = updateModelDeploymentReq;
    }
    const [res] = await to(request(params));
    if (res) {
      message.success('操作成功');
      navigate(-1);
    }
  };

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

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

  const disabled = operationType !== ModelDeploymentOperationType.Create;
  let buttonText = '新建';
  if (operationType === ModelDeploymentOperationType.Update) {
    buttonText = '更新';
  } else if (operationType === ModelDeploymentOperationType.Restart) {
    buttonText = '重启';
  }

  return (
    <div className={styles['model-deployment-create']}>
      <PageTitle title="创建推理服务"></PageTitle>
      <div className={styles['model-deployment-create__content']}>
        <div>
          <Form
            name="model-deployment-create"
            labelCol={{ flex: '100px' }}
            labelAlign="left"
            form={form}
            initialValues={{ upload_type: CommonTabKeys.Public }}
            onFinish={handleSubmit}
            size="large"
            autoComplete="off"
          >
            <SubAreaTitle
              title="基本信息"
              image={require('@/assets/img/mirror-basic.png')}
              style={{ marginBottom: '26px' }}
            ></SubAreaTitle>
            <Row gutter={8}>
              <Col span={10}>
                <Form.Item
                  label="服务名称"
                  name="serviceName"
                  rules={[
                    {
                      required: true,
                      message: '请输入服务名称',
                    },
                  ]}
                >
                  <Input
                    placeholder="请输入服务名称"
                    disabled={disabled}
                    maxLength={30}
                    showCount
                    allowClear
                  />
                </Form.Item>
              </Col>
            </Row>
            <Row gutter={8}>
              <Col span={20}>
                <Form.Item
                  label="描　　述"
                  name="description"
                  rules={[
                    {
                      required: true,
                      message: '请输入描述',
                    },
                  ]}
                >
                  <Input.TextArea
                    autoSize={{ minRows: 2, maxRows: 6 }}
                    placeholder="请输入描述，最长128字符"
                    maxLength={128}
                    showCount
                    allowClear
                  />
                </Form.Item>
              </Col>
            </Row>
            <SubAreaTitle
              title="部署构建"
              image={require('@/assets/img/model-deployment.png')}
              style={{ marginTop: '20px', marginBottom: '24px' }}
            ></SubAreaTitle>
            <Row gutter={8}>
              <Col span={10}>
                <Form.Item
                  label="选择模型"
                  name="model"
                  rules={[
                    {
                      validator: requiredValidator,
                      message: '请选择模型',
                    },
                  ]}
                  required
                >
                  <ResourceSelect
                    type={ResourceSelectorType.Model}
                    placeholder="请选择模型"
                    disabled={disabled}
                    canInput={false}
                    size="large"
                  />
                </Form.Item>
              </Col>
            </Row>
            <Row gutter={8}>
              <Col span={10}>
                <Form.Item
                  label="选择镜像"
                  name="image"
                  rules={[
                    {
                      validator: requiredValidator,
                      message: '请选择镜像',
                    },
                  ]}
                  required
                >
                  <ResourceSelect
                    type={ResourceSelectorType.Mirror}
                    placeholder="请选择镜像"
                    canInput={false}
                    size="large"
                  />
                </Form.Item>
              </Col>
            </Row>
            <Row gutter={8}>
              <Col span={10}>
                <Form.Item
                  label="资源规格"
                  name="resource"
                  rules={[
                    {
                      required: true,
                      message: '请选择资源规格',
                    },
                  ]}
                >
                  <Select
                    showSearch
                    placeholder="请选择资源规格"
                    filterOption={filterResourceStandard}
                    options={resourceStandardList}
                    fieldNames={{
                      label: 'description',
                      value: 'standard',
                    }}
                  />
                </Form.Item>
              </Col>
            </Row>
            <Row gutter={8}>
              <Col span={10}>
                <Form.Item
                  label="副本数量"
                  name="replicas"
                  rules={[
                    {
                      required: true,
                      message: '请输入副本数量',
                    },
                    {
                      pattern: /^[1-9]\d*$/,
                      message: '副本数量必须是正整数',
                    },
                  ]}
                >
                  <Input placeholder="请输入副本数量" allowClear />
                </Form.Item>
              </Col>
            </Row>

            <Row gutter={8}>
              <Col span={10}>
                <Form.Item
                  label="挂载路径"
                  name="modelPath"
                  rules={[
                    {
                      required: true,
                      message: '请输入模型挂载路径',
                    },
                  ]}
                >
                  <Input
                    placeholder="请输入模型挂载路径"
                    disabled={disabled}
                    maxLength={64}
                    showCount
                    allowClear
                  />
                </Form.Item>
              </Col>
            </Row>

            <Form.List name="env">
              {(fields, { add, remove }) => (
                <>
                  <Row gutter={8}>
                    <Col span={10}>
                      <Form.Item label="环境变量">
                        <Button type="link" style={{ padding: '0' }} onClick={() => add()}>
                          添加环境变量
                        </Button>
                      </Form.Item>
                    </Col>
                  </Row>
                  {fields.map(({ key, name, ...restField }) => (
                    <Flex key={key} align="center" gap="0 8px" style={{ width: '50%' }}>
                      <Form.Item
                        {...restField}
                        name={[name, 'key']}
                        style={{ flex: 1 }}
                        rules={[{ required: true, message: '请输入变量名' }]}
                      >
                        <Input placeholder="请输入变量名" />
                      </Form.Item>
                      <span style={{ marginBottom: '24px' }}>=</span>
                      <Form.Item
                        {...restField}
                        name={[name, 'value']}
                        style={{ flex: 1 }}
                        rules={[{ required: true, message: '请输入变量值' }]}
                      >
                        <Input placeholder="请输入变量值" />
                      </Form.Item>
                      <Button
                        type="link"
                        style={{ marginBottom: '24px' }}
                        icon={<KFIcon type="icon-shanchu" font={16} />}
                        onClick={() => {
                          modalConfirm({
                            content: '是否确认删除?',
                            onOk: () => {
                              remove(name);
                            },
                          });
                        }}
                      ></Button>
                    </Flex>
                  ))}
                </>
              )}
            </Form.List>

            <Form.Item wrapperCol={{ offset: 0, span: 16 }}>
              <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 ModelDeploymentCreate;
