/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, Col, Form, Input, InputNumber, Row, Select, Switch } from 'antd';
import type { FormInstance } from 'antd/es/form';
import React, { useState } from 'react';
import { useIntl } from 'umi';

type Props = {
  form: FormInstance;
  schema: Record<string, any> | undefined;
};

type PolicyProps = 'local' | 'redis' | 'redis-cluster';

type FormsProps = {
  schema: Record<string, any> | undefined;
};

const FORM_ITEM_LAYOUT = {
  labelCol: {
    span: 7,
  },
  wrapperCol: {
    span: 10,
  },
};

const FORM_ITEM_WITHOUT_LABEL = {
  wrapperCol: {
    span: 10,
    offset: 7,
  },
};

const removeBtnStyle = {
  marginLeft: 20,
  display: 'flex',
  alignItems: 'center',
};

const RedisForm: React.FC<FormsProps> = ({ schema }) => {
  const { formatMessage } = useIntl();
  const properties = schema?.properties;

  return (
    <>
      <Form.Item
        label="redis_host"
        name="redis_host"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.redis_host.tooltip' })}
        rules={[
          {
            required: true,
            message: `${formatMessage({ id: 'component.global.pleaseEnter' })} redis_host`,
          },
          {
            min: properties.redis_host.minLength,
            message: formatMessage({
              id: 'component.pluginForm.limit-count.atLeast2Characters.rule',
            }),
          },
        ]}
        validateTrigger={['onChange', 'onBlur', 'onClick']}
      >
        <Input />
      </Form.Item>
      <Form.Item
        initialValue={properties.redis_port.default}
        label="redis_port"
        name="redis_port"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.redis_port.tooltip' })}
      >
        <InputNumber
          min={properties.redis_port.minimum}
          max={properties.redis_port.maximum || 65535}
        />
      </Form.Item>
      <Form.Item
        label="redis_password"
        name="redis_password"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.redis_password.tooltip' })}
        rules={[
          {
            required: true,
            message: `${formatMessage({ id: 'component.global.pleaseEnter' })} redis_password`,
          },
        ]}
        validateTrigger={['onChange', 'onBlur', 'onClick']}
      >
        <Input />
      </Form.Item>
      <Form.Item
        initialValue={properties.redis_database.default}
        label="redis_database"
        name="redis_database"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.redis_database.tooltip' })}
      >
        <InputNumber min={properties.redis_database.minimum} />
      </Form.Item>
      <Form.Item
        initialValue={properties.redis_timeout.default}
        label="redis_timeout"
        name="redis_timeout"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.redis_timeout.tooltip' })}
      >
        <InputNumber min={properties.redis_timeout.minimum} />
      </Form.Item>
    </>
  );
};

const RedisClusterForm: React.FC<FormsProps> = ({ schema }) => {
  const { formatMessage } = useIntl();
  const properties = schema?.properties;
  const nodesPro = properties.redis_cluster_nodes;
  const { maxLength, minLength } = nodesPro.items;
  const nodesInit = Array(nodesPro.minItems).join('.').split('.');

  return (
    <>
      <Form.Item
        label="redis_cluster_name"
        name="redis_cluster_name"
        validateTrigger={['onChange', 'onBlur', 'onClick']}
        rules={[
          {
            required: true,
            message: `${formatMessage({ id: 'component.global.pleaseEnter' })} redis_cluster_name`,
          },
        ]}
        tooltip={formatMessage({
          id: 'component.pluginForm.limit-count.redis_cluster_name.tooltip',
        })}
      >
        <Input />
      </Form.Item>
      <Form.List name="redis_cluster_nodes" initialValue={nodesInit}>
        {(fields, { add, remove }) => {
          return (
            <div>
              <Form.Item
                label="redis_cluster_nodes"
                style={{ marginBottom: 0 }}
                required
                tooltip={formatMessage({
                  id: 'component.pluginForm.limit-count.redis_cluster_nodes.tooltip',
                })}
              >
                {fields.map((field, index) => (
                  <Row style={{ marginBottom: 10 }} gutter={16} key={index}>
                    <Col>
                      <Form.Item
                        {...field}
                        noStyle
                        validateTrigger={['onChange', 'onBlur', 'onClick']}
                        rules={[
                          {
                            required: true,
                            message: `${formatMessage({
                              id: 'component.global.pleaseEnter',
                            })} redis_cluster_node`,
                          },
                          {
                            min: 2,
                            message: formatMessage({
                              id: 'component.pluginForm.limit-count.atLeast2Characters.rule',
                            }),
                          },
                        ]}
                      >
                        <Input />
                      </Form.Item>
                    </Col>
                    <Col style={{ ...removeBtnStyle, marginLeft: -10 }}>
                      {fields.length > minLength && (
                        <MinusCircleOutlined
                          className="dynamic-delete-button"
                          onClick={() => {
                            remove(field.name);
                          }}
                        />
                      )}
                    </Col>
                  </Row>
                ))}
              </Form.Item>

              <Form.Item {...FORM_ITEM_WITHOUT_LABEL}>
                {fields.length < maxLength && (
                  <Button
                    type="dashed"
                    onClick={() => {
                      add();
                    }}
                  >
                    <PlusOutlined /> {formatMessage({ id: 'component.global.add' })}
                  </Button>
                )}
              </Form.Item>
            </div>
          );
        }}
      </Form.List>
      <Form.Item
        label="redis_password"
        name="redis_password"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.redis_password.tooltip' })}
      >
        <Input />
      </Form.Item>
      <Form.Item
        initialValue={properties.redis_timeout.default}
        label="redis_timeout"
        name="redis_timeout"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.redis_timeout.tooltip' })}
      >
        <InputNumber min={properties.redis_timeout.minimum} />
      </Form.Item>
    </>
  );
};

