text: import React, {useEffect, useState} from "react";
  import {AutoComplete, Button, Cascader, Col, Form, Input, message, Modal, Row, Space, Switch, Tag} from "antd";
  import {Select} from "antd/es";
  import {Store} from "rc-field-form/lib/interface"
  import {fetchWorkerZones} from "@/services/testplatform";
  import {WorkerZone} from "@/models/testplatform/types";
  import {fetchCollections} from "@/services/httptest";
  import {MinusCircleOutlined, PlusOutlined} from "@ant-design/icons/lib";
  import {fetchServiceMethodTree} from "@/services/grpctest";
  import {grpcAddrList} from "@/services/app";
  
  interface ModalCreatePipelineProps {
    visible: boolean
    onFinish: (fields: Store) => void
    onCancel: () => void
    env: string
    zoneCode: string
    appName: string
  }
  
  interface GrpcAddr {
    port: string,
    hosts: {
      env: string
      addr: string
    }[]
  }
  
  const formItemLayout = {
    labelCol: {
      xs: {span: 24},
      sm: {span: 4},
    },
    wrapperCol: {
      xs: {span: 24},
      sm: {span: 20},
    },
  };
  const formItemLayoutWithOutLabel = {
    wrapperCol: {
      xs: {span: 24, offset: 0},
      sm: {span: 20, offset: 4},
    },
  };
  
  
  export default function ModalCreatePipeline(props: ModalCreatePipelineProps) {
    const {visible, env, zoneCode, appName} = props
    const [form] = Form.useForm()
    const [workerZones, setWorkerZones] = useState<WorkerZone[]>([])
    const [httpCollections, setHttpCollections] = useState<{ id: number, name: string, test_cases: any[] }[]>([])
    const [grpcTestFlag, setGrpcTestFlag] = useState(false)
    const [services, setServices] = useState([])
    const [testCases, setTestCases] = useState({}) // service -> test cases
    const [grpcAddr, setGrpcAddr] = useState<GrpcAddr | null>(null)
  
    useEffect(() => {
      if (visible) {
        grpcAddrList({app_name: appName}).then(r => {
          setGrpcAddr(r.data)
        })
  
        fetchServiceMethodTree(appName).then(r => {
          if (r.code === 14000) return
          if (r.code !== 0) {
            message.error(r.msg)
            return
          }
  
          setServices(r.data)
        })
      }
    }, [visible])
  
    useEffect(() => {
      fetchWorkerZones().then(r => {
        if (r.code === 14000) return
        if (r.code !== 0) {
          message.error("加载 Worker 节点失败 " + r.msg)
          return
        }
  
        setWorkerZones(r.data)
      })
    }, [])
  
    useEffect(() => {
      form.setFieldsValue({
        env: env,
        zone_code: zoneCode === 'all' ? null : zoneCode,
        app_name: appName,
        unit_test: true,
        code_check: true
      })
  
      fetchCollections(appName).then(r => {
        if (r.code === 14000) return
        if (r.code !== 0) {
          message.error(r.msg)
          return
        }
  
        setHttpCollections(r.data.list || [])
      })
    }, [env, zoneCode, appName])
  
    const testCaseCascadeOptions = services?.map((item: any, index: number) => {
      return {
        value: item.id,
        label: item.name,
        children: item.methods?.map((method: any) => ({
          value: method.id,
          label: method.name,
          children: method.use_cases?.map((useCase: any) => ({
            value: useCase.id,
            label: useCase.name
          })) || []
        }))
      }
    }) || []
  
    return <Modal
      title={"创建 Pipeline"}
      visible={visible}
      onOk={() => form.submit()}
      onCancel={props.onCancel}
      width={grpcTestFlag ? "900px" : "500px"}
    >
      <Form
        form={form}
        onFinish={props.onFinish}
      >
  
        <Row gutter={15}>
  
          <Col span={grpcTestFlag ? 10 : 24}>
            <Form.Item label={"Env"} name={"env"}>
              <Input disabled/>
            </Form.Item>
  
            <Form.Item label={"App"} name={"app_name"}>
              <Input disabled/>
            </Form.Item>
  
            <Form.Item
              label={"名称"}
              name={"name"}
              rules={[
                {required: true, message: "请输入 Pipeline 名称"},
                {pattern: /^[a-zA-Z0-9_-]{4,32}$/, message: 'Pipeline名称只能为 a-zA-Z0-9_- 组合，长度为 4 - 32 位'}
              ]}
            >
              <Input/>
            </Form.Item>
  
            <Form.Item
              label={"代码分支"}
              name={"branch"}
              rules={[
                {required: true, message: '请输入代码分支'}
              ]}
            >
              <Input/>
            </Form.Item>
  
            <Form.Item
              label={"机房"} name={"zone_code"}
              rules={[
                {required: true, message: "请选择机房"}
              ]}
            >
              <Select disabled={zoneCode !== 'all'}>
                {workerZones.map((item, id) => <Select.Option key={id}
                                                              value={item.zone_code}>{item.zone_name}</Select.Option>)}
              </Select>
            </Form.Item>
  
            <Form.Item label={"Http测试集合(可选)"} name={"http_test_collection"}>
              <Select allowClear>
                {httpCollections.map((item, idx) => <Select.Option value={item.id} key={idx}>
                  {item.name}({item.test_cases.length}个用例)
                </Select.Option>)}
              </Select>
            </Form.Item>
  
            <Form.Item label={"单元测试"} name={"unit_test"} valuePropName={"checked"}>
              <Switch/>
            </Form.Item>
  
            <Form.Item label={"静态检查"} name={"code_check"} valuePropName={"checked"}>
              <Switch/>
            </Form.Item>
  
            <Form.Item label={"GRPC接口测试"}>
              <Switch onChange={val => {
                setGrpcTestFlag(val)
                form.setFieldsValue({
                  grpc_test_cases: val ? [{}] : []
                })
              }}/>
            </Form.Item>
          </Col>
  
          {/*GRPC 测试用例*/}
          {grpcTestFlag && <Col span={14}>
            <Form.Item label={"GRPC服务地址"} name={"grpc_test_addr"}>
              <AutoComplete placeholder={"1.2.3.4:1234"}>
                {grpcAddr && grpcAddr.hosts?.map((item, idx) => <AutoComplete.Option
                  value={item.addr + ':' + grpcAddr.port}>
                  <Tag>{item.env}</Tag> {item.addr} : {grpcAddr.port}
                </AutoComplete.Option>)}
              </AutoComplete>
            </Form.Item>
            <Form.List name={"grpc_test_cases"}>
              {(fields, {add, remove}) => {
                return <div>
                  {fields.map((field, index) => {
                    return <Form.Item
                      {...(index === 0 ? formItemLayout : formItemLayoutWithOutLabel)}
                      label={index === 0 ? 'GRPC用例' : ''}
                      key={field.key}
                    >
                      <Space>
                        <Form.Item
                          noStyle name={[field.name, "testcase"]}
                          rules={[
                            {required: true, message: '请选择用例'}
                          ]}
                        >
                          <Cascader options={testCaseCascadeOptions} style={{width: '400px'}}/>
                        </Form.Item>
  
                        <Form.Item noStyle>
                          {index > 0 && <MinusCircleOutlined
                            onClick={() => {
                              setTestCases({
                                ...testCases,
                                [field.name]: undefined
                              })
                              remove(field.name);
                            }}
                          />}
                        </Form.Item>
                      </Space>
                    </Form.Item>
                  })}
  
                  <Form.Item>
                    <Button
                      type="dashed"
                      onClick={() => {
                        add();
                      }}
                      block
                    >
                      <PlusOutlined/> 新增用例
                    </Button>
                  </Form.Item>
                </div>
              }}
            </Form.List>
          </Col>}
  
        </Row>
  
      </Form>
    </Modal>
  }
  