// Libs
// -----------------------------------------------------------------------------
import React, { FC, Fragment, useState, useEffect } from 'react';
import {
  Form,
  Input,
  Select,
  Row,
  Col,
  Alert,
  AlertProps,
  Checkbox,
  InputNumber,
} from 'antd';
import { Rule } from 'antd/lib/form';

// App
// -----------------------------------------------------------------------------
import { CommonActionFormProps } from './CommonActionFormProps';
import { useCorrelationRulesTemplateMessages } from '../../i18n';
import { useStore } from 'stores/StoreProvider';
import { RootStore } from 'stores/RootStore';
import {
  TypeFirewallStatus,
  TypeFirewallFieldValues,
  TypeFirewallDevice,
} from 'types/default';
import { firewallOptionsToSelectOptions } from './helpers';
import { openNotificationError } from 'components/Messages';
import { makeListForSelect } from 'components/helpers';

const MAX_DESCRIPTION_LENGTH = 256;

export const FirewallActionForm: FC<CommonActionFormProps> = ({
  form,
  name,
  isDisabled,
  cardSize,
}) => {
  // Списки возможных значений полей для выбранного фаервола
  const [fieldValues, setFieldValues] =
    useState<TypeFirewallFieldValues | null>(null);
  // Статус выбранного фаервола
  const [status, setStatus] = useState<TypeFirewallStatus | null>(null);
  // Статус сетевого запроса
  const [isLoading, setIsLoading] = useState<boolean>(false);

  // Корневой стор данных
  const rootStore: RootStore = useStore();
  const firewallStore = rootStore.firewallStore;

  // Объект локализации
  const locale = useCorrelationRulesTemplateMessages();
  const fieldStrings = locale.actionsRuleMessage.blockMessages.fireWallMessage;

  // Общие правила для полей
  const fieldRules: Array<Rule> = [
    { required: true, message: locale.formValidationMessages.emptyField },
  ];

  // Id выбранного фаервола
  const currentArmaIfId: string | null =
    Form.useWatch(['actions_json', name, 'armaif'], form) ?? null;

  useEffect(() => {
    const run = async (): Promise<void> => {
      // Если выбран фаервол
      if (currentArmaIfId) {
        // Найти фаервол в сторе (он точно найдется)
        const currentArmaIf = firewallStore.list.find(
          (f) => f.id.toString() === currentArmaIfId,
        ) as TypeFirewallDevice;

        // Заполнить форму данными фаервола
        form.setFieldValue(
          ['actions_json', name, 'sensor', 'ip'],
          currentArmaIf?.ip,
        );
        form.setFieldValue(['actions_json', name, 'sensor', 'scheme'], 'https');
        form.setFieldValue(
          ['actions_json', name, 'sensor', 'key'],
          currentArmaIf?.key,
        );
        form.setFieldValue(
          ['actions_json', name, 'sensor', 'secret'],
          currentArmaIf?.secret,
        );

        try {
          // Получить текущий статус фаервола
          setIsLoading(true);
          setStatus(null);
          const currentStatus = await firewallStore.getStatus(
            parseInt(currentArmaIfId),
          );
          setStatus(currentStatus);

          // Если фаервол онлайн
          if (currentStatus.status === 'online') {
            // Запросить у фаервола возможные значения полей формы
            // вместе с умолчаниями
            const currentFieldValues = await firewallStore.getRuleFields(
              parseInt(currentArmaIfId),
            );

            // Задать форме возможные значения полей (селектов)
            setFieldValues(currentFieldValues);
          }
        } catch {
          setStatus(null);
          setFieldValues(null);
          openNotificationError({
            messageTitle: fieldStrings.other.firewallConnectionError,
          });
        } finally {
          setIsLoading(false);
        }
      }
    };
    run();
  }, [firewallStore, currentArmaIfId, form, name]);

  // Фаервол офлайн или статус недоступен
  const isOffline = status === null || status.status === 'offline';

  // Настройки уведомления о статусе фаервола
  let alertProps: AlertProps | null = null;
  const commonAlertProps: AlertProps = {
    showIcon: true,
    style: { marginBottom: '24px' },
  };
  if (!currentArmaIfId) {
    alertProps = {
      ...commonAlertProps,
      type: 'info',
      message: fieldStrings.other.pleaseSelectFirewall,
    };
  } else if (isLoading) {
    alertProps = {
      ...commonAlertProps,
      type: 'info',
      message: fieldStrings.other.connectingToTheFirewall,
    };
  } else if (status?.status === 'online') {
    alertProps = {
      ...commonAlertProps,
      type: 'success',
      message: fieldStrings.other.firewallIsOnline,
    };
  } else if (status?.status === 'offline') {
    alertProps = {
      ...commonAlertProps,
      type: 'error',
      message: fieldStrings.other.firewallIsOffline,
    };
  }

  return (
    <Fragment>
      <Form.Item name={[name, 'type']} hidden>
        <Input type="hidden" disabled={isDisabled} />
      </Form.Item>

      <Form.Item name={[name, 'gateway']} hidden>
        <Input type="hidden" disabled={isDisabled} />
      </Form.Item>

      <Form.Item name={[name, 'sensor', 'ip']} hidden>
        <Input type="hidden" disabled={isDisabled} />
      </Form.Item>

      <Form.Item name={[name, 'sensor', 'scheme']} hidden>
        <Input type="hidden" disabled={isDisabled} />
      </Form.Item>

      <Form.Item name={[name, 'sensor', 'key']} hidden>
        <Input type="hidden" disabled={isDisabled} />
      </Form.Item>

      <Form.Item name={[name, 'sensor', 'secret']} hidden>
        <Input type="hidden" disabled={isDisabled} />
      </Form.Item>

      <Row gutter={[32, 0]}>
        <Col span={24}>
          <Form.Item
            name={[name, 'armaif']}
            label={fieldStrings.armaif.title}
            validateStatus={status?.status === 'online' ? 'success' : 'error'}
            help={
              status?.status !== 'online'
                ? fieldStrings.other.firewallShouldBeOnline
                : null
            }
          >
            <Select
              disabled={isDisabled || isLoading}
              loading={isLoading}
              options={makeListForSelect(firewallStore.list)}
            />
          </Form.Item>
        </Col>
      </Row>

      {alertProps && (
        <Row gutter={[32, 0]}>
          <Col span={24}>
            <Alert {...alertProps} />
          </Col>
        </Row>
      )}

      <Row gutter={[32, 0]}>
        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item
            name={[name, 'enabled']}
            extra={fieldStrings.enabled.extra}
            valuePropName="checked"
          >
            <Checkbox disabled={isDisabled || isOffline}>
              {fieldStrings.enabled.title}
            </Checkbox>
          </Form.Item>
        </Col>

        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item name={[name, 'quick']} valuePropName="checked">
            <Checkbox disabled={isDisabled || isOffline}>
              {fieldStrings.quick.title}
            </Checkbox>
          </Form.Item>
        </Col>

        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item
            name={[name, 'log']}
            extra={fieldStrings.log.extra}
            valuePropName="checked"
          >
            <Checkbox disabled={isDisabled || isOffline}>
              {fieldStrings.log.title}
            </Checkbox>
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={[32, 0]}>
        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item
            name={[name, 'interface']}
            label={fieldStrings.interface.title}
            extra={fieldStrings.interface.extra}
            rules={fieldRules}
          >
            <Select
              disabled={isDisabled || isOffline}
              options={firewallOptionsToSelectOptions(
                fieldValues?.rule.interface,
              )}
              mode="multiple"
            />
          </Form.Item>
        </Col>

        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item
            name={[name, 'direction']}
            label={fieldStrings.direction.title}
            extra={fieldStrings.direction.extra}
            rules={fieldRules}
          >
            <Select
              disabled={isDisabled || isOffline}
              options={firewallOptionsToSelectOptions(
                fieldValues?.rule.direction,
              )}
            />
          </Form.Item>
        </Col>

        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item
            name={[name, 'sequence']}
            label={fieldStrings.sequence.title}
            extra={fieldStrings.sequence.extra}
            rules={fieldRules}
          >
            <InputNumber
              disabled={isDisabled || isOffline}
              style={{ width: '100%' }}
              stringMode
            />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={[32, 0]}>
        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item
            name={[name, 'action']}
            label={fieldStrings.action.title}
            extra={fieldStrings.action.extra}
            rules={fieldRules}
          >
            <Select
              disabled={isDisabled || isOffline}
              options={firewallOptionsToSelectOptions(fieldValues?.rule.action)}
            />
          </Form.Item>
        </Col>

        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item
            name={[name, 'ipprotocol']}
            label={fieldStrings.ipprotocol.title}
            rules={fieldRules}
          >
            <Select
              disabled={isDisabled || isOffline}
              options={firewallOptionsToSelectOptions(
                fieldValues?.rule.ipprotocol,
              )}
            />
          </Form.Item>
        </Col>

        <Col span={cardSize === 'large' ? 8 : 24}>
          <Form.Item
            name={[name, 'protocol']}
            label={fieldStrings.enabled.title}
            rules={fieldRules}
          >
            <Select
              disabled={isDisabled || isOffline}
              options={firewallOptionsToSelectOptions(
                fieldValues?.rule.protocol,
              )}
            />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={[32, 0]}>
        <Col span={cardSize === 'large' ? 12 : 24}>
          <Form.Item
            name={[name, 'source_net']}
            label={fieldStrings.source_net.title}
            rules={fieldRules}
          >
            <Input disabled={isDisabled || isOffline} />
          </Form.Item>
        </Col>

        <Col span={cardSize === 'large' ? 12 : 24}>
          <Form.Item
            name={[name, 'source_port']}
            label={fieldStrings.source_port.title}
          >
            <Input disabled={isDisabled || isOffline} />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={[32, 0]}>
        <Col span={24}>
          <Form.Item name={[name, 'source_not']} valuePropName="checked">
            <Checkbox disabled={isDisabled || isOffline}>
              {fieldStrings.source_not.title}
            </Checkbox>
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={[32, 0]}>
        <Col span={cardSize === 'large' ? 12 : 24}>
          <Form.Item
            name={[name, 'destination_net']}
            label={fieldStrings.destination_net.title}
            rules={fieldRules}
          >
            <Input disabled={isDisabled || isOffline} />
          </Form.Item>
        </Col>

        <Col span={cardSize === 'large' ? 12 : 24}>
          <Form.Item
            name={[name, 'destination_port']}
            label={fieldStrings.destination_port.title}
          >
            <Input disabled={isDisabled || isOffline} />
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={[32, 0]}>
        <Col span={24}>
          <Form.Item name={[name, 'destination_not']} valuePropName="checked">
            <Checkbox disabled={isDisabled || isOffline}>
              {fieldStrings.destination_not.title}
            </Checkbox>
          </Form.Item>
        </Col>
      </Row>

      <Row gutter={[32, 0]}>
        <Col span={24}>
          <Form.Item
            name={[name, 'description']}
            label={fieldStrings.description.title}
            extra={fieldStrings.description.extra(MAX_DESCRIPTION_LENGTH)}
            rules={[{ max: MAX_DESCRIPTION_LENGTH }]}
          >
            <Input.TextArea
              disabled={isDisabled || isOffline}
              rows={5}
              maxLength={MAX_DESCRIPTION_LENGTH}
            ></Input.TextArea>
          </Form.Item>
        </Col>
      </Row>
    </Fragment>
  );
};