const LimitCount: React.FC<Props> = ({ form, schema }) => {
  const properties = schema?.properties;
  const [policy, setPoicy] = useState<PolicyProps>(properties.policy.default);
  const { formatMessage } = useIntl();
  const redisSchema = schema?.then;
  const redisClusterSchema = schema?.else.then;

  return (
    <Form form={form} {...FORM_ITEM_LAYOUT}>
      <Form.Item
        label="count"
        name="count"
        rules={[
          {
            required: true,
            message: `${formatMessage({ id: 'component.global.pleaseEnter' })} count`,
          },
        ]}
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.count.tooltip' })}
        validateTrigger={['onChange', 'onBlur', 'onClick']}
      >
        <InputNumber min={properties.count.exclusiveMinimum} />
      </Form.Item>
      <Form.Item
        label="time_window"
        name="time_window"
        rules={[
          {
            required: true,
            message: `${formatMessage({ id: 'component.global.pleaseEnter' })} time_window`,
          },
        ]}
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.time_window.tooltip' })}
        validateTrigger={['onChange', 'onBlur', 'onClick']}
      >
        <InputNumber min={properties.time_window.exclusiveMinimum} />
      </Form.Item>
      <Form.Item
        label="key_type"
        name="key_type"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.key_type.tooltip' })}
        initialValue={properties.key_type.default}
      >
        <Select>
          {properties.key_type.enum.map((item: string) => {
            return (
              <Select.Option value={item} key={item}>
                {item}
              </Select.Option>
            );
          })}
        </Select>
      </Form.Item>
      <Form.Item
        label="key"
        name="key"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.key.tooltip' })}
      >
        <Input min={1} />
      </Form.Item>
      <Form.Item
        initialValue={properties.rejected_code.default}
        label="rejected_code"
        name="rejected_code"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.rejected_code.tooltip' })}
      >
        <InputNumber
          min={properties.rejected_code.minimum}
          max={properties.rejected_code.maximum}
        />
      </Form.Item>
      <Form.Item
        label="rejected_msg"
        name="rejected_msg"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-req.rejected_msg.tooltip' })}
      >
        <Input />
      </Form.Item>
      <Form.Item
        initialValue={policy}
        label="policy"
        name="policy"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.policy.tooltip' })}
      >
        <Select
          onChange={(e: PolicyProps) => {
            setPoicy(e);
          }}
        >
          {properties.policy.enum.map((item: string) => (
            <Select.Option value={item} key={item}>
              {item}
            </Select.Option>
          ))}
        </Select>
      </Form.Item>
      <Form.Item
        label="group"
        name="group"
        tooltip={formatMessage({ id: 'component.pluginForm.limit-count.key.tooltip' })}
      >
        <Input />
      </Form.Item>
      <Form.Item
        initialValue={properties.allow_degradation.default}
        label="allow_degradation"
        name="allow_degradation"
        tooltip={formatMessage({
          id: 'component.pluginForm.limit-count.allow_degradation.tooltip',
        })}
        valuePropName="checked"
      >
        <Switch />
      </Form.Item>
      <Form.Item
        initialValue={properties.show_limit_quota_header.default}
        label="show_limit_quota_header"
        name="show_limit_quota_header"
        tooltip={formatMessage({
          id: 'component.pluginForm.limit-count.show_limit_quota_header.tooltip',
        })}
        valuePropName="checked"
      >
        <Switch />
      </Form.Item>
      <Form.Item
        shouldUpdate={(prev, next) => prev.policy !== next.policy}
        style={{ display: 'none' }}
      >
        {() => {
          setPoicy(form.getFieldValue('policy'));
        }}
      </Form.Item>
      {Boolean(policy === 'redis') && <RedisForm schema={redisSchema} />}
      {Boolean(policy === 'redis-cluster') && <RedisClusterForm schema={redisClusterSchema} />}
    </Form>
  );
};

export default LimitCount;
